blob: 6fd5c07362ec216c3c47a988a145539a63b9f88f [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;
Amith Yamasani742a6712011-05-04 14:49:28 -070078import android.content.pm.UserInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070079import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040080import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.content.res.Configuration;
82import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070083import android.net.Proxy;
84import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.net.Uri;
86import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080087import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070089import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080090import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080092import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.FileUtils;
94import android.os.Handler;
95import android.os.IBinder;
96import android.os.IPermissionController;
97import android.os.Looper;
98import android.os.Message;
99import android.os.Parcel;
100import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700102import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.os.RemoteException;
104import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700105import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.os.SystemClock;
107import android.os.SystemProperties;
Amith Yamasani742a6712011-05-04 14:49:28 -0700108import android.os.UserId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.util.EventLog;
Dianne Hackborn905577f2011-09-07 18:31:28 -0700111import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800112import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800113import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.util.PrintWriterPrinter;
115import android.util.SparseArray;
Amith Yamasani742a6712011-05-04 14:49:28 -0700116import android.util.SparseIntArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700117import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import android.view.Gravity;
119import android.view.LayoutInflater;
120import android.view.View;
121import android.view.WindowManager;
122import android.view.WindowManagerPolicy;
123
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.BufferedInputStream;
125import java.io.BufferedOutputStream;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700126import java.io.BufferedReader;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700127import java.io.DataInputStream;
128import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.File;
130import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700131import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700133import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200134import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800135import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136import java.io.PrintWriter;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700137import java.io.StringWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138import java.lang.IllegalStateException;
139import java.lang.ref.WeakReference;
140import java.util.ArrayList;
Amith Yamasani742a6712011-05-04 14:49:28 -0700141import java.util.Collection;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700142import java.util.Collections;
143import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144import java.util.HashMap;
145import java.util.HashSet;
146import java.util.Iterator;
147import java.util.List;
148import java.util.Locale;
149import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700150import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700151import java.util.concurrent.atomic.AtomicBoolean;
152import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700154public final class ActivityManagerService extends ActivityManagerNative
155 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
Amith Yamasani742a6712011-05-04 14:49:28 -0700156 private static final String USER_DATA_DIR = "/data/user/";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final String TAG = "ActivityManager";
Amith Yamasani742a6712011-05-04 14:49:28 -0700158 static final String TAG_MU = "ActivityManagerServiceMU";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400160 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_SWITCH = localLOGV || false;
162 static final boolean DEBUG_TASKS = localLOGV || false;
163 static final boolean DEBUG_PAUSE = localLOGV || false;
164 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
165 static final boolean DEBUG_TRANSITION = localLOGV || false;
166 static final boolean DEBUG_BROADCAST = localLOGV || false;
Christopher Tatef46723b2012-01-26 14:19:24 -0800167 static final boolean DEBUG_BACKGROUND_BROADCAST = DEBUG_BROADCAST || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700168 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700170 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 static final boolean DEBUG_VISBILITY = localLOGV || false;
172 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700173 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800174 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700176 static final boolean DEBUG_RESULTS = localLOGV || false;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -0700177 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700178 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700179 static final boolean DEBUG_POWER = localLOGV || false;
180 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
Amith Yamasani742a6712011-05-04 14:49:28 -0700181 static final boolean DEBUG_MU = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 static final boolean VALIDATE_TOKENS = false;
183 static final boolean SHOW_ACTIVITY_START_TIME = true;
184
185 // Control over CPU and battery monitoring.
186 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
187 static final boolean MONITOR_CPU_USAGE = true;
188 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
189 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
190 static final boolean MONITOR_THREAD_CPU_USAGE = false;
191
Dianne Hackborn1655be42009-05-08 14:29:01 -0700192 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700193 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700194
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800195 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 // Maximum number of recent tasks that we can remember.
198 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700199
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700200 // Amount of time after a call to stopAppSwitches() during which we will
201 // prevent further untrusted switches from happening.
202 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203
204 // How long we wait for a launched process to attach to the activity manager
205 // before we decide it's never going to come up for real.
206 static final int PROC_START_TIMEOUT = 10*1000;
207
Jeff Brown3f9dd282011-07-08 20:02:19 -0700208 // How long we wait for a launched process to attach to the activity manager
209 // before we decide it's never going to come up for real, when the process was
210 // started with a wrapper for instrumentation (such as Valgrind) because it
211 // could take much longer than usual.
212 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 // How long to wait after going idle before forcing apps to GC.
215 static final int GC_TIMEOUT = 5*1000;
216
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700217 // The minimum amount of time between successive GC requests for a process.
218 static final int GC_MIN_INTERVAL = 60*1000;
219
Dianne Hackborn287952c2010-09-22 22:34:31 -0700220 // The rate at which we check for apps using excessive power -- 15 mins.
221 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
222
223 // The minimum sample duration we will allow before deciding we have
224 // enough data on wake locks to start killing things.
225 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
226
227 // The minimum sample duration we will allow before deciding we have
228 // enough data on CPU usage to start killing things.
229 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 // How long we allow a receiver to run before giving up on it.
Christopher Tatef46723b2012-01-26 14:19:24 -0800232 static final int BROADCAST_FG_TIMEOUT = 10*1000;
233 static final int BROADCAST_BG_TIMEOUT = 60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234
235 // How long we wait for a service to finish executing.
236 static final int SERVICE_TIMEOUT = 20*1000;
237
238 // How long a service needs to be running until restarting its process
239 // is no longer considered to be a relaunch of the service.
240 static final int SERVICE_RESTART_DURATION = 5*1000;
241
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700242 // How long a service needs to be running until it will start back at
243 // SERVICE_RESTART_DURATION after being killed.
244 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
245
246 // Multiplying factor to increase restart duration time by, for each time
247 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
248 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
249
250 // The minimum amount of time between restarting services that we allow.
251 // That is, when multiple services are restarting, we won't allow each
252 // to restart less than this amount of time from the last one.
253 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 // Maximum amount of time for there to be no activity on a service before
256 // we consider it non-essential and allow its process to go on the
257 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700258 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259
260 // How long we wait until we timeout on key dispatching.
261 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 // How long we wait until we timeout on key dispatching during instrumentation.
264 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
265
Dan Egnor42471dd2010-01-07 17:25:22 -0800266 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
268 static final String[] EMPTY_STRING_ARRAY = new String[0];
269
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700270 public ActivityStack mMainStack;
271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700273 * Description of a request to start a new activity, which has been held
274 * due to app switches being disabled.
275 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700276 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700277 ActivityRecord r;
278 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700279 Uri[] grantedUriPermissions;
280 int grantedMode;
281 boolean onlyIfNeeded;
282 }
283
284 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
285 = new ArrayList<PendingActivityLaunch>();
286
287 /**
Christopher Tatef46723b2012-01-26 14:19:24 -0800288 * BROADCASTS
289 *
290 * We keep two broadcast queues and associated bookkeeping, one for those at
291 * foreground priority, and one for normal (background-priority) broadcasts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 */
Christopher Tatef46723b2012-01-26 14:19:24 -0800293 public class BroadcastQueue {
294 static final String TAG = "BroadcastQueue";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
Christopher Tatef46723b2012-01-26 14:19:24 -0800296 static final int MAX_BROADCAST_HISTORY = 25;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
Christopher Tatef46723b2012-01-26 14:19:24 -0800298 /**
299 * Recognizable moniker for this queue
300 */
301 String mQueueName;
Dianne Hackborn12527f92009-11-11 17:39:50 -0800302
Christopher Tatef46723b2012-01-26 14:19:24 -0800303 /**
304 * Timeout period for this queue's broadcasts
305 */
306 long mTimeoutPeriod;
307
308 /**
309 * Lists of all active broadcasts that are to be executed immediately
310 * (without waiting for another broadcast to finish). Currently this only
311 * contains broadcasts to registered receivers, to avoid spinning up
312 * a bunch of processes to execute IntentReceiver components. Background-
313 * and foreground-priority broadcasts are queued separately.
314 */
315 final ArrayList<BroadcastRecord> mParallelBroadcasts
316 = new ArrayList<BroadcastRecord>();
317 /**
318 * List of all active broadcasts that are to be executed one at a time.
319 * The object at the top of the list is the currently activity broadcasts;
320 * those after it are waiting for the top to finish. As with parallel
321 * broadcasts, separate background- and foreground-priority queues are
322 * maintained.
323 */
324 final ArrayList<BroadcastRecord> mOrderedBroadcasts
325 = new ArrayList<BroadcastRecord>();
326
327 /**
328 * Historical data of past broadcasts, for debugging.
329 */
330 final BroadcastRecord[] mBroadcastHistory
331 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
332
333 /**
334 * Set when we current have a BROADCAST_INTENT_MSG in flight.
335 */
336 boolean mBroadcastsScheduled = false;
337
338 /**
339 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
340 */
341 boolean mPendingBroadcastTimeoutMessage;
342
343 /**
344 * Intent broadcasts that we have tried to start, but are
345 * waiting for the application's process to be created. We only
346 * need one per scheduling class (instead of a list) because we always
347 * process broadcasts one at a time, so no others can be started while
348 * waiting for this one.
349 */
350 BroadcastRecord mPendingBroadcast = null;
351
352 /**
353 * The receiver index that is pending, to restart the broadcast if needed.
354 */
355 int mPendingBroadcastRecvIndex;
356
357 BroadcastQueue(String name, long timeoutPeriod) {
358 mQueueName = name;
359 mTimeoutPeriod = timeoutPeriod;
360 }
361
362 public boolean isPendingBroadcastProcessLocked(int pid) {
363 return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
364 }
365
366 public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
367 mParallelBroadcasts.add(r);
368 }
369
370 public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
371 mOrderedBroadcasts.add(r);
372 }
373
374 public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
375 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
376 if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
377 if (DEBUG_BROADCAST) Slog.v(TAG,
378 "***** DROPPING PARALLEL ["
379 + mQueueName + "]: " + r.intent);
380 mParallelBroadcasts.set(i, r);
381 return true;
382 }
383 }
384 return false;
385 }
386
387 public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
388 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
389 if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
390 if (DEBUG_BROADCAST) Slog.v(TAG,
391 "***** DROPPING ORDERED ["
392 + mQueueName + "]: " + r.intent);
393 mOrderedBroadcasts.set(i, r);
394 return true;
395 }
396 }
397 return false;
398 }
399
400 public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
401 boolean didSomething = false;
402 final BroadcastRecord br = mPendingBroadcast;
403 if (br != null && br.curApp.pid == app.pid) {
404 try {
405 mPendingBroadcast = null;
406 processCurBroadcastLocked(br, app);
407 didSomething = true;
408 } catch (Exception e) {
409 Slog.w(TAG, "Exception in new application when starting receiver "
410 + br.curComponent.flattenToShortString(), e);
411 logBroadcastReceiverDiscardLocked(br);
412 finishReceiverLocked(br, br.resultCode, br.resultData,
413 br.resultExtras, br.resultAbort, true);
414 scheduleBroadcastsLocked();
415 // We need to reset the state if we fails to start the receiver.
416 br.state = BroadcastRecord.IDLE;
417 throw new RuntimeException(e.getMessage());
418 }
419 }
420 return didSomething;
421 }
422
423 public void skipPendingBroadcastLocked(int pid) {
424 final BroadcastRecord br = mPendingBroadcast;
425 if (br != null && br.curApp.pid == pid) {
426 br.state = BroadcastRecord.IDLE;
427 br.nextReceiver = mPendingBroadcastRecvIndex;
428 mPendingBroadcast = null;
429 scheduleBroadcastsLocked();
430 }
431 }
432
433 public void skipCurrentReceiverLocked(ProcessRecord app) {
434 boolean reschedule = false;
435 BroadcastRecord r = app.curReceiver;
436 if (r != null) {
437 // The current broadcast is waiting for this app's receiver
438 // to be finished. Looks like that's not going to happen, so
439 // let the broadcast continue.
440 logBroadcastReceiverDiscardLocked(r);
441 finishReceiverLocked(r, r.resultCode, r.resultData,
442 r.resultExtras, r.resultAbort, true);
443 reschedule = true;
444 }
445
446 r = mPendingBroadcast;
447 if (r != null && r.curApp == app) {
448 if (DEBUG_BROADCAST) Slog.v(TAG,
449 "[" + mQueueName + "] skip & discard pending app " + r);
450 logBroadcastReceiverDiscardLocked(r);
451 finishReceiverLocked(r, r.resultCode, r.resultData,
452 r.resultExtras, r.resultAbort, true);
453 reschedule = true;
454 }
455 if (reschedule) {
456 scheduleBroadcastsLocked();
457 }
458 }
459
460 public void scheduleBroadcastsLocked() {
461 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
462 + mQueueName + "]: current="
463 + mBroadcastsScheduled);
464
465 if (mBroadcastsScheduled) {
466 return;
467 }
468 mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
469 mBroadcastsScheduled = true;
470 }
471
472 public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
473 if (mOrderedBroadcasts.size() > 0) {
474 final BroadcastRecord r = mOrderedBroadcasts.get(0);
475 if (r != null && r.receiver == receiver) {
476 return r;
477 }
478 }
479 return null;
480 }
481
482 public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
483 String resultData, Bundle resultExtras, boolean resultAbort,
484 boolean explicit) {
485 int state = r.state;
486 r.state = BroadcastRecord.IDLE;
487 if (state == BroadcastRecord.IDLE) {
488 if (explicit) {
489 Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
490 }
491 }
492 r.receiver = null;
493 r.intent.setComponent(null);
494 if (r.curApp != null) {
495 r.curApp.curReceiver = null;
496 }
497 if (r.curFilter != null) {
498 r.curFilter.receiverList.curBroadcast = null;
499 }
500 r.curFilter = null;
501 r.curApp = null;
502 r.curComponent = null;
503 r.curReceiver = null;
504 mPendingBroadcast = null;
505
506 r.resultCode = resultCode;
507 r.resultData = resultData;
508 r.resultExtras = resultExtras;
509 r.resultAbort = resultAbort;
510
511 // We will process the next receiver right now if this is finishing
512 // an app receiver (which is always asynchronous) or after we have
513 // come back from calling a receiver.
514 return state == BroadcastRecord.APP_RECEIVE
515 || state == BroadcastRecord.CALL_DONE_RECEIVE;
516 }
517
518 private final void processNextBroadcast(boolean fromMsg) {
519 synchronized(ActivityManagerService.this) {
520 BroadcastRecord r;
521
522 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
523 + mQueueName + "]: "
524 + mParallelBroadcasts.size() + " broadcasts, "
525 + mOrderedBroadcasts.size() + " ordered broadcasts");
526
527 updateCpuStats();
528
529 if (fromMsg) {
530 mBroadcastsScheduled = false;
531 }
532
533 // First, deliver any non-serialized broadcasts right away.
534 while (mParallelBroadcasts.size() > 0) {
535 r = mParallelBroadcasts.remove(0);
536 r.dispatchTime = SystemClock.uptimeMillis();
537 r.dispatchClockTime = System.currentTimeMillis();
538 final int N = r.receivers.size();
539 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["
540 + mQueueName + "] " + r);
541 for (int i=0; i<N; i++) {
542 Object target = r.receivers.get(i);
543 if (DEBUG_BROADCAST) Slog.v(TAG,
544 "Delivering non-ordered on [" + mQueueName + "] to registered "
545 + target + ": " + r);
546 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
547 }
548 addBroadcastToHistoryLocked(r);
549 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
550 + mQueueName + "] " + r);
551 }
552
553 // Now take care of the next serialized one...
554
555 // If we are waiting for a process to come up to handle the next
556 // broadcast, then do nothing at this point. Just in case, we
557 // check that the process we're waiting for still exists.
558 if (mPendingBroadcast != null) {
559 if (DEBUG_BROADCAST_LIGHT) {
560 Slog.v(TAG, "processNextBroadcast ["
561 + mQueueName + "]: waiting for "
562 + mPendingBroadcast.curApp);
563 }
564
565 boolean isDead;
566 synchronized (mPidsSelfLocked) {
567 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
568 }
569 if (!isDead) {
570 // It's still alive, so keep waiting
571 return;
572 } else {
573 Slog.w(TAG, "pending app ["
574 + mQueueName + "]" + mPendingBroadcast.curApp
575 + " died before responding to broadcast");
576 mPendingBroadcast.state = BroadcastRecord.IDLE;
577 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
578 mPendingBroadcast = null;
579 }
580 }
581
582 boolean looped = false;
583
584 do {
585 if (mOrderedBroadcasts.size() == 0) {
586 // No more broadcasts pending, so all done!
587 scheduleAppGcsLocked();
588 if (looped) {
589 // If we had finished the last ordered broadcast, then
590 // make sure all processes have correct oom and sched
591 // adjustments.
592 updateOomAdjLocked();
593 }
594 return;
595 }
596 r = mOrderedBroadcasts.get(0);
597 boolean forceReceive = false;
598
599 // Ensure that even if something goes awry with the timeout
600 // detection, we catch "hung" broadcasts here, discard them,
601 // and continue to make progress.
602 //
603 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
604 // receivers don't get executed with timeouts. They're intended for
605 // one time heavy lifting after system upgrades and can take
606 // significant amounts of time.
607 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
608 if (mProcessesReady && r.dispatchTime > 0) {
609 long now = SystemClock.uptimeMillis();
610 if ((numReceivers > 0) &&
611 (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
612 Slog.w(TAG, "Hung broadcast ["
613 + mQueueName + "] discarded after timeout failure:"
614 + " now=" + now
615 + " dispatchTime=" + r.dispatchTime
616 + " startTime=" + r.receiverTime
617 + " intent=" + r.intent
618 + " numReceivers=" + numReceivers
619 + " nextReceiver=" + r.nextReceiver
620 + " state=" + r.state);
621 broadcastTimeoutLocked(false); // forcibly finish this broadcast
622 forceReceive = true;
623 r.state = BroadcastRecord.IDLE;
624 }
625 }
626
627 if (r.state != BroadcastRecord.IDLE) {
628 if (DEBUG_BROADCAST) Slog.d(TAG,
629 "processNextBroadcast("
630 + mQueueName + ") called when not idle (state="
631 + r.state + ")");
632 return;
633 }
634
635 if (r.receivers == null || r.nextReceiver >= numReceivers
636 || r.resultAbort || forceReceive) {
637 // No more receivers for this broadcast! Send the final
638 // result if requested...
639 if (r.resultTo != null) {
640 try {
641 if (DEBUG_BROADCAST) {
642 int seq = r.intent.getIntExtra("seq", -1);
643 Slog.i(TAG, "Finishing broadcast ["
644 + mQueueName + "] " + r.intent.getAction()
645 + " seq=" + seq + " app=" + r.callerApp);
646 }
647 performReceiveLocked(r.callerApp, r.resultTo,
648 new Intent(r.intent), r.resultCode,
649 r.resultData, r.resultExtras, false, false);
650 // Set this to null so that the reference
651 // (local and remote) isnt kept in the mBroadcastHistory.
652 r.resultTo = null;
653 } catch (RemoteException e) {
654 Slog.w(TAG, "Failure ["
655 + mQueueName + "] sending broadcast result of "
656 + r.intent, e);
657 }
658 }
659
660 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
661 cancelBroadcastTimeoutLocked();
662
663 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
664 + r);
665
666 // ... and on to the next...
667 addBroadcastToHistoryLocked(r);
668 mOrderedBroadcasts.remove(0);
669 r = null;
670 looped = true;
671 continue;
672 }
673 } while (r == null);
674
675 // Get the next receiver...
676 int recIdx = r.nextReceiver++;
677
678 // Keep track of when this receiver started, and make sure there
679 // is a timeout message pending to kill it if need be.
680 r.receiverTime = SystemClock.uptimeMillis();
681 if (recIdx == 0) {
682 r.dispatchTime = r.receiverTime;
683 r.dispatchClockTime = System.currentTimeMillis();
684 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["
685 + mQueueName + "] " + r);
686 }
687 if (! mPendingBroadcastTimeoutMessage) {
688 long timeoutTime = r.receiverTime + mTimeoutPeriod;
689 if (DEBUG_BROADCAST) Slog.v(TAG,
690 "Submitting BROADCAST_TIMEOUT_MSG ["
691 + mQueueName + "] for " + r + " at " + timeoutTime);
692 setBroadcastTimeoutLocked(timeoutTime);
693 }
694
695 Object nextReceiver = r.receivers.get(recIdx);
696 if (nextReceiver instanceof BroadcastFilter) {
697 // Simple case: this is a registered receiver who gets
698 // a direct call.
699 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
700 if (DEBUG_BROADCAST) Slog.v(TAG,
701 "Delivering ordered ["
702 + mQueueName + "] to registered "
703 + filter + ": " + r);
704 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
705 if (r.receiver == null || !r.ordered) {
706 // The receiver has already finished, so schedule to
707 // process the next one.
708 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["
709 + mQueueName + "]: ordered="
710 + r.ordered + " receiver=" + r.receiver);
711 r.state = BroadcastRecord.IDLE;
712 scheduleBroadcastsLocked();
713 }
714 return;
715 }
716
717 // Hard case: need to instantiate the receiver, possibly
718 // starting its application process to host it.
719
720 ResolveInfo info =
721 (ResolveInfo)nextReceiver;
722
723 boolean skip = false;
724 int perm = checkComponentPermission(info.activityInfo.permission,
725 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
726 info.activityInfo.exported);
727 if (perm != PackageManager.PERMISSION_GRANTED) {
728 if (!info.activityInfo.exported) {
729 Slog.w(TAG, "Permission Denial: broadcasting "
730 + r.intent.toString()
731 + " from " + r.callerPackage + " (pid=" + r.callingPid
732 + ", uid=" + r.callingUid + ")"
733 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
734 + " due to receiver " + info.activityInfo.packageName
735 + "/" + info.activityInfo.name);
736 } else {
737 Slog.w(TAG, "Permission Denial: broadcasting "
738 + r.intent.toString()
739 + " from " + r.callerPackage + " (pid=" + r.callingPid
740 + ", uid=" + r.callingUid + ")"
741 + " requires " + info.activityInfo.permission
742 + " due to receiver " + info.activityInfo.packageName
743 + "/" + info.activityInfo.name);
744 }
745 skip = true;
746 }
747 if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
748 r.requiredPermission != null) {
749 try {
750 perm = AppGlobals.getPackageManager().
751 checkPermission(r.requiredPermission,
752 info.activityInfo.applicationInfo.packageName);
753 } catch (RemoteException e) {
754 perm = PackageManager.PERMISSION_DENIED;
755 }
756 if (perm != PackageManager.PERMISSION_GRANTED) {
757 Slog.w(TAG, "Permission Denial: receiving "
758 + r.intent + " to "
759 + info.activityInfo.applicationInfo.packageName
760 + " requires " + r.requiredPermission
761 + " due to sender " + r.callerPackage
762 + " (uid " + r.callingUid + ")");
763 skip = true;
764 }
765 }
766 if (r.curApp != null && r.curApp.crashing) {
767 // If the target process is crashing, just skip it.
768 if (DEBUG_BROADCAST) Slog.v(TAG,
769 "Skipping deliver ordered ["
770 + mQueueName + "] " + r + " to " + r.curApp
771 + ": process crashing");
772 skip = true;
773 }
774
775 if (skip) {
776 if (DEBUG_BROADCAST) Slog.v(TAG,
777 "Skipping delivery of ordered ["
778 + mQueueName + "] " + r + " for whatever reason");
779 r.receiver = null;
780 r.curFilter = null;
781 r.state = BroadcastRecord.IDLE;
782 scheduleBroadcastsLocked();
783 return;
784 }
785
786 r.state = BroadcastRecord.APP_RECEIVE;
787 String targetProcess = info.activityInfo.processName;
788 r.curComponent = new ComponentName(
789 info.activityInfo.applicationInfo.packageName,
790 info.activityInfo.name);
Amith Yamasani742a6712011-05-04 14:49:28 -0700791 if (r.callingUid != Process.SYSTEM_UID) {
792 info.activityInfo = getActivityInfoForUser(info.activityInfo, UserId
793 .getUserId(r.callingUid));
794 }
Christopher Tatef46723b2012-01-26 14:19:24 -0800795 r.curReceiver = info.activityInfo;
Amith Yamasani742a6712011-05-04 14:49:28 -0700796 if (DEBUG_MU && r.callingUid > UserId.PER_USER_RANGE) {
797 Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
798 + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
799 + info.activityInfo.applicationInfo.uid);
800 }
Christopher Tatef46723b2012-01-26 14:19:24 -0800801
802 // Broadcast is being executed, its package can't be stopped.
803 try {
804 AppGlobals.getPackageManager().setPackageStoppedState(
805 r.curComponent.getPackageName(), false);
806 } catch (RemoteException e) {
807 } catch (IllegalArgumentException e) {
808 Slog.w(TAG, "Failed trying to unstop package "
809 + r.curComponent.getPackageName() + ": " + e);
810 }
811
812 // Is this receiver's application already running?
813 ProcessRecord app = getProcessRecordLocked(targetProcess,
814 info.activityInfo.applicationInfo.uid);
815 if (app != null && app.thread != null) {
816 try {
817 app.addPackage(info.activityInfo.packageName);
818 processCurBroadcastLocked(r, app);
819 return;
820 } catch (RemoteException e) {
821 Slog.w(TAG, "Exception when sending broadcast to "
822 + r.curComponent, e);
823 }
824
825 // If a dead object exception was thrown -- fall through to
826 // restart the application.
827 }
828
829 // Not running -- get it started, to be executed when the app comes up.
830 if (DEBUG_BROADCAST) Slog.v(TAG,
831 "Need to start app ["
832 + mQueueName + "] " + targetProcess + " for broadcast " + r);
833 if ((r.curApp=startProcessLocked(targetProcess,
834 info.activityInfo.applicationInfo, true,
835 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
836 "broadcast", r.curComponent,
837 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
838 == null) {
839 // Ah, this recipient is unavailable. Finish it if necessary,
840 // and mark the broadcast record as ready for the next.
841 Slog.w(TAG, "Unable to launch app "
842 + info.activityInfo.applicationInfo.packageName + "/"
843 + info.activityInfo.applicationInfo.uid + " for broadcast "
844 + r.intent + ": process is bad");
845 logBroadcastReceiverDiscardLocked(r);
846 finishReceiverLocked(r, r.resultCode, r.resultData,
847 r.resultExtras, r.resultAbort, true);
848 scheduleBroadcastsLocked();
849 r.state = BroadcastRecord.IDLE;
850 return;
851 }
852
853 mPendingBroadcast = r;
854 mPendingBroadcastRecvIndex = recIdx;
855 }
856 }
857
858 final void setBroadcastTimeoutLocked(long timeoutTime) {
859 if (! mPendingBroadcastTimeoutMessage) {
860 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
861 mHandler.sendMessageAtTime(msg, timeoutTime);
862 mPendingBroadcastTimeoutMessage = true;
863 }
864 }
865
866 final void cancelBroadcastTimeoutLocked() {
867 if (mPendingBroadcastTimeoutMessage) {
868 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
869 mPendingBroadcastTimeoutMessage = false;
870 }
871 }
872
873 final void broadcastTimeoutLocked(boolean fromMsg) {
874 if (fromMsg) {
875 mPendingBroadcastTimeoutMessage = false;
876 }
877
878 if (mOrderedBroadcasts.size() == 0) {
879 return;
880 }
881
882 long now = SystemClock.uptimeMillis();
883 BroadcastRecord r = mOrderedBroadcasts.get(0);
884 if (fromMsg) {
885 if (mDidDexOpt) {
886 // Delay timeouts until dexopt finishes.
887 mDidDexOpt = false;
888 long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
889 setBroadcastTimeoutLocked(timeoutTime);
890 return;
891 }
892 if (! mProcessesReady) {
893 // Only process broadcast timeouts if the system is ready. That way
894 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
895 // to do heavy lifting for system up.
896 return;
897 }
898
899 long timeoutTime = r.receiverTime + mTimeoutPeriod;
900 if (timeoutTime > now) {
901 // We can observe premature timeouts because we do not cancel and reset the
902 // broadcast timeout message after each receiver finishes. Instead, we set up
903 // an initial timeout then kick it down the road a little further as needed
904 // when it expires.
905 if (DEBUG_BROADCAST) Slog.v(TAG,
906 "Premature timeout ["
907 + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
908 + timeoutTime);
909 setBroadcastTimeoutLocked(timeoutTime);
910 return;
911 }
912 }
913
914 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
915 + ", started " + (now - r.receiverTime) + "ms ago");
916 r.receiverTime = now;
917 r.anrCount++;
918
919 // Current receiver has passed its expiration date.
920 if (r.nextReceiver <= 0) {
921 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
922 return;
923 }
924
925 ProcessRecord app = null;
926 String anrMessage = null;
927
928 Object curReceiver = r.receivers.get(r.nextReceiver-1);
929 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
930 logBroadcastReceiverDiscardLocked(r);
931 if (curReceiver instanceof BroadcastFilter) {
932 BroadcastFilter bf = (BroadcastFilter)curReceiver;
933 if (bf.receiverList.pid != 0
934 && bf.receiverList.pid != MY_PID) {
935 synchronized (ActivityManagerService.this.mPidsSelfLocked) {
936 app = ActivityManagerService.this.mPidsSelfLocked.get(
937 bf.receiverList.pid);
938 }
939 }
940 } else {
941 app = r.curApp;
942 }
943
944 if (app != null) {
945 anrMessage = "Broadcast of " + r.intent.toString();
946 }
947
948 if (mPendingBroadcast == r) {
949 mPendingBroadcast = null;
950 }
951
952 // Move on to the next receiver.
953 finishReceiverLocked(r, r.resultCode, r.resultData,
954 r.resultExtras, r.resultAbort, true);
955 scheduleBroadcastsLocked();
956
957 if (anrMessage != null) {
958 // Post the ANR to the handler since we do not want to process ANRs while
959 // potentially holding our lock.
960 mHandler.post(new AppNotResponding(app, anrMessage));
961 }
962 }
963
964 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
965 if (r.callingUid < 0) {
966 // This was from a registerReceiver() call; ignore it.
967 return;
968 }
969 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
970 MAX_BROADCAST_HISTORY-1);
971 r.finishTime = SystemClock.uptimeMillis();
972 mBroadcastHistory[0] = r;
973 }
974
975 final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
976 if (r.nextReceiver > 0) {
977 Object curReceiver = r.receivers.get(r.nextReceiver-1);
978 if (curReceiver instanceof BroadcastFilter) {
979 BroadcastFilter bf = (BroadcastFilter) curReceiver;
980 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
981 System.identityHashCode(r),
982 r.intent.getAction(),
983 r.nextReceiver - 1,
984 System.identityHashCode(bf));
985 } else {
986 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
987 System.identityHashCode(r),
988 r.intent.getAction(),
989 r.nextReceiver - 1,
990 ((ResolveInfo)curReceiver).toString());
991 }
992 } else {
993 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
994 + r);
995 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
996 System.identityHashCode(r),
997 r.intent.getAction(),
998 r.nextReceiver,
999 "NONE");
1000 }
1001 }
1002
1003 final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
1004 int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
1005 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
1006 || mPendingBroadcast != null) {
1007 boolean printed = false;
1008 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
1009 BroadcastRecord br = mParallelBroadcasts.get(i);
1010 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
1011 continue;
1012 }
1013 if (!printed) {
1014 if (needSep) {
1015 pw.println();
1016 needSep = false;
1017 }
1018 printed = true;
1019 pw.println(" Active broadcasts [" + mQueueName + "]:");
1020 }
1021 pw.println(" Broadcast #" + i + ":");
1022 br.dump(pw, " ");
1023 }
1024 printed = false;
1025 needSep = true;
1026 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
1027 BroadcastRecord br = mOrderedBroadcasts.get(i);
1028 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
1029 continue;
1030 }
1031 if (!printed) {
1032 if (needSep) {
1033 pw.println();
1034 }
1035 needSep = true;
1036 pw.println(" Active ordered broadcasts [" + mQueueName + "]:");
1037 }
1038 pw.println(" Ordered Broadcast #" + i + ":");
1039 mOrderedBroadcasts.get(i).dump(pw, " ");
1040 }
1041 if (dumpPackage == null || (mPendingBroadcast != null
1042 && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
1043 if (needSep) {
1044 pw.println();
1045 }
1046 pw.println(" Pending broadcast [" + mQueueName + "]:");
1047 if (mPendingBroadcast != null) {
1048 mPendingBroadcast.dump(pw, " ");
1049 } else {
1050 pw.println(" (null)");
1051 }
1052 needSep = true;
1053 }
1054 }
1055
1056 boolean printed = false;
1057 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
1058 BroadcastRecord r = mBroadcastHistory[i];
1059 if (r == null) {
1060 break;
1061 }
1062 if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
1063 continue;
1064 }
1065 if (!printed) {
1066 if (needSep) {
1067 pw.println();
1068 }
1069 needSep = true;
1070 pw.println(" Historical broadcasts [" + mQueueName + "]:");
1071 printed = true;
1072 }
1073 if (dumpAll) {
1074 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
1075 r.dump(pw, " ");
1076 } else {
1077 if (i >= 50) {
1078 pw.println(" ...");
1079 break;
1080 }
1081 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
1082 }
1083 }
1084
1085 return needSep;
1086 }
1087 }
1088
1089 final BroadcastQueue mFgBroadcastQueue = new BroadcastQueue("foreground", BROADCAST_FG_TIMEOUT);
1090 final BroadcastQueue mBgBroadcastQueue = new BroadcastQueue("background", BROADCAST_BG_TIMEOUT);
1091 // Convenient for easy iteration over the queues. Foreground is first
1092 // so that dispatch of foreground broadcasts gets precedence.
1093 final BroadcastQueue[] mBroadcastQueues = { mFgBroadcastQueue, mBgBroadcastQueue };
1094
1095 BroadcastQueue broadcastQueueForIntent(Intent intent) {
1096 final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
1097 if (DEBUG_BACKGROUND_BROADCAST) {
1098 Slog.i(TAG, "Broadcast intent " + intent + " on "
1099 + (isFg ? "foreground" : "background")
1100 + " queue");
1101 }
1102 return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
1103 }
1104
1105 BroadcastRecord broadcastRecordForReceiverLocked(IBinder receiver) {
1106 for (BroadcastQueue queue : mBroadcastQueues) {
1107 BroadcastRecord r = queue.getMatchingOrderedReceiver(receiver);
1108 if (r != null) {
1109 return r;
1110 }
1111 }
1112 return null;
1113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114
1115 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 * Activity we have told the window manager to have key focus.
1117 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001118 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001119 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 * List of intents that were used to start the most recent tasks.
1121 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001122 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123
1124 /**
Dianne Hackborn7d608422011-08-07 16:24:18 -07001125 * Process management.
1126 */
1127 final ProcessList mProcessList = new ProcessList();
1128
1129 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 * All of the applications we currently have running organized by name.
1131 * The keys are strings of the application package name (as
1132 * returned by the package manager), and the keys are ApplicationRecord
1133 * objects.
1134 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001135 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136
1137 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -07001138 * The currently running heavy-weight process, if any.
1139 */
1140 ProcessRecord mHeavyWeightProcess = null;
1141
1142 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 * The last time that various processes have crashed.
1144 */
1145 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
1146
1147 /**
1148 * Set of applications that we consider to be bad, and will reject
1149 * incoming broadcasts from (which the user has no control over).
1150 * Processes are added to this set when they have crashed twice within
1151 * a minimum amount of time; they are removed from it when they are
1152 * later restarted (hopefully due to some user action). The value is the
1153 * time it was added to the list.
1154 */
1155 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
1156
1157 /**
1158 * All of the processes we currently have running organized by pid.
1159 * The keys are the pid running the application.
1160 *
1161 * <p>NOTE: This object is protected by its own lock, NOT the global
1162 * activity manager lock!
1163 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001164 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165
1166 /**
1167 * All of the processes that have been forced to be foreground. The key
1168 * is the pid of the caller who requested it (we hold a death
1169 * link on it).
1170 */
1171 abstract class ForegroundToken implements IBinder.DeathRecipient {
1172 int pid;
1173 IBinder token;
1174 }
1175 final SparseArray<ForegroundToken> mForegroundProcesses
1176 = new SparseArray<ForegroundToken>();
1177
1178 /**
1179 * List of records for processes that someone had tried to start before the
1180 * system was ready. We don't start them at that point, but ensure they
1181 * are started by the time booting is complete.
1182 */
1183 final ArrayList<ProcessRecord> mProcessesOnHold
1184 = new ArrayList<ProcessRecord>();
1185
1186 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 * List of persistent applications that are in the process
1188 * of being started.
1189 */
1190 final ArrayList<ProcessRecord> mPersistentStartingProcesses
1191 = new ArrayList<ProcessRecord>();
1192
1193 /**
1194 * Processes that are being forcibly torn down.
1195 */
1196 final ArrayList<ProcessRecord> mRemovedProcesses
1197 = new ArrayList<ProcessRecord>();
1198
1199 /**
1200 * List of running applications, sorted by recent usage.
1201 * The first entry in the list is the least recently used.
1202 * It contains ApplicationRecord objects. This list does NOT include
1203 * any persistent application records (since we never want to exit them).
1204 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001205 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 = new ArrayList<ProcessRecord>();
1207
1208 /**
1209 * List of processes that should gc as soon as things are idle.
1210 */
1211 final ArrayList<ProcessRecord> mProcessesToGc
1212 = new ArrayList<ProcessRecord>();
1213
1214 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001215 * This is the process holding what we currently consider to be
1216 * the "home" activity.
1217 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001218 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001219
1220 /**
Dianne Hackbornf35fe232011-11-01 19:25:20 -07001221 * This is the process holding the activity the user last visited that
1222 * is in a different process from the one they are currently in.
1223 */
1224 ProcessRecord mPreviousProcess;
Dianne Hackborn50685602011-12-01 12:23:37 -08001225
1226 /**
1227 * The time at which the previous process was last visible.
1228 */
1229 long mPreviousProcessVisibleTime;
1230
Dianne Hackbornf35fe232011-11-01 19:25:20 -07001231 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001232 * Packages that the user has asked to have run in screen size
1233 * compatibility mode instead of filling the screen.
1234 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001235 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001236
1237 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 * Set of PendingResultRecord objects that are currently active.
1239 */
1240 final HashSet mPendingResultRecords = new HashSet();
1241
1242 /**
1243 * Set of IntentSenderRecord objects that are currently active.
1244 */
1245 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
1246 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
1247
1248 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001249 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07001250 * already logged DropBox entries for. Guarded by itself. If
1251 * something (rogue user app) forces this over
1252 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
1253 */
1254 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
1255 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
1256
1257 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07001258 * Strict Mode background batched logging state.
1259 *
1260 * The string buffer is guarded by itself, and its lock is also
1261 * used to determine if another batched write is already
1262 * in-flight.
1263 */
1264 private final StringBuilder mStrictModeBuffer = new StringBuilder();
1265
1266 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 * Keeps track of all IIntentReceivers that have been registered for
1268 * broadcasts. Hash keys are the receiver IBinder, hash value is
1269 * a ReceiverList.
1270 */
1271 final HashMap mRegisteredReceivers = new HashMap();
1272
1273 /**
1274 * Resolver for broadcast intents to registered receivers.
1275 * Holds BroadcastFilter (subclass of IntentFilter).
1276 */
1277 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
1278 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
1279 @Override
1280 protected boolean allowFilterResult(
1281 BroadcastFilter filter, List<BroadcastFilter> dest) {
1282 IBinder target = filter.receiverList.receiver.asBinder();
1283 for (int i=dest.size()-1; i>=0; i--) {
1284 if (dest.get(i).receiverList.receiver.asBinder() == target) {
1285 return false;
1286 }
1287 }
1288 return true;
1289 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001290
1291 @Override
1292 protected String packageForFilter(BroadcastFilter filter) {
1293 return filter.packageName;
1294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001295 };
1296
1297 /**
1298 * State of all active sticky broadcasts. Keys are the action of the
1299 * sticky Intent, values are an ArrayList of all broadcasted intents with
1300 * that action (which should usually be one).
1301 */
1302 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
1303 new HashMap<String, ArrayList<Intent>>();
1304
Amith Yamasani742a6712011-05-04 14:49:28 -07001305 final ServiceMap mServiceMap = new ServiceMap();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306
1307 /**
1308 * All currently bound service connections. Keys are the IBinder of
1309 * the client's IServiceConnection.
1310 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07001311 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
1312 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313
1314 /**
1315 * List of services that we have been asked to start,
1316 * but haven't yet been able to. It is used to hold start requests
1317 * while waiting for their corresponding application thread to get
1318 * going.
1319 */
1320 final ArrayList<ServiceRecord> mPendingServices
1321 = new ArrayList<ServiceRecord>();
1322
1323 /**
1324 * List of services that are scheduled to restart following a crash.
1325 */
1326 final ArrayList<ServiceRecord> mRestartingServices
1327 = new ArrayList<ServiceRecord>();
1328
1329 /**
1330 * List of services that are in the process of being stopped.
1331 */
1332 final ArrayList<ServiceRecord> mStoppingServices
1333 = new ArrayList<ServiceRecord>();
1334
1335 /**
Christopher Tate181fafa2009-05-14 11:12:14 -07001336 * Backup/restore process management
1337 */
1338 String mBackupAppName = null;
1339 BackupRecord mBackupTarget = null;
1340
1341 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 * List of PendingThumbnailsRecord objects of clients who are still
1343 * waiting to receive all of the thumbnails for a task.
1344 */
1345 final ArrayList mPendingThumbnails = new ArrayList();
1346
1347 /**
1348 * List of HistoryRecord objects that have been finished and must
1349 * still report back to a pending thumbnail receiver.
1350 */
1351 final ArrayList mCancelledThumbnails = new ArrayList();
1352
1353 /**
1354 * All of the currently running global content providers. Keys are a
1355 * string containing the provider name and values are a
1356 * ContentProviderRecord object containing the data about it. Note
1357 * that a single provider may be published under multiple names, so
1358 * there may be multiple entries here for a single one in mProvidersByClass.
1359 */
Dianne Hackborn860755f2010-06-03 18:47:52 -07001360 final HashMap<String, ContentProviderRecord> mProvidersByName
1361 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362
1363 /**
1364 * All of the currently running global content providers. Keys are a
1365 * string containing the provider's implementation class and values are a
1366 * ContentProviderRecord object containing the data about it.
1367 */
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07001368 final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
1369 = new HashMap<ComponentName, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370
Amith Yamasani742a6712011-05-04 14:49:28 -07001371 final ProviderMap mProviderMap = new ProviderMap();
1372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 /**
1374 * List of content providers who have clients waiting for them. The
1375 * application is currently being launched and the provider will be
1376 * removed from this list once it is published.
1377 */
Dianne Hackborn860755f2010-06-03 18:47:52 -07001378 final ArrayList<ContentProviderRecord> mLaunchingProviders
1379 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380
1381 /**
1382 * Global set of specific Uri permissions that have been granted.
1383 */
1384 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
1385 = new SparseArray<HashMap<Uri, UriPermission>>();
1386
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08001387 CoreSettingsObserver mCoreSettingsObserver;
1388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 /**
1390 * Thread-local storage used to carry caller permissions over through
1391 * indirect content-provider access.
1392 * @see #ActivityManagerService.openContentUri()
1393 */
1394 private class Identity {
1395 public int pid;
1396 public int uid;
1397
1398 Identity(int _pid, int _uid) {
1399 pid = _pid;
1400 uid = _uid;
1401 }
1402 }
Amith Yamasani742a6712011-05-04 14:49:28 -07001403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
1405
1406 /**
1407 * All information we have collected about the runtime performance of
1408 * any user id that can impact battery performance.
1409 */
1410 final BatteryStatsService mBatteryStatsService;
1411
1412 /**
1413 * information about component usage
1414 */
1415 final UsageStatsService mUsageStatsService;
1416
1417 /**
1418 * Current configuration information. HistoryRecord objects are given
1419 * a reference to this object to indicate which configuration they are
1420 * currently running in, so this object must be kept immutable.
1421 */
1422 Configuration mConfiguration = new Configuration();
1423
1424 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001425 * Current sequencing integer of the configuration, for skipping old
1426 * configurations.
1427 */
1428 int mConfigurationSeq = 0;
1429
1430 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -07001431 * Hardware-reported OpenGLES version.
1432 */
1433 final int GL_ES_VERSION;
1434
1435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 * List of initialization arguments to pass to all processes when binding applications to them.
1437 * For example, references to the commonly used services.
1438 */
1439 HashMap<String, IBinder> mAppBindArgs;
1440
1441 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001442 * Temporary to avoid allocations. Protected by main lock.
1443 */
1444 final StringBuilder mStringBuilder = new StringBuilder(256);
1445
1446 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 * Used to control how we initialize the service.
1448 */
1449 boolean mStartRunning = false;
1450 ComponentName mTopComponent;
1451 String mTopAction;
1452 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001453 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 boolean mSystemReady = false;
1455 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001456 boolean mWaitingUpdate = false;
1457 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001458 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001459 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460
1461 Context mContext;
1462
1463 int mFactoryTest;
1464
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001465 boolean mCheckedForSetup;
1466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001468 * The time at which we will allow normal application switches again,
1469 * after a call to {@link #stopAppSwitches()}.
1470 */
1471 long mAppSwitchesAllowedTime;
1472
1473 /**
1474 * This is set to true after the first switch after mAppSwitchesAllowedTime
1475 * is set; any switches after that will clear the time.
1476 */
1477 boolean mDidAppSwitch;
1478
1479 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -07001480 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001481 */
Dianne Hackborn287952c2010-09-22 22:34:31 -07001482 long mLastPowerCheckRealtime;
1483
1484 /**
1485 * Last time (in uptime) at which we checked for power usage.
1486 */
1487 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001488
1489 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 * Set while we are wanting to sleep, to prevent any
1491 * activities from being started/resumed.
1492 */
1493 boolean mSleeping = false;
1494
1495 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -07001496 * Set if we are shutting down the system, similar to sleeping.
1497 */
1498 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499
1500 /**
1501 * Task identifier that activities are currently being started
1502 * in. Incremented each time a new task is created.
1503 * todo: Replace this with a TokenSpace class that generates non-repeating
1504 * integers that won't wrap.
1505 */
1506 int mCurTask = 1;
1507
1508 /**
1509 * Current sequence id for oom_adj computation traversal.
1510 */
1511 int mAdjSeq = 0;
1512
1513 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -07001514 * Current sequence id for process LRU updating.
1515 */
1516 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517
1518 /**
Dianne Hackborne02c88a2011-10-28 13:58:15 -07001519 * Keep track of the number of service processes we last found, to
1520 * determine on the next iteration which should be B services.
1521 */
1522 int mNumServiceProcs = 0;
1523 int mNewNumServiceProcs = 0;
1524
1525 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 * System monitoring: number of processes that died since the last
1527 * N procs were started.
1528 */
1529 int[] mProcDeaths = new int[20];
1530
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001531 /**
1532 * This is set if we had to do a delayed dexopt of an app before launching
1533 * it, to increasing the ANR timeouts in that case.
1534 */
1535 boolean mDidDexOpt;
1536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 String mDebugApp = null;
1538 boolean mWaitForDebugger = false;
1539 boolean mDebugTransient = false;
1540 String mOrigDebugApp = null;
1541 boolean mOrigWaitForDebugger = false;
1542 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001543 IActivityController mController = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07001544 String mProfileApp = null;
1545 ProcessRecord mProfileProc = null;
1546 String mProfileFile;
1547 ParcelFileDescriptor mProfileFd;
1548 int mProfileType = 0;
1549 boolean mAutoStopProfiler = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001551 final RemoteCallbackList<IActivityWatcher> mWatchers
1552 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -07001553
1554 final RemoteCallbackList<IProcessObserver> mProcessObservers
1555 = new RemoteCallbackList<IProcessObserver>();
1556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 /**
1558 * Callback of last caller to {@link #requestPss}.
1559 */
1560 Runnable mRequestPssCallback;
1561
1562 /**
1563 * Remaining processes for which we are waiting results from the last
1564 * call to {@link #requestPss}.
1565 */
1566 final ArrayList<ProcessRecord> mRequestPssList
1567 = new ArrayList<ProcessRecord>();
1568
1569 /**
1570 * Runtime statistics collection thread. This object's lock is used to
1571 * protect all related state.
1572 */
1573 final Thread mProcessStatsThread;
1574
1575 /**
1576 * Used to collect process stats when showing not responding dialog.
1577 * Protected by mProcessStatsThread.
1578 */
1579 final ProcessStats mProcessStats = new ProcessStats(
1580 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001581 final AtomicLong mLastCpuTime = new AtomicLong(0);
1582 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
1583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 long mLastWriteTime = 0;
1585
1586 /**
1587 * Set to true after the system has finished booting.
1588 */
1589 boolean mBooted = false;
1590
Dianne Hackborn7d608422011-08-07 16:24:18 -07001591 int mProcessLimit = ProcessList.MAX_HIDDEN_APPS;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001592 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593
1594 WindowManagerService mWindowManager;
1595
1596 static ActivityManagerService mSelf;
1597 static ActivityThread mSystemThread;
1598
1599 private final class AppDeathRecipient implements IBinder.DeathRecipient {
1600 final ProcessRecord mApp;
1601 final int mPid;
1602 final IApplicationThread mAppThread;
1603
1604 AppDeathRecipient(ProcessRecord app, int pid,
1605 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 TAG, "New death recipient " + this
1608 + " for thread " + thread.asBinder());
1609 mApp = app;
1610 mPid = pid;
1611 mAppThread = thread;
1612 }
1613
1614 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001615 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 TAG, "Death received in " + this
1617 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 synchronized(ActivityManagerService.this) {
1619 appDiedLocked(mApp, mPid, mAppThread);
1620 }
1621 }
1622 }
1623
1624 static final int SHOW_ERROR_MSG = 1;
1625 static final int SHOW_NOT_RESPONDING_MSG = 2;
1626 static final int SHOW_FACTORY_ERROR_MSG = 3;
1627 static final int UPDATE_CONFIGURATION_MSG = 4;
1628 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1629 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1630 static final int BROADCAST_INTENT_MSG = 7;
1631 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 static final int SERVICE_TIMEOUT_MSG = 12;
1633 static final int UPDATE_TIME_ZONE = 13;
1634 static final int SHOW_UID_ERROR_MSG = 14;
1635 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001637 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001638 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001639 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001640 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1641 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001642 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001643 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001644 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001645 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001646 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001647 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
1648 static final int DISPATCH_PROCESS_DIED = 32;
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001649 static final int REPORT_MEM_USAGE = 33;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650
1651 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001652 CompatModeDialog mCompatModeDialog;
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001653 long mLastMemUsageReportTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654
1655 final Handler mHandler = new Handler() {
1656 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001657 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 //}
1659
1660 public void handleMessage(Message msg) {
1661 switch (msg.what) {
1662 case SHOW_ERROR_MSG: {
1663 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 synchronized (ActivityManagerService.this) {
1665 ProcessRecord proc = (ProcessRecord)data.get("app");
1666 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001667 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 return;
1669 }
1670 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001671 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001672 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 d.show();
1674 proc.crashDialog = d;
1675 } else {
1676 // The device is asleep, so just pretend that the user
1677 // saw a crash dialog and hit "force quit".
1678 res.set(0);
1679 }
1680 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001681
1682 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 } break;
1684 case SHOW_NOT_RESPONDING_MSG: {
1685 synchronized (ActivityManagerService.this) {
1686 HashMap data = (HashMap) msg.obj;
1687 ProcessRecord proc = (ProcessRecord)data.get("app");
1688 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001689 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 return;
1691 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001692
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001693 Intent intent = new Intent("android.intent.action.ANR");
1694 if (!mProcessesReady) {
Christopher Tatef46723b2012-01-26 14:19:24 -08001695 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1696 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001697 }
1698 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001699 null, null, 0, null, null, null,
Amith Yamasani742a6712011-05-04 14:49:28 -07001700 false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
The Android Open Source Project4df24232009-03-05 14:34:35 -08001701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001703 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 d.show();
1705 proc.anrDialog = d;
1706 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001707
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001708 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001710 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1711 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1712 synchronized (ActivityManagerService.this) {
1713 ProcessRecord proc = (ProcessRecord) data.get("app");
1714 if (proc == null) {
1715 Slog.e(TAG, "App not found when showing strict mode dialog.");
1716 break;
1717 }
1718 if (proc.crashDialog != null) {
1719 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1720 return;
1721 }
1722 AppErrorResult res = (AppErrorResult) data.get("result");
1723 if (!mSleeping && !mShuttingDown) {
1724 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1725 d.show();
1726 proc.crashDialog = d;
1727 } else {
1728 // The device is asleep, so just pretend that the user
1729 // saw a crash dialog and hit "force quit".
1730 res.set(0);
1731 }
1732 }
1733 ensureBootCompleted();
1734 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 case SHOW_FACTORY_ERROR_MSG: {
1736 Dialog d = new FactoryErrorDialog(
1737 mContext, msg.getData().getCharSequence("msg"));
1738 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001739 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 } break;
1741 case UPDATE_CONFIGURATION_MSG: {
1742 final ContentResolver resolver = mContext.getContentResolver();
1743 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1744 } break;
1745 case GC_BACKGROUND_PROCESSES_MSG: {
1746 synchronized (ActivityManagerService.this) {
1747 performAppGcsIfAppropriateLocked();
1748 }
1749 } break;
1750 case WAIT_FOR_DEBUGGER_MSG: {
1751 synchronized (ActivityManagerService.this) {
1752 ProcessRecord app = (ProcessRecord)msg.obj;
1753 if (msg.arg1 != 0) {
1754 if (!app.waitedForDebugger) {
1755 Dialog d = new AppWaitingForDebuggerDialog(
1756 ActivityManagerService.this,
1757 mContext, app);
1758 app.waitDialog = d;
1759 app.waitedForDebugger = true;
1760 d.show();
1761 }
1762 } else {
1763 if (app.waitDialog != null) {
1764 app.waitDialog.dismiss();
1765 app.waitDialog = null;
1766 }
1767 }
1768 }
1769 } break;
1770 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001771 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 TAG, "Received BROADCAST_INTENT_MSG");
Christopher Tatef46723b2012-01-26 14:19:24 -08001773 BroadcastQueue queue = (BroadcastQueue) msg.obj;
1774 queue.processNextBroadcast(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 } break;
1776 case BROADCAST_TIMEOUT_MSG: {
Christopher Tatef46723b2012-01-26 14:19:24 -08001777 final BroadcastQueue queue = (BroadcastQueue) msg.obj;
Jeff Brown4d94a762010-09-23 11:33:28 -07001778 synchronized (ActivityManagerService.this) {
Christopher Tatef46723b2012-01-26 14:19:24 -08001779 queue.broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001783 if (mDidDexOpt) {
1784 mDidDexOpt = false;
1785 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1786 nmsg.obj = msg.obj;
1787 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1788 return;
1789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 serviceTimeout((ProcessRecord)msg.obj);
1791 } break;
1792 case UPDATE_TIME_ZONE: {
1793 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001794 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1795 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 if (r.thread != null) {
1797 try {
1798 r.thread.updateTimeZone();
1799 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001800 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 }
1802 }
1803 }
1804 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001805 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001806 case CLEAR_DNS_CACHE: {
1807 synchronized (ActivityManagerService.this) {
1808 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1809 ProcessRecord r = mLruProcesses.get(i);
1810 if (r.thread != null) {
1811 try {
1812 r.thread.clearDnsCache();
1813 } catch (RemoteException ex) {
1814 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1815 }
1816 }
1817 }
1818 }
1819 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001820 case UPDATE_HTTP_PROXY: {
1821 ProxyProperties proxy = (ProxyProperties)msg.obj;
1822 String host = "";
1823 String port = "";
1824 String exclList = "";
1825 if (proxy != null) {
1826 host = proxy.getHost();
1827 port = Integer.toString(proxy.getPort());
1828 exclList = proxy.getExclusionList();
1829 }
1830 synchronized (ActivityManagerService.this) {
1831 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1832 ProcessRecord r = mLruProcesses.get(i);
1833 if (r.thread != null) {
1834 try {
1835 r.thread.setHttpProxy(host, port, exclList);
1836 } catch (RemoteException ex) {
1837 Slog.w(TAG, "Failed to update http proxy for: " +
1838 r.info.processName);
1839 }
1840 }
1841 }
1842 }
1843 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 case SHOW_UID_ERROR_MSG: {
1845 // XXX This is a temporary dialog, no need to localize.
1846 AlertDialog d = new BaseErrorDialog(mContext);
1847 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1848 d.setCancelable(false);
1849 d.setTitle("System UIDs Inconsistent");
1850 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 +02001851 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1853 mUidAlert = d;
1854 d.show();
1855 } break;
1856 case IM_FEELING_LUCKY_MSG: {
1857 if (mUidAlert != null) {
1858 mUidAlert.dismiss();
1859 mUidAlert = null;
1860 }
1861 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001863 if (mDidDexOpt) {
1864 mDidDexOpt = false;
1865 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1866 nmsg.obj = msg.obj;
1867 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1868 return;
1869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 ProcessRecord app = (ProcessRecord)msg.obj;
1871 synchronized (ActivityManagerService.this) {
1872 processStartTimedOutLocked(app);
1873 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001874 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001875 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1876 synchronized (ActivityManagerService.this) {
1877 doPendingActivityLaunchesLocked(true);
1878 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001879 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001880 case KILL_APPLICATION_MSG: {
1881 synchronized (ActivityManagerService.this) {
1882 int uid = msg.arg1;
1883 boolean restart = (msg.arg2 == 1);
1884 String pkg = (String) msg.obj;
Christopher Tate3dacd842011-08-19 14:56:15 -07001885 forceStopPackageLocked(pkg, uid, restart, false, true, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001886 }
1887 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001888 case FINALIZE_PENDING_INTENT_MSG: {
1889 ((PendingIntentRecord)msg.obj).completeFinalize();
1890 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001891 case POST_HEAVY_NOTIFICATION_MSG: {
1892 INotificationManager inm = NotificationManager.getService();
1893 if (inm == null) {
1894 return;
1895 }
1896
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001897 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001898 ProcessRecord process = root.app;
1899 if (process == null) {
1900 return;
1901 }
1902
1903 try {
1904 Context context = mContext.createPackageContext(process.info.packageName, 0);
1905 String text = mContext.getString(R.string.heavy_weight_notification,
1906 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1907 Notification notification = new Notification();
1908 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1909 notification.when = 0;
1910 notification.flags = Notification.FLAG_ONGOING_EVENT;
1911 notification.tickerText = text;
1912 notification.defaults = 0; // please be quiet
1913 notification.sound = null;
1914 notification.vibrate = null;
1915 notification.setLatestEventInfo(context, text,
1916 mContext.getText(R.string.heavy_weight_notification_detail),
1917 PendingIntent.getActivity(mContext, 0, root.intent,
1918 PendingIntent.FLAG_CANCEL_CURRENT));
1919
1920 try {
1921 int[] outId = new int[1];
1922 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1923 notification, outId);
1924 } catch (RuntimeException e) {
1925 Slog.w(ActivityManagerService.TAG,
1926 "Error showing notification for heavy-weight app", e);
1927 } catch (RemoteException e) {
1928 }
1929 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001930 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001931 }
1932 } break;
1933 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1934 INotificationManager inm = NotificationManager.getService();
1935 if (inm == null) {
1936 return;
1937 }
1938 try {
1939 inm.cancelNotification("android",
1940 R.string.heavy_weight_notification);
1941 } catch (RuntimeException e) {
1942 Slog.w(ActivityManagerService.TAG,
1943 "Error canceling notification for service", e);
1944 } catch (RemoteException e) {
1945 }
1946 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001947 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1948 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001949 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001950 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001951 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1952 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001953 }
1954 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001955 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1956 synchronized (ActivityManagerService.this) {
1957 ActivityRecord ar = (ActivityRecord)msg.obj;
1958 if (mCompatModeDialog != null) {
1959 if (mCompatModeDialog.mAppInfo.packageName.equals(
1960 ar.info.applicationInfo.packageName)) {
1961 return;
1962 }
1963 mCompatModeDialog.dismiss();
1964 mCompatModeDialog = null;
1965 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001966 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001967 if (mCompatModePackages.getPackageAskCompatModeLocked(
1968 ar.packageName)) {
1969 int mode = mCompatModePackages.computeCompatModeLocked(
1970 ar.info.applicationInfo);
1971 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1972 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1973 mCompatModeDialog = new CompatModeDialog(
1974 ActivityManagerService.this, mContext,
1975 ar.info.applicationInfo);
1976 mCompatModeDialog.show();
1977 }
1978 }
1979 }
1980 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001981 break;
1982 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001983 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001984 final int pid = msg.arg1;
1985 final int uid = msg.arg2;
1986 final boolean foregroundActivities = (Boolean) msg.obj;
1987 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001988 break;
1989 }
1990 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001991 final int pid = msg.arg1;
1992 final int uid = msg.arg2;
1993 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001994 break;
1995 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001996 case REPORT_MEM_USAGE: {
1997 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
1998 if (!isDebuggable) {
1999 return;
2000 }
2001 synchronized (ActivityManagerService.this) {
2002 long now = SystemClock.uptimeMillis();
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002003 if (now < (mLastMemUsageReportTime+5*60*1000)) {
2004 // Don't report more than every 5 minutes to somewhat
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002005 // avoid spamming.
2006 return;
2007 }
2008 mLastMemUsageReportTime = now;
2009 }
2010 Thread thread = new Thread() {
2011 @Override public void run() {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002012 StringBuilder dropBuilder = new StringBuilder(1024);
2013 StringBuilder logBuilder = new StringBuilder(1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -08002014 StringWriter oomSw = new StringWriter();
2015 PrintWriter oomPw = new PrintWriter(oomSw);
2016 StringWriter catSw = new StringWriter();
2017 PrintWriter catPw = new PrintWriter(catSw);
2018 String[] emptyArgs = new String[] { };
2019 StringBuilder tag = new StringBuilder(128);
2020 StringBuilder stack = new StringBuilder(128);
2021 tag.append("Low on memory -- ");
2022 dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw,
2023 tag, stack);
2024 dropBuilder.append(stack);
2025 dropBuilder.append('\n');
2026 dropBuilder.append('\n');
2027 String oomString = oomSw.toString();
2028 dropBuilder.append(oomString);
2029 dropBuilder.append('\n');
2030 logBuilder.append(oomString);
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002031 try {
2032 java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
2033 "procrank", });
2034 final InputStreamReader converter = new InputStreamReader(
2035 proc.getInputStream());
2036 BufferedReader in = new BufferedReader(converter);
2037 String line;
2038 while (true) {
2039 line = in.readLine();
2040 if (line == null) {
2041 break;
2042 }
2043 if (line.length() > 0) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002044 logBuilder.append(line);
2045 logBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002046 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002047 dropBuilder.append(line);
2048 dropBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002049 }
2050 converter.close();
2051 } catch (IOException e) {
2052 }
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002053 synchronized (ActivityManagerService.this) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08002054 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002055 dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002056 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002057 dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002058 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002059 dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002060 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002061 dropBuilder.append(catSw.toString());
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08002062 addErrorToDropBox("lowmem", null, "system_server", null,
2063 null, tag.toString(), dropBuilder.toString(), null, null);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002064 Slog.i(TAG, logBuilder.toString());
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002065 synchronized (ActivityManagerService.this) {
2066 long now = SystemClock.uptimeMillis();
2067 if (mLastMemUsageReportTime < now) {
2068 mLastMemUsageReportTime = now;
2069 }
2070 }
2071 }
2072 };
2073 thread.start();
2074 break;
2075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 }
2077 }
2078 };
2079
2080 public static void setSystemProcess() {
2081 try {
2082 ActivityManagerService m = mSelf;
2083
2084 ServiceManager.addService("activity", m);
2085 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07002086 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
Jeff Brown6754ba22011-12-14 20:20:01 -08002087 ServiceManager.addService("dbinfo", new DbBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 if (MONITOR_CPU_USAGE) {
2089 ServiceManager.addService("cpuinfo", new CpuBinder(m));
2090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 ServiceManager.addService("permission", new PermissionController(m));
2092
2093 ApplicationInfo info =
2094 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07002095 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07002096 mSystemThread.installSystemApplicationInfo(info);
2097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 synchronized (mSelf) {
2099 ProcessRecord app = mSelf.newProcessRecordLocked(
2100 mSystemThread.getApplicationThread(), info,
2101 info.processName);
2102 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002103 app.pid = MY_PID;
Dianne Hackborn7d608422011-08-07 16:24:18 -07002104 app.maxAdj = ProcessList.SYSTEM_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
2106 synchronized (mSelf.mPidsSelfLocked) {
2107 mSelf.mPidsSelfLocked.put(app.pid, app);
2108 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002109 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 }
2111 } catch (PackageManager.NameNotFoundException e) {
2112 throw new RuntimeException(
2113 "Unable to find android system package", e);
2114 }
2115 }
2116
2117 public void setWindowManager(WindowManagerService wm) {
2118 mWindowManager = wm;
2119 }
2120
2121 public static final Context main(int factoryTest) {
2122 AThread thr = new AThread();
2123 thr.start();
2124
2125 synchronized (thr) {
2126 while (thr.mService == null) {
2127 try {
2128 thr.wait();
2129 } catch (InterruptedException e) {
2130 }
2131 }
2132 }
2133
2134 ActivityManagerService m = thr.mService;
2135 mSelf = m;
2136 ActivityThread at = ActivityThread.systemMain();
2137 mSystemThread = at;
2138 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08002139 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 m.mContext = context;
2141 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002142 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143
2144 m.mBatteryStatsService.publish(context);
2145 m.mUsageStatsService.publish(context);
2146
2147 synchronized (thr) {
2148 thr.mReady = true;
2149 thr.notifyAll();
2150 }
2151
2152 m.startRunning(null, null, null, null);
2153
2154 return context;
2155 }
2156
2157 public static ActivityManagerService self() {
2158 return mSelf;
2159 }
2160
2161 static class AThread extends Thread {
2162 ActivityManagerService mService;
2163 boolean mReady = false;
2164
2165 public AThread() {
2166 super("ActivityManager");
2167 }
2168
2169 public void run() {
2170 Looper.prepare();
2171
2172 android.os.Process.setThreadPriority(
2173 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07002174 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175
2176 ActivityManagerService m = new ActivityManagerService();
2177
2178 synchronized (this) {
2179 mService = m;
2180 notifyAll();
2181 }
2182
2183 synchronized (this) {
2184 while (!mReady) {
2185 try {
2186 wait();
2187 } catch (InterruptedException e) {
2188 }
2189 }
2190 }
2191
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07002192 // For debug builds, log event loop stalls to dropbox for analysis.
2193 if (StrictMode.conditionallyEnableDebugLogging()) {
2194 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
2195 }
2196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 Looper.loop();
2198 }
2199 }
2200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 static class MemBinder extends Binder {
2202 ActivityManagerService mActivityManagerService;
2203 MemBinder(ActivityManagerService activityManagerService) {
2204 mActivityManagerService = activityManagerService;
2205 }
2206
2207 @Override
2208 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07002209 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2210 != PackageManager.PERMISSION_GRANTED) {
2211 pw.println("Permission Denial: can't dump meminfo from from pid="
2212 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2213 + " without permission " + android.Manifest.permission.DUMP);
2214 return;
2215 }
2216
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08002217 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args,
Dianne Hackborn672342c2011-11-29 11:29:02 -08002218 false, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219 }
2220 }
2221
Chet Haase9c1e23b2011-03-24 10:51:31 -07002222 static class GraphicsBinder extends Binder {
2223 ActivityManagerService mActivityManagerService;
2224 GraphicsBinder(ActivityManagerService activityManagerService) {
2225 mActivityManagerService = activityManagerService;
2226 }
2227
2228 @Override
2229 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07002230 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2231 != PackageManager.PERMISSION_GRANTED) {
2232 pw.println("Permission Denial: can't dump gfxinfo from from pid="
2233 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2234 + " without permission " + android.Manifest.permission.DUMP);
2235 return;
2236 }
2237
Dianne Hackborne17aeb32011-04-07 15:11:57 -07002238 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07002239 }
2240 }
2241
Jeff Brown6754ba22011-12-14 20:20:01 -08002242 static class DbBinder extends Binder {
2243 ActivityManagerService mActivityManagerService;
2244 DbBinder(ActivityManagerService activityManagerService) {
2245 mActivityManagerService = activityManagerService;
2246 }
2247
2248 @Override
2249 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2250 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2251 != PackageManager.PERMISSION_GRANTED) {
2252 pw.println("Permission Denial: can't dump dbinfo from from pid="
2253 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2254 + " without permission " + android.Manifest.permission.DUMP);
2255 return;
2256 }
2257
2258 mActivityManagerService.dumpDbInfo(fd, pw, args);
2259 }
2260 }
2261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 static class CpuBinder extends Binder {
2263 ActivityManagerService mActivityManagerService;
2264 CpuBinder(ActivityManagerService activityManagerService) {
2265 mActivityManagerService = activityManagerService;
2266 }
2267
2268 @Override
2269 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07002270 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2271 != PackageManager.PERMISSION_GRANTED) {
2272 pw.println("Permission Denial: can't dump cpuinfo from from pid="
2273 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2274 + " without permission " + android.Manifest.permission.DUMP);
2275 return;
2276 }
2277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002279 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
2280 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
2281 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 }
2283 }
2284 }
2285
2286 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002287 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07002288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 File dataDir = Environment.getDataDirectory();
2290 File systemDir = new File(dataDir, "system");
2291 systemDir.mkdirs();
2292 mBatteryStatsService = new BatteryStatsService(new File(
2293 systemDir, "batterystats.bin").toString());
2294 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07002295 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07002296 mOnBattery = DEBUG_POWER ? true
2297 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002298 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002300 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07002301 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302
Jack Palevichb90d28c2009-07-22 15:35:24 -07002303 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
2304 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
2305
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002306 mConfiguration.setToDefaults();
2307 mConfiguration.locale = Locale.getDefault();
Dianne Hackborn813075a62011-11-14 17:45:19 -08002308 mConfigurationSeq = mConfiguration.seq = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 mProcessStats.init();
2310
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002311 mCompatModePackages = new CompatModePackages(this, systemDir);
2312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 // Add ourself to the Watchdog monitors.
2314 Watchdog.getInstance().addMonitor(this);
2315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002316 mProcessStatsThread = new Thread("ProcessStats") {
2317 public void run() {
2318 while (true) {
2319 try {
2320 try {
2321 synchronized(this) {
2322 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002323 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002325 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 // + ", write delay=" + nextWriteDelay);
2327 if (nextWriteDelay < nextCpuDelay) {
2328 nextCpuDelay = nextWriteDelay;
2329 }
2330 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002331 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 this.wait(nextCpuDelay);
2333 }
2334 }
2335 } catch (InterruptedException e) {
2336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 updateCpuStatsNow();
2338 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002339 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 }
2341 }
2342 }
2343 };
2344 mProcessStatsThread.start();
2345 }
2346
2347 @Override
2348 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
2349 throws RemoteException {
2350 try {
2351 return super.onTransact(code, data, reply, flags);
2352 } catch (RuntimeException e) {
2353 // The activity manager only throws security exceptions, so let's
2354 // log all others.
2355 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002356 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 }
2358 throw e;
2359 }
2360 }
2361
2362 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002363 final long now = SystemClock.uptimeMillis();
2364 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
2365 return;
2366 }
2367 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
2368 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 mProcessStatsThread.notify();
2370 }
2371 }
2372 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 void updateCpuStatsNow() {
2375 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002376 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 final long now = SystemClock.uptimeMillis();
2378 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002381 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
2382 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 haveNewCpuStats = true;
2384 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002385 //Slog.i(TAG, mProcessStats.printCurrentState());
2386 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 // + mProcessStats.getTotalCpuPercent() + "%");
2388
Joe Onorato8a9b2202010-02-26 18:56:32 -08002389 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 if ("true".equals(SystemProperties.get("events.cpu"))) {
2391 int user = mProcessStats.getLastUserTime();
2392 int system = mProcessStats.getLastSystemTime();
2393 int iowait = mProcessStats.getLastIoWaitTime();
2394 int irq = mProcessStats.getLastIrqTime();
2395 int softIrq = mProcessStats.getLastSoftIrqTime();
2396 int idle = mProcessStats.getLastIdleTime();
2397
2398 int total = user + system + iowait + irq + softIrq + idle;
2399 if (total == 0) total = 1;
2400
Doug Zongker2bec3d42009-12-04 12:52:44 -08002401 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 ((user+system+iowait+irq+softIrq) * 100) / total,
2403 (user * 100) / total,
2404 (system * 100) / total,
2405 (iowait * 100) / total,
2406 (irq * 100) / total,
2407 (softIrq * 100) / total);
2408 }
2409 }
2410
Amith Yamasanie43530a2009-08-21 13:11:37 -07002411 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07002412 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002413 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 synchronized(mPidsSelfLocked) {
2415 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002416 if (mOnBattery) {
2417 int perc = bstats.startAddingCpuLocked();
2418 int totalUTime = 0;
2419 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07002420 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07002422 ProcessStats.Stats st = mProcessStats.getStats(i);
2423 if (!st.working) {
2424 continue;
2425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002427 int otherUTime = (st.rel_utime*perc)/100;
2428 int otherSTime = (st.rel_stime*perc)/100;
2429 totalUTime += otherUTime;
2430 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 if (pr != null) {
2432 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002433 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
2434 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07002435 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07002436 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002437 } else {
2438 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07002439 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002440 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002441 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
2442 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07002443 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 }
2446 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002447 bstats.finishAddingCpuLocked(perc, totalUTime,
2448 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449 }
2450 }
2451 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
2454 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07002455 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 }
2457 }
2458 }
2459 }
2460
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002461 @Override
2462 public void batteryNeedsCpuUpdate() {
2463 updateCpuStatsNow();
2464 }
2465
2466 @Override
2467 public void batteryPowerChanged(boolean onBattery) {
2468 // When plugging in, update the CPU stats first before changing
2469 // the plug state.
2470 updateCpuStatsNow();
2471 synchronized (this) {
2472 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07002473 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002474 }
2475 }
2476 }
2477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 /**
2479 * Initialize the application bind args. These are passed to each
2480 * process when the bindApplication() IPC is sent to the process. They're
2481 * lazily setup to make sure the services are running when they're asked for.
2482 */
2483 private HashMap<String, IBinder> getCommonServicesLocked() {
2484 if (mAppBindArgs == null) {
2485 mAppBindArgs = new HashMap<String, IBinder>();
2486
2487 // Setup the application init args
2488 mAppBindArgs.put("package", ServiceManager.getService("package"));
2489 mAppBindArgs.put("window", ServiceManager.getService("window"));
2490 mAppBindArgs.put(Context.ALARM_SERVICE,
2491 ServiceManager.getService(Context.ALARM_SERVICE));
2492 }
2493 return mAppBindArgs;
2494 }
2495
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002496 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 if (mFocusedActivity != r) {
2498 mFocusedActivity = r;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002499 if (r != null) {
2500 mWindowManager.setFocusedApp(r.appToken, true);
2501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 }
2503 }
2504
Dianne Hackborn906497c2010-05-10 15:57:38 -07002505 private final void updateLruProcessInternalLocked(ProcessRecord app,
2506 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002508 int lrui = mLruProcesses.indexOf(app);
2509 if (lrui >= 0) mLruProcesses.remove(lrui);
2510
2511 int i = mLruProcesses.size()-1;
2512 int skipTop = 0;
2513
Dianne Hackborn906497c2010-05-10 15:57:38 -07002514 app.lruSeq = mLruSeq;
2515
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002516 // compute the new weight for this process.
2517 if (updateActivityTime) {
2518 app.lastActivityTime = SystemClock.uptimeMillis();
2519 }
2520 if (app.activities.size() > 0) {
2521 // If this process has activities, we more strongly want to keep
2522 // it around.
2523 app.lruWeight = app.lastActivityTime;
2524 } else if (app.pubProviders.size() > 0) {
2525 // If this process contains content providers, we want to keep
2526 // it a little more strongly.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002527 app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002528 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002529 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002530 } else {
2531 // If this process doesn't have activities, we less strongly
2532 // want to keep it around, and generally want to avoid getting
2533 // in front of any very recently used activities.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002534 app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002535 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002536 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002537 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07002538
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002539 while (i >= 0) {
2540 ProcessRecord p = mLruProcesses.get(i);
2541 // If this app shouldn't be in front of the first N background
2542 // apps, then skip over that many that are currently hidden.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002543 if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002544 skipTop--;
2545 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07002546 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002547 mLruProcesses.add(i+1, app);
2548 break;
2549 }
2550 i--;
2551 }
2552 if (i < 0) {
2553 mLruProcesses.add(0, app);
2554 }
2555
Dianne Hackborn906497c2010-05-10 15:57:38 -07002556 // If the app is currently using a content provider or service,
2557 // bump those processes as well.
2558 if (app.connections.size() > 0) {
2559 for (ConnectionRecord cr : app.connections) {
2560 if (cr.binding != null && cr.binding.service != null
2561 && cr.binding.service.app != null
2562 && cr.binding.service.app.lruSeq != mLruSeq) {
2563 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
2564 updateActivityTime, i+1);
2565 }
2566 }
2567 }
2568 if (app.conProviders.size() > 0) {
2569 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07002570 if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
2571 updateLruProcessInternalLocked(cpr.proc, oomAdj,
Dianne Hackborn906497c2010-05-10 15:57:38 -07002572 updateActivityTime, i+1);
2573 }
2574 }
2575 }
2576
Joe Onorato8a9b2202010-02-26 18:56:32 -08002577 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 if (oomAdj) {
2579 updateOomAdjLocked();
2580 }
2581 }
2582
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002583 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07002584 boolean oomAdj, boolean updateActivityTime) {
2585 mLruSeq++;
2586 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
2587 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07002588
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002589 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 String processName, int uid) {
2591 if (uid == Process.SYSTEM_UID) {
2592 // The system gets to run in any process. If there are multiple
2593 // processes with the same uid, just pick the first (this
2594 // should never happen).
2595 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
2596 processName);
2597 return procs != null ? procs.valueAt(0) : null;
2598 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002599 // uid = applyUserId(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 ProcessRecord proc = mProcessNames.get(processName, uid);
2601 return proc;
2602 }
2603
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002604 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002605 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002606 try {
2607 if (pm.performDexOpt(packageName)) {
2608 mDidDexOpt = true;
2609 }
2610 } catch (RemoteException e) {
2611 }
2612 }
2613
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002614 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 int transit = mWindowManager.getPendingAppTransition();
2616 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2617 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
2618 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
2619 }
2620
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002623 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2625 // We don't have to do anything more if:
2626 // (1) There is an existing application record; and
2627 // (2) The caller doesn't think it is dead, OR there is no thread
2628 // object attached to it so we know it couldn't have crashed; and
2629 // (3) There is a pid assigned to it, so it is either starting or
2630 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002631 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 + " app=" + app + " knownToBeDead=" + knownToBeDead
2633 + " thread=" + (app != null ? app.thread : null)
2634 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002635 if (app != null && app.pid > 0) {
2636 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002637 // We already have the app running, or are waiting for it to
2638 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002639 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002640 // If this is a new package in the process, add the package to the list
2641 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01002642 return app;
2643 } else {
2644 // An application record is attached to a previous process,
2645 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002646 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002647 handleAppDiedLocked(app, true, true);
Magnus Edlund7bb25812010-02-24 15:45:06 +01002648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 String hostingNameStr = hostingName != null
2652 ? hostingName.flattenToShortString() : null;
2653
2654 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2655 // If we are in the background, then check to see if this process
2656 // is bad. If so, we will just silently fail.
2657 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002658 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
2659 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 return null;
2661 }
2662 } else {
2663 // When the user is explicitly starting a process, then clear its
2664 // crash count so that we won't make it bad until they see at
2665 // least one crash dialog again, and make the process good again
2666 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002667 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
2668 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 mProcessCrashTimes.remove(info.processName, info.uid);
2670 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002671 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 info.processName);
2673 mBadProcesses.remove(info.processName, info.uid);
2674 if (app != null) {
2675 app.bad = false;
2676 }
2677 }
2678 }
2679
2680 if (app == null) {
2681 app = newProcessRecordLocked(null, info, processName);
2682 mProcessNames.put(processName, info.uid, app);
2683 } else {
2684 // If this is a new package in the process, add the package to the list
2685 app.addPackage(info.packageName);
2686 }
2687
2688 // If the system is not ready yet, then hold off on starting this
2689 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002690 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002691 && !isAllowedWhileBooting(info)
2692 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 if (!mProcessesOnHold.contains(app)) {
2694 mProcessesOnHold.add(app);
2695 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002696 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 return app;
2698 }
2699
2700 startProcessLocked(app, hostingType, hostingNameStr);
2701 return (app.pid != 0) ? app : null;
2702 }
2703
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002704 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2705 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2706 }
2707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 private final void startProcessLocked(ProcessRecord app,
2709 String hostingType, String hostingNameStr) {
2710 if (app.pid > 0 && app.pid != MY_PID) {
2711 synchronized (mPidsSelfLocked) {
2712 mPidsSelfLocked.remove(app.pid);
2713 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2714 }
2715 app.pid = 0;
2716 }
2717
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002718 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
2719 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 mProcessesOnHold.remove(app);
2721
2722 updateCpuStats();
2723
2724 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2725 mProcDeaths[0] = 0;
2726
2727 try {
2728 int uid = app.info.uid;
Amith Yamasani742a6712011-05-04 14:49:28 -07002729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 int[] gids = null;
2731 try {
2732 gids = mContext.getPackageManager().getPackageGids(
2733 app.info.packageName);
2734 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002735 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 }
2737 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2738 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2739 && mTopComponent != null
2740 && app.processName.equals(mTopComponent.getPackageName())) {
2741 uid = 0;
2742 }
2743 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2744 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2745 uid = 0;
2746 }
2747 }
2748 int debugFlags = 0;
2749 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2750 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07002751 // Also turn on CheckJNI for debuggable apps. It's quite
2752 // awkward to turn on otherwise.
2753 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002755 // Run the app in safe mode if its manifest requests so or the
2756 // system is booted in safe mode.
2757 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2758 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002759 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2762 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2763 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07002764 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
2765 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
2766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 if ("1".equals(SystemProperties.get("debug.assert"))) {
2768 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2769 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07002770
2771 // Start the process. It will either succeed and return a result containing
2772 // the PID of the new process, or else throw a RuntimeException.
2773 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07002774 app.processName, uid, uid, gids, debugFlags,
2775 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07002776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002777 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2778 synchronized (bs) {
2779 if (bs.isOnBattery()) {
2780 app.batteryStats.incStartsLocked();
2781 }
2782 }
2783
Jeff Brown3f9dd282011-07-08 20:02:19 -07002784 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 app.processName, hostingType,
2786 hostingNameStr != null ? hostingNameStr : "");
2787
2788 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07002789 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 }
2791
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002792 StringBuilder buf = mStringBuilder;
2793 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 buf.append("Start proc ");
2795 buf.append(app.processName);
2796 buf.append(" for ");
2797 buf.append(hostingType);
2798 if (hostingNameStr != null) {
2799 buf.append(" ");
2800 buf.append(hostingNameStr);
2801 }
2802 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07002803 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 buf.append(" uid=");
2805 buf.append(uid);
2806 buf.append(" gids={");
2807 if (gids != null) {
2808 for (int gi=0; gi<gids.length; gi++) {
2809 if (gi != 0) buf.append(", ");
2810 buf.append(gids[gi]);
2811
2812 }
2813 }
2814 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002815 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07002816 app.pid = startResult.pid;
2817 app.usingWrapper = startResult.usingWrapper;
2818 app.removed = false;
2819 synchronized (mPidsSelfLocked) {
2820 this.mPidsSelfLocked.put(startResult.pid, app);
2821 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2822 msg.obj = app;
2823 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2824 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825 }
2826 } catch (RuntimeException e) {
2827 // XXX do better error recovery.
2828 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002829 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830 }
2831 }
2832
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002833 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 if (resumed) {
2835 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2836 } else {
2837 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2838 }
2839 }
2840
Amith Yamasani742a6712011-05-04 14:49:28 -07002841 boolean startHomeActivityLocked(int userId) {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002842 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2843 && mTopAction == null) {
2844 // We are running in factory test mode, but unable to find
2845 // the factory test app, so just sit around displaying the
2846 // error message and don't try to start anything.
2847 return false;
2848 }
2849 Intent intent = new Intent(
2850 mTopAction,
2851 mTopData != null ? Uri.parse(mTopData) : null);
2852 intent.setComponent(mTopComponent);
2853 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2854 intent.addCategory(Intent.CATEGORY_HOME);
2855 }
2856 ActivityInfo aInfo =
2857 intent.resolveActivityInfo(mContext.getPackageManager(),
2858 STOCK_PM_FLAGS);
2859 if (aInfo != null) {
2860 intent.setComponent(new ComponentName(
2861 aInfo.applicationInfo.packageName, aInfo.name));
2862 // Don't do this if the home app is currently being
2863 // instrumented.
Amith Yamasani742a6712011-05-04 14:49:28 -07002864 aInfo = new ActivityInfo(aInfo);
2865 aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002866 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2867 aInfo.applicationInfo.uid);
2868 if (app == null || app.instrumentationClass == null) {
2869 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002870 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002871 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002872 }
2873 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002874
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002875 return true;
2876 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002877
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002878 /**
2879 * Starts the "new version setup screen" if appropriate.
2880 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002881 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002882 // Only do this once per boot.
2883 if (mCheckedForSetup) {
2884 return;
2885 }
2886
2887 // We will show this screen if the current one is a different
2888 // version than the last one shown, and we are not running in
2889 // low-level factory test mode.
2890 final ContentResolver resolver = mContext.getContentResolver();
2891 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2892 Settings.Secure.getInt(resolver,
2893 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2894 mCheckedForSetup = true;
2895
2896 // See if we should be showing the platform update setup UI.
2897 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2898 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2899 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2900
2901 // We don't allow third party apps to replace this.
2902 ResolveInfo ri = null;
2903 for (int i=0; ris != null && i<ris.size(); i++) {
2904 if ((ris.get(i).activityInfo.applicationInfo.flags
2905 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2906 ri = ris.get(i);
2907 break;
2908 }
2909 }
2910
2911 if (ri != null) {
2912 String vers = ri.activityInfo.metaData != null
2913 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2914 : null;
2915 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2916 vers = ri.activityInfo.applicationInfo.metaData.getString(
2917 Intent.METADATA_SETUP_VERSION);
2918 }
2919 String lastVers = Settings.Secure.getString(
2920 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2921 if (vers != null && !vers.equals(lastVers)) {
2922 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2923 intent.setComponent(new ComponentName(
2924 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002925 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002926 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002927 }
2928 }
2929 }
2930 }
2931
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002932 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002933 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002934 }
2935
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002936 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002937 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002938 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2939 }
2940 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002941
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002942 public void setFrontActivityScreenCompatMode(int mode) {
2943 synchronized (this) {
2944 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2945 }
2946 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002947
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002948 public int getPackageScreenCompatMode(String packageName) {
2949 synchronized (this) {
2950 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2951 }
2952 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002953
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002954 public void setPackageScreenCompatMode(String packageName, int mode) {
2955 synchronized (this) {
2956 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002957 }
2958 }
2959
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002960 public boolean getPackageAskScreenCompat(String packageName) {
2961 synchronized (this) {
2962 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2963 }
2964 }
2965
2966 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2967 synchronized (this) {
2968 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2969 }
2970 }
2971
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002972 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002973 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002974
2975 final int identHash = System.identityHashCode(r);
2976 updateUsageStats(r, true);
2977
2978 int i = mWatchers.beginBroadcast();
2979 while (i > 0) {
2980 i--;
2981 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2982 if (w != null) {
2983 try {
2984 w.activityResuming(identHash);
2985 } catch (RemoteException e) {
2986 }
2987 }
2988 }
2989 mWatchers.finishBroadcast();
2990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991
Jeff Sharkeya4620792011-05-20 15:29:23 -07002992 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2993 int i = mProcessObservers.beginBroadcast();
2994 while (i > 0) {
2995 i--;
2996 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2997 if (observer != null) {
2998 try {
2999 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
3000 } catch (RemoteException e) {
3001 }
3002 }
3003 }
3004 mProcessObservers.finishBroadcast();
3005 }
3006
3007 private void dispatchProcessDied(int pid, int uid) {
3008 int i = mProcessObservers.beginBroadcast();
3009 while (i > 0) {
3010 i--;
3011 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
3012 if (observer != null) {
3013 try {
3014 observer.onProcessDied(pid, uid);
3015 } catch (RemoteException e) {
3016 }
3017 }
3018 }
3019 mProcessObservers.finishBroadcast();
3020 }
3021
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003022 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003023 final int N = mPendingActivityLaunches.size();
3024 if (N <= 0) {
3025 return;
3026 }
3027 for (int i=0; i<N; i++) {
3028 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003029 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003030 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3031 doResume && i == (N-1));
3032 }
3033 mPendingActivityLaunches.clear();
3034 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003035
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003036 public final int startActivity(IApplicationThread caller,
3037 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3038 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003039 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
3040 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Amith Yamasani742a6712011-05-04 14:49:28 -07003041 int userId = 0;
3042 if (intent.getCategories() != null && intent.getCategories().contains(Intent.CATEGORY_HOME)) {
3043 // Requesting home, set the identity to the current user
3044 // HACK!
3045 userId = mCurrentUserId;
3046 } else {
3047 // TODO: Fix this in a better way - calls coming from SystemUI should probably carry
3048 // the current user's userId
3049 if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
3050 userId = 0;
3051 } else {
3052 userId = Binder.getOrigCallingUser();
3053 }
3054 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003055 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Amith Yamasani742a6712011-05-04 14:49:28 -07003056 grantedUriPermissions, grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded,
3057 debug, profileFile, profileFd, autoStopProfiler, null, null, userId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003058 }
3059
3060 public final WaitResult startActivityAndWait(IApplicationThread caller,
3061 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3062 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003063 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
3064 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003065 WaitResult res = new WaitResult();
Amith Yamasani742a6712011-05-04 14:49:28 -07003066 int userId = Binder.getOrigCallingUser();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003067 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003068 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003069 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
Amith Yamasani742a6712011-05-04 14:49:28 -07003070 res, null, userId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003071 return res;
3072 }
3073
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003074 public final int startActivityWithConfig(IApplicationThread caller,
3075 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3076 int grantedMode, IBinder resultTo,
3077 String resultWho, int requestCode, boolean onlyIfNeeded,
3078 boolean debug, Configuration config) {
Amith Yamasani742a6712011-05-04 14:49:28 -07003079 int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003080 grantedUriPermissions, grantedMode, resultTo, resultWho,
Amith Yamasani742a6712011-05-04 14:49:28 -07003081 requestCode, onlyIfNeeded,
3082 debug, null, null, false, null, config, Binder.getOrigCallingUser());
3083 return ret;
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003084 }
3085
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003086 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003087 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003088 IBinder resultTo, String resultWho, int requestCode,
3089 int flagsMask, int flagsValues) {
3090 // Refuse possible leaked file descriptors
3091 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3092 throw new IllegalArgumentException("File descriptors passed in Intent");
3093 }
3094
3095 IIntentSender sender = intent.getTarget();
3096 if (!(sender instanceof PendingIntentRecord)) {
3097 throw new IllegalArgumentException("Bad PendingIntent object");
3098 }
3099
3100 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003101
3102 synchronized (this) {
3103 // If this is coming from the currently resumed activity, it is
3104 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003105 if (mMainStack.mResumedActivity != null
3106 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003107 Binder.getCallingUid()) {
3108 mAppSwitchesAllowedTime = 0;
3109 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003110 }
Amith Yamasani742a6712011-05-04 14:49:28 -07003111 int ret = pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003112 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
Amith Yamasani742a6712011-05-04 14:49:28 -07003113 return ret;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003114 }
3115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 public boolean startNextMatchingActivity(IBinder callingActivity,
3117 Intent intent) {
3118 // Refuse possible leaked file descriptors
3119 if (intent != null && intent.hasFileDescriptors() == true) {
3120 throw new IllegalArgumentException("File descriptors passed in Intent");
3121 }
3122
3123 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003124 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
3125 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 return false;
3127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 if (r.app == null || r.app.thread == null) {
3129 // The caller is not running... d'oh!
3130 return false;
3131 }
3132 intent = new Intent(intent);
3133 // The caller is not allowed to change the data.
3134 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3135 // And we are resetting to find the next component...
3136 intent.setComponent(null);
3137
3138 ActivityInfo aInfo = null;
3139 try {
3140 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003141 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003143 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144
3145 // Look for the original activity in the list...
3146 final int N = resolves != null ? resolves.size() : 0;
3147 for (int i=0; i<N; i++) {
3148 ResolveInfo rInfo = resolves.get(i);
3149 if (rInfo.activityInfo.packageName.equals(r.packageName)
3150 && rInfo.activityInfo.name.equals(r.info.name)) {
3151 // We found the current one... the next matching is
3152 // after it.
3153 i++;
3154 if (i<N) {
3155 aInfo = resolves.get(i).activityInfo;
3156 }
3157 break;
3158 }
3159 }
3160 } catch (RemoteException e) {
3161 }
3162
3163 if (aInfo == null) {
3164 // Nobody who is next!
3165 return false;
3166 }
3167
3168 intent.setComponent(new ComponentName(
3169 aInfo.applicationInfo.packageName, aInfo.name));
3170 intent.setFlags(intent.getFlags()&~(
3171 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3172 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3173 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3174 Intent.FLAG_ACTIVITY_NEW_TASK));
3175
3176 // Okay now we need to start the new activity, replacing the
3177 // currently running activity. This is a little tricky because
3178 // we want to start the new one as if the current one is finished,
3179 // but not finish the current one first so that there is no flicker.
3180 // And thus...
3181 final boolean wasFinishing = r.finishing;
3182 r.finishing = true;
3183
3184 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003185 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 final String resultWho = r.resultWho;
3187 final int requestCode = r.requestCode;
3188 r.resultTo = null;
3189 if (resultTo != null) {
3190 resultTo.removeResultsLocked(r, resultWho, requestCode);
3191 }
3192
3193 final long origId = Binder.clearCallingIdentity();
3194 // XXX we are not dealing with propagating grantedUriPermissions...
3195 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003196 int res = mMainStack.startActivityLocked(r.app.thread, intent,
Dianne Hackbornbe707852011-11-11 14:32:10 -08003197 r.resolvedType, null, 0, aInfo,
3198 resultTo != null ? resultTo.appToken : null, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003199 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 Binder.restoreCallingIdentity(origId);
3201
3202 r.finishing = wasFinishing;
3203 if (res != START_SUCCESS) {
3204 return false;
3205 }
3206 return true;
3207 }
3208 }
3209
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003210 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 Intent intent, String resolvedType, IBinder resultTo,
3212 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003213
3214 // This is so super not safe, that only the system (or okay root)
3215 // can do it.
Amith Yamasani742a6712011-05-04 14:49:28 -07003216 int userId = Binder.getOrigCallingUser();
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003217 final int callingUid = Binder.getCallingUid();
3218 if (callingUid != 0 && callingUid != Process.myUid()) {
3219 throw new SecurityException(
3220 "startActivityInPackage only available to the system");
3221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222
Amith Yamasani742a6712011-05-04 14:49:28 -07003223 int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003224 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
Amith Yamasani742a6712011-05-04 14:49:28 -07003225 null, null, false, null, null, userId);
3226 return ret;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003227 }
3228
3229 public final int startActivities(IApplicationThread caller,
3230 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
Amith Yamasani742a6712011-05-04 14:49:28 -07003231 int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
3232 Binder.getOrigCallingUser());
3233 return ret;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003234 }
3235
3236 public final int startActivitiesInPackage(int uid,
3237 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
3238
3239 // This is so super not safe, that only the system (or okay root)
3240 // can do it.
3241 final int callingUid = Binder.getCallingUid();
3242 if (callingUid != 0 && callingUid != Process.myUid()) {
3243 throw new SecurityException(
3244 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 }
Amith Yamasani742a6712011-05-04 14:49:28 -07003246 int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
3247 UserId.getUserId(uid));
3248 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
3250
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003251 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08003253 // Quick case: check if the top-most recent task is the same.
3254 if (N > 0 && mRecentTasks.get(0) == task) {
3255 return;
3256 }
3257 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 for (int i=0; i<N; i++) {
3259 TaskRecord tr = mRecentTasks.get(i);
Amith Yamasani742a6712011-05-04 14:49:28 -07003260 if (task.userId == tr.userId
3261 && ((task.affinity != null && task.affinity.equals(tr.affinity))
3262 || (task.intent != null && task.intent.filterEquals(tr.intent)))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 mRecentTasks.remove(i);
3264 i--;
3265 N--;
3266 if (task.intent == null) {
3267 // If the new recent task we are adding is not fully
3268 // specified, then replace it with the existing recent task.
3269 task = tr;
3270 }
3271 }
3272 }
3273 if (N >= MAX_RECENT_TASKS) {
3274 mRecentTasks.remove(N-1);
3275 }
3276 mRecentTasks.add(0, task);
3277 }
3278
3279 public void setRequestedOrientation(IBinder token,
3280 int requestedOrientation) {
3281 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003282 ActivityRecord r = mMainStack.isInStackLocked(token);
3283 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 return;
3285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbe707852011-11-11 14:32:10 -08003287 mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003289 mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -08003290 r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 if (config != null) {
3292 r.frozenBeforeDestroy = true;
Dianne Hackborn813075a62011-11-14 17:45:19 -08003293 if (!updateConfigurationLocked(config, r, false, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003294 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 }
3296 }
3297 Binder.restoreCallingIdentity(origId);
3298 }
3299 }
3300
3301 public int getRequestedOrientation(IBinder token) {
3302 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003303 ActivityRecord r = mMainStack.isInStackLocked(token);
3304 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3306 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08003307 return mWindowManager.getAppOrientation(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 }
3309 }
3310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 /**
3312 * This is the internal entry point for handling Activity.finish().
3313 *
3314 * @param token The Binder token referencing the Activity we want to finish.
3315 * @param resultCode Result code, if any, from this Activity.
3316 * @param resultData Result data (Intent), if any, from this Activity.
3317 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11003318 * @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 -08003319 */
3320 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
3321 // Refuse possible leaked file descriptors
3322 if (resultData != null && resultData.hasFileDescriptors() == true) {
3323 throw new IllegalArgumentException("File descriptors passed in Intent");
3324 }
3325
3326 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003327 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003329 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 if (next != null) {
3331 // ask watcher if this is allowed
3332 boolean resumeOK = true;
3333 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003334 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003336 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 }
3338
3339 if (!resumeOK) {
3340 return false;
3341 }
3342 }
3343 }
3344 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003345 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 resultData, "app-request");
3347 Binder.restoreCallingIdentity(origId);
3348 return res;
3349 }
3350 }
3351
Dianne Hackborn860755f2010-06-03 18:47:52 -07003352 public final void finishHeavyWeightApp() {
3353 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3354 != PackageManager.PERMISSION_GRANTED) {
3355 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
3356 + Binder.getCallingPid()
3357 + ", uid=" + Binder.getCallingUid()
3358 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
3359 Slog.w(TAG, msg);
3360 throw new SecurityException(msg);
3361 }
3362
3363 synchronized(this) {
3364 if (mHeavyWeightProcess == null) {
3365 return;
3366 }
3367
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003368 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07003369 mHeavyWeightProcess.activities);
3370 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003371 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003372 if (!r.finishing) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003373 int index = mMainStack.indexOfTokenLocked(r.appToken);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003374 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003375 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07003376 null, "finish-heavy");
3377 }
3378 }
3379 }
3380
3381 mHeavyWeightProcess = null;
3382 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3383 }
3384 }
3385
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07003386 public void crashApplication(int uid, int initialPid, String packageName,
3387 String message) {
3388 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3389 != PackageManager.PERMISSION_GRANTED) {
3390 String msg = "Permission Denial: crashApplication() from pid="
3391 + Binder.getCallingPid()
3392 + ", uid=" + Binder.getCallingUid()
3393 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
3394 Slog.w(TAG, msg);
3395 throw new SecurityException(msg);
3396 }
3397
3398 synchronized(this) {
3399 ProcessRecord proc = null;
3400
3401 // Figure out which process to kill. We don't trust that initialPid
3402 // still has any relation to current pids, so must scan through the
3403 // list.
3404 synchronized (mPidsSelfLocked) {
3405 for (int i=0; i<mPidsSelfLocked.size(); i++) {
3406 ProcessRecord p = mPidsSelfLocked.valueAt(i);
3407 if (p.info.uid != uid) {
3408 continue;
3409 }
3410 if (p.pid == initialPid) {
3411 proc = p;
3412 break;
3413 }
3414 for (String str : p.pkgList) {
3415 if (str.equals(packageName)) {
3416 proc = p;
3417 }
3418 }
3419 }
3420 }
3421
3422 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07003423 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07003424 + " initialPid=" + initialPid
3425 + " packageName=" + packageName);
3426 return;
3427 }
3428
3429 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07003430 if (proc.pid == Process.myPid()) {
3431 Log.w(TAG, "crashApplication: trying to crash self!");
3432 return;
3433 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07003434 long ident = Binder.clearCallingIdentity();
3435 try {
3436 proc.thread.scheduleCrash(message);
3437 } catch (RemoteException e) {
3438 }
3439 Binder.restoreCallingIdentity(ident);
3440 }
3441 }
3442 }
3443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 public final void finishSubActivity(IBinder token, String resultWho,
3445 int requestCode) {
3446 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003447 ActivityRecord self = mMainStack.isInStackLocked(token);
3448 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 return;
3450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451
3452 final long origId = Binder.clearCallingIdentity();
3453
3454 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003455 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3456 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 if (r.resultTo == self && r.requestCode == requestCode) {
3458 if ((r.resultWho == null && resultWho == null) ||
3459 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003460 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 Activity.RESULT_CANCELED, null, "request-sub");
3462 }
3463 }
3464 }
3465
3466 Binder.restoreCallingIdentity(origId);
3467 }
3468 }
3469
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003470 public boolean willActivityBeVisible(IBinder token) {
3471 synchronized(this) {
3472 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003473 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3474 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08003475 if (r.appToken == token) {
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003476 return true;
3477 }
3478 if (r.fullscreen && !r.finishing) {
3479 return false;
3480 }
3481 }
3482 return true;
3483 }
3484 }
3485
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003486 public void overridePendingTransition(IBinder token, String packageName,
3487 int enterAnim, int exitAnim) {
3488 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003489 ActivityRecord self = mMainStack.isInStackLocked(token);
3490 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003491 return;
3492 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003493
3494 final long origId = Binder.clearCallingIdentity();
3495
3496 if (self.state == ActivityState.RESUMED
3497 || self.state == ActivityState.PAUSING) {
3498 mWindowManager.overridePendingAppTransition(packageName,
3499 enterAnim, exitAnim);
3500 }
3501
3502 Binder.restoreCallingIdentity(origId);
3503 }
3504 }
3505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 * Main function for removing an existing process from the activity manager
3508 * as a result of that process going away. Clears out all connections
3509 * to the process.
3510 */
3511 private final void handleAppDiedLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003512 boolean restarting, boolean allowRestart) {
3513 cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003515 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 }
3517
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003518 if (mProfileProc == app) {
3519 clearProfilerLocked();
3520 }
3521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003523 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
3524 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
3525 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003527 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
3528 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 }
3530
3531 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003532 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533
3534 boolean atTop = true;
3535 boolean hasVisibleActivities = false;
3536
3537 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003538 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003539 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 TAG, "Removing app " + app + " from history with " + i + " entries");
3541 while (i > 0) {
3542 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003543 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003544 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 TAG, "Record #" + i + " " + r + ": app=" + r.app);
3546 if (r.app == app) {
3547 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003548 if (ActivityStack.DEBUG_ADD_REMOVE) {
3549 RuntimeException here = new RuntimeException("here");
3550 here.fillInStackTrace();
3551 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
3552 + ": haveState=" + r.haveState
3553 + " stateNotNeeded=" + r.stateNotNeeded
3554 + " finishing=" + r.finishing
3555 + " state=" + r.state, here);
3556 }
3557 if (!r.finishing) {
3558 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -08003559 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3560 System.identityHashCode(r),
3561 r.task.taskId, r.shortComponentName,
3562 "proc died without state saved");
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003563 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08003564 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003565 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003566 r.takeFromHistory();
Dianne Hackbornbe707852011-11-11 14:32:10 -08003567 mWindowManager.removeAppToken(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003569 mMainStack.validateAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003571 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572
3573 } else {
3574 // We have the current state for this activity, so
3575 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003576 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 TAG, "Keeping entry, setting app to null");
3578 if (r.visible) {
3579 hasVisibleActivities = true;
3580 }
3581 r.app = null;
3582 r.nowVisible = false;
3583 if (!r.haveState) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003584 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
3585 "App died, clearing saved state of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 r.icicle = null;
3587 }
3588 }
3589
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003590 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 }
3592 atTop = false;
3593 }
3594
3595 app.activities.clear();
3596
3597 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003598 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 + " running instrumentation " + app.instrumentationClass);
3600 Bundle info = new Bundle();
3601 info.putString("shortMsg", "Process crashed.");
3602 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
3603 }
3604
3605 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003606 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 // If there was nothing to resume, and we are not already
3608 // restarting this process, but there is a visible activity that
3609 // is hosted by the process... then make sure all visible
3610 // activities are running, taking care of restarting this
3611 // process.
3612 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003613 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 }
3615 }
3616 }
3617 }
3618
3619 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
3620 IBinder threadBinder = thread.asBinder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003622 for (int i=mLruProcesses.size()-1; i>=0; i--) {
3623 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
3625 return i;
3626 }
3627 }
3628 return -1;
3629 }
3630
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003631 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 IApplicationThread thread) {
3633 if (thread == null) {
3634 return null;
3635 }
3636
3637 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003638 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 }
3640
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003641 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 IApplicationThread thread) {
3643
3644 mProcDeaths[0]++;
3645
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003646 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
3647 synchronized (stats) {
3648 stats.noteProcessDiedLocked(app.info.uid, pid);
3649 }
3650
Magnus Edlund7bb25812010-02-24 15:45:06 +01003651 // Clean up already done if the process has been re-started.
3652 if (app.pid == pid && app.thread != null &&
3653 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07003654 if (!app.killedBackground) {
3655 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
3656 + ") has died.");
3657 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003658 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003659 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 TAG, "Dying app: " + app + ", pid: " + pid
3661 + ", thread: " + thread.asBinder());
3662 boolean doLowMem = app.instrumentationClass == null;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003663 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664
3665 if (doLowMem) {
3666 // If there are no longer any background processes running,
3667 // and the app that died was not running instrumentation,
3668 // then tell everyone we are now low on memory.
3669 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003670 for (int i=mLruProcesses.size()-1; i>=0; i--) {
3671 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -07003672 if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 haveBg = true;
3674 break;
3675 }
3676 }
3677
3678 if (!haveBg) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003679 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003680 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003681 for (int i=mLruProcesses.size()-1; i>=0; i--) {
3682 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07003683 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003684 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
3685 // The low memory report is overriding any current
3686 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07003687 // heavy/important/visible/foreground processes first.
Dianne Hackborn7d608422011-08-07 16:24:18 -07003688 if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003689 rec.lastRequestedGc = 0;
3690 } else {
3691 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003693 rec.reportLowMemory = true;
3694 rec.lastLowMemory = now;
3695 mProcessesToGc.remove(rec);
3696 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 }
3698 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07003699 mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003700 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 }
3702 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01003703 } else if (app.pid != pid) {
3704 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003705 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01003706 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08003707 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003708 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003709 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 + thread.asBinder());
3711 }
3712 }
3713
Dan Egnor42471dd2010-01-07 17:25:22 -08003714 /**
3715 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07003716 * @param clearTraces causes the dump file to be erased prior to the new
3717 * traces being written, if true; when false, the new traces will be
3718 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003719 * @param firstPids of dalvik VM processes to dump stack traces for first
3720 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08003721 * @return file containing stack traces, or null if no dump file is configured
3722 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003723 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
3724 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003725 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
3726 if (tracesPath == null || tracesPath.length() == 0) {
3727 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003729
3730 File tracesFile = new File(tracesPath);
3731 try {
3732 File tracesDir = tracesFile.getParentFile();
3733 if (!tracesDir.exists()) tracesFile.mkdirs();
3734 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
3735
Christopher Tate6ee412d2010-05-28 12:01:56 -07003736 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08003737 tracesFile.createNewFile();
3738 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
3739 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003740 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08003741 return null;
3742 }
3743
3744 // Use a FileObserver to detect when traces finish writing.
3745 // The order of traces is considered important to maintain for legibility.
3746 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
3747 public synchronized void onEvent(int event, String path) { notify(); }
3748 };
3749
3750 try {
3751 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003752
3753 // First collect all of the stacks of the most important pids.
3754 try {
3755 int num = firstPids.size();
3756 for (int i = 0; i < num; i++) {
3757 synchronized (observer) {
3758 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
3759 observer.wait(200); // Wait for write-close, give up after 200msec
3760 }
3761 }
3762 } catch (InterruptedException e) {
3763 Log.wtf(TAG, e);
3764 }
3765
3766 // Next measure CPU usage.
3767 if (processStats != null) {
3768 processStats.init();
3769 System.gc();
3770 processStats.update();
3771 try {
3772 synchronized (processStats) {
3773 processStats.wait(500); // measure over 1/2 second.
3774 }
3775 } catch (InterruptedException e) {
3776 }
3777 processStats.update();
3778
3779 // We'll take the stack crawls of just the top apps using CPU.
3780 final int N = processStats.countWorkingStats();
3781 int numProcs = 0;
3782 for (int i=0; i<N && numProcs<5; i++) {
3783 ProcessStats.Stats stats = processStats.getWorkingStats(i);
3784 if (lastPids.indexOfKey(stats.pid) >= 0) {
3785 numProcs++;
3786 try {
3787 synchronized (observer) {
3788 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
3789 observer.wait(200); // Wait for write-close, give up after 200msec
3790 }
3791 } catch (InterruptedException e) {
3792 Log.wtf(TAG, e);
3793 }
3794
3795 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003796 }
3797 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003798
3799 return tracesFile;
3800
Dan Egnor42471dd2010-01-07 17:25:22 -08003801 } finally {
3802 observer.stopWatching();
3803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 }
3805
Jeff Brown4d94a762010-09-23 11:33:28 -07003806 private final class AppNotResponding implements Runnable {
3807 private final ProcessRecord mApp;
3808 private final String mAnnotation;
3809
3810 public AppNotResponding(ProcessRecord app, String annotation) {
3811 mApp = app;
3812 mAnnotation = annotation;
3813 }
3814
3815 @Override
3816 public void run() {
3817 appNotResponding(mApp, null, null, mAnnotation);
3818 }
3819 }
3820
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003821 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
3822 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003823 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
3824 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
3825
Dianne Hackborn287952c2010-09-22 22:34:31 -07003826 if (mController != null) {
3827 try {
3828 // 0 == continue, -1 = kill process immediately
3829 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
3830 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3831 } catch (RemoteException e) {
3832 mController = null;
3833 }
3834 }
3835
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003836 long anrTime = SystemClock.uptimeMillis();
3837 if (MONITOR_CPU_USAGE) {
3838 updateCpuStatsNow();
3839 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003840
3841 synchronized (this) {
3842 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
3843 if (mShuttingDown) {
3844 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
3845 return;
3846 } else if (app.notResponding) {
3847 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
3848 return;
3849 } else if (app.crashing) {
3850 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3851 return;
3852 }
3853
3854 // In case we come through here for the same app before completing
3855 // this one, mark as anring now so we will bail out.
3856 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003857
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003858 // Log the ANR to the event log.
3859 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3860 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003861
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003862 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003863 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003864
3865 int parentPid = app.pid;
3866 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003867 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003868
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003869 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003870
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003871 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3872 ProcessRecord r = mLruProcesses.get(i);
3873 if (r != null && r.thread != null) {
3874 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003875 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3876 if (r.persistent) {
3877 firstPids.add(pid);
3878 } else {
3879 lastPids.put(pid, Boolean.TRUE);
3880 }
3881 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 }
3884 }
3885
Dan Egnor42471dd2010-01-07 17:25:22 -08003886 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003887 StringBuilder info = mStringBuilder;
3888 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003889 info.append("ANR in ").append(app.processName);
3890 if (activity != null && activity.shortComponentName != null) {
3891 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003892 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003893 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003895 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003897 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003898 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900
Dianne Hackborn287952c2010-09-22 22:34:31 -07003901 final ProcessStats processStats = new ProcessStats(true);
3902
3903 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3904
Dan Egnor42471dd2010-01-07 17:25:22 -08003905 String cpuInfo = null;
3906 if (MONITOR_CPU_USAGE) {
3907 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003908 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003909 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003910 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003911 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003912 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
3914
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003915 info.append(processStats.printCurrentState(anrTime));
3916
Joe Onorato8a9b2202010-02-26 18:56:32 -08003917 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003918 if (tracesFile == null) {
3919 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3920 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3921 }
3922
Jeff Sharkeya353d262011-10-28 11:12:06 -07003923 addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
3924 cpuInfo, tracesFile, null);
Dan Egnor42471dd2010-01-07 17:25:22 -08003925
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003926 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003928 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3929 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003931 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3932 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 }
3934 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003935 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 }
3937 }
3938
Dan Egnor42471dd2010-01-07 17:25:22 -08003939 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3940 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3941 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003942
3943 synchronized (this) {
3944 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003945 Slog.w(TAG, "Killing " + app + ": background ANR");
3946 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3947 app.processName, app.setAdj, "background ANR");
3948 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003949 return;
3950 }
3951
3952 // Set the app's notResponding state, and look up the errorReportReceiver
3953 makeAppNotRespondingLocked(app,
3954 activity != null ? activity.shortComponentName : null,
3955 annotation != null ? "ANR " + annotation : "ANR",
3956 info.toString());
3957
3958 // Bring up the infamous App Not Responding dialog
3959 Message msg = Message.obtain();
3960 HashMap map = new HashMap();
3961 msg.what = SHOW_NOT_RESPONDING_MSG;
3962 msg.obj = map;
3963 map.put("app", app);
3964 if (activity != null) {
3965 map.put("activity", activity);
3966 }
3967
3968 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 }
3971
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003972 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3973 if (!mLaunchWarningShown) {
3974 mLaunchWarningShown = true;
3975 mHandler.post(new Runnable() {
3976 @Override
3977 public void run() {
3978 synchronized (ActivityManagerService.this) {
3979 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3980 d.show();
3981 mHandler.postDelayed(new Runnable() {
3982 @Override
3983 public void run() {
3984 synchronized (ActivityManagerService.this) {
3985 d.dismiss();
3986 mLaunchWarningShown = false;
3987 }
3988 }
3989 }, 4000);
3990 }
3991 }
3992 });
3993 }
3994 }
3995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003996 public boolean clearApplicationUserData(final String packageName,
Amith Yamasani742a6712011-05-04 14:49:28 -07003997 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 int uid = Binder.getCallingUid();
3999 int pid = Binder.getCallingPid();
4000 long callingId = Binder.clearCallingIdentity();
4001 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004002 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 int pkgUid = -1;
4004 synchronized(this) {
4005 try {
4006 pkgUid = pm.getPackageUid(packageName);
4007 } catch (RemoteException e) {
4008 }
4009 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004010 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 return false;
4012 }
4013 if (uid == pkgUid || checkComponentPermission(
4014 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004015 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004017 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 } else {
4019 throw new SecurityException(pid+" does not have permission:"+
4020 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4021 "for process:"+packageName);
4022 }
4023 }
4024
4025 try {
4026 //clear application user data
4027 pm.clearApplicationUserData(packageName, observer);
4028 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4029 Uri.fromParts("package", packageName, null));
4030 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004031 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
Amith Yamasani742a6712011-05-04 14:49:28 -07004032 null, null, 0, null, null, null, false, false, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 } catch (RemoteException e) {
4034 }
4035 } finally {
4036 Binder.restoreCallingIdentity(callingId);
4037 }
4038 return true;
4039 }
4040
Dianne Hackborn03abb812010-01-04 18:43:19 -08004041 public void killBackgroundProcesses(final String packageName) {
4042 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4043 != PackageManager.PERMISSION_GRANTED &&
4044 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4045 != PackageManager.PERMISSION_GRANTED) {
4046 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 + Binder.getCallingPid()
4048 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004049 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004050 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004051 throw new SecurityException(msg);
4052 }
4053
4054 long callingId = Binder.clearCallingIdentity();
4055 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004056 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 int pkgUid = -1;
4058 synchronized(this) {
4059 try {
4060 pkgUid = pm.getPackageUid(packageName);
4061 } catch (RemoteException e) {
4062 }
4063 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004064 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065 return;
4066 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004067 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004068 ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
4069 }
4070 } finally {
4071 Binder.restoreCallingIdentity(callingId);
4072 }
4073 }
4074
4075 public void killAllBackgroundProcesses() {
4076 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4077 != PackageManager.PERMISSION_GRANTED) {
4078 String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
4079 + Binder.getCallingPid()
4080 + ", uid=" + Binder.getCallingUid()
4081 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
4082 Slog.w(TAG, msg);
4083 throw new SecurityException(msg);
4084 }
4085
4086 long callingId = Binder.clearCallingIdentity();
4087 try {
4088 synchronized(this) {
4089 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
4090 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
4091 final int NA = apps.size();
4092 for (int ia=0; ia<NA; ia++) {
4093 ProcessRecord app = apps.valueAt(ia);
4094 if (app.persistent) {
4095 // we don't kill persistent processes
4096 continue;
4097 }
4098 if (app.removed) {
4099 procs.add(app);
4100 } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
4101 app.removed = true;
4102 procs.add(app);
4103 }
4104 }
4105 }
4106
4107 int N = procs.size();
4108 for (int i=0; i<N; i++) {
4109 removeProcessLocked(procs.get(i), false, true, "kill all background");
4110 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004111 }
4112 } finally {
4113 Binder.restoreCallingIdentity(callingId);
4114 }
4115 }
4116
4117 public void forceStopPackage(final String packageName) {
4118 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4119 != PackageManager.PERMISSION_GRANTED) {
4120 String msg = "Permission Denial: forceStopPackage() from pid="
4121 + Binder.getCallingPid()
4122 + ", uid=" + Binder.getCallingUid()
4123 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004124 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004125 throw new SecurityException(msg);
4126 }
Amith Yamasani742a6712011-05-04 14:49:28 -07004127 final int userId = Binder.getOrigCallingUser();
Dianne Hackborn03abb812010-01-04 18:43:19 -08004128 long callingId = Binder.clearCallingIdentity();
4129 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004130 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08004131 int pkgUid = -1;
4132 synchronized(this) {
4133 try {
4134 pkgUid = pm.getPackageUid(packageName);
Amith Yamasani742a6712011-05-04 14:49:28 -07004135 // Convert the uid to the one for the calling user
4136 pkgUid = UserId.getUid(userId, pkgUid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004137 } catch (RemoteException e) {
4138 }
4139 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004140 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004141 return;
4142 }
4143 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08004144 try {
4145 pm.setPackageStoppedState(packageName, true);
4146 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08004147 } catch (IllegalArgumentException e) {
4148 Slog.w(TAG, "Failed trying to unstop package "
4149 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08004150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 }
4152 } finally {
4153 Binder.restoreCallingIdentity(callingId);
4154 }
4155 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004156
4157 /*
4158 * The pkg name and uid have to be specified.
4159 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4160 */
4161 public void killApplicationWithUid(String pkg, int uid) {
4162 if (pkg == null) {
4163 return;
4164 }
4165 // Make sure the uid is valid.
4166 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004167 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004168 return;
4169 }
4170 int callerUid = Binder.getCallingUid();
4171 // Only the system server can kill an application
4172 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004173 // Post an aysnc message to kill the application
4174 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4175 msg.arg1 = uid;
4176 msg.arg2 = 0;
4177 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004178 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004179 } else {
4180 throw new SecurityException(callerUid + " cannot kill pkg: " +
4181 pkg);
4182 }
4183 }
4184
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004185 public void closeSystemDialogs(String reason) {
4186 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004187 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004188 if (reason != null) {
4189 intent.putExtra("reason", reason);
4190 }
4191
4192 final int uid = Binder.getCallingUid();
4193 final long origId = Binder.clearCallingIdentity();
4194 synchronized (this) {
4195 int i = mWatchers.beginBroadcast();
4196 while (i > 0) {
4197 i--;
4198 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4199 if (w != null) {
4200 try {
4201 w.closingSystemDialogs(reason);
4202 } catch (RemoteException e) {
4203 }
4204 }
4205 }
4206 mWatchers.finishBroadcast();
4207
Dianne Hackbornffa42482009-09-23 22:20:11 -07004208 mWindowManager.closeSystemDialogs(reason);
4209
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004210 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
4211 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07004212 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004213 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07004214 Activity.RESULT_CANCELED, null, "close-sys");
4215 }
4216 }
4217
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004218 broadcastIntentLocked(null, null, intent, null,
Amith Yamasani742a6712011-05-04 14:49:28 -07004219 null, 0, null, null, null, false, false, -1, uid, 0 /* TODO: Verify */);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004220 }
4221 Binder.restoreCallingIdentity(origId);
4222 }
4223
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004224 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004225 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004226 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4227 for (int i=pids.length-1; i>=0; i--) {
4228 infos[i] = new Debug.MemoryInfo();
4229 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004230 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004231 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004232 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004233
Dianne Hackbornb437e092011-08-05 17:50:29 -07004234 public long[] getProcessPss(int[] pids) throws RemoteException {
4235 long[] pss = new long[pids.length];
4236 for (int i=pids.length-1; i>=0; i--) {
4237 pss[i] = Debug.getPss(pids[i]);
4238 }
4239 return pss;
4240 }
4241
Christopher Tate5e1ab332009-09-01 20:32:49 -07004242 public void killApplicationProcess(String processName, int uid) {
4243 if (processName == null) {
4244 return;
4245 }
4246
4247 int callerUid = Binder.getCallingUid();
4248 // Only the system server can kill an application
4249 if (callerUid == Process.SYSTEM_UID) {
4250 synchronized (this) {
4251 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07004252 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07004253 try {
4254 app.thread.scheduleSuicide();
4255 } catch (RemoteException e) {
4256 // If the other end already died, then our work here is done.
4257 }
4258 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004259 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07004260 + processName + " / " + uid);
4261 }
4262 }
4263 } else {
4264 throw new SecurityException(callerUid + " cannot kill app process: " +
4265 processName);
4266 }
4267 }
4268
Dianne Hackborn03abb812010-01-04 18:43:19 -08004269 private void forceStopPackageLocked(final String packageName, int uid) {
Christopher Tate3dacd842011-08-19 14:56:15 -07004270 forceStopPackageLocked(packageName, uid, false, false, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4272 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004273 if (!mProcessesReady) {
4274 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
4275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004276 intent.putExtra(Intent.EXTRA_UID, uid);
4277 broadcastIntentLocked(null, null, intent,
4278 null, null, 0, null, null, null,
Amith Yamasani742a6712011-05-04 14:49:28 -07004279 false, false,
4280 MY_PID, Process.SYSTEM_UID, UserId.getUserId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 }
4282
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004283 private final boolean killPackageProcessesLocked(String packageName, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07004284 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004285 boolean evenPersistent, String reason) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004286 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287
Dianne Hackborn03abb812010-01-04 18:43:19 -08004288 // Remove all processes this package may have touched: all with the
4289 // same UID (except for the system or root user), and all whose name
4290 // matches the package name.
4291 final String procNamePrefix = packageName + ":";
4292 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
4293 final int NA = apps.size();
4294 for (int ia=0; ia<NA; ia++) {
4295 ProcessRecord app = apps.valueAt(ia);
Christopher Tate3dacd842011-08-19 14:56:15 -07004296 if (app.persistent && !evenPersistent) {
Christopher Tate064d8422011-07-26 15:38:07 -07004297 // we don't kill persistent processes
4298 continue;
4299 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004300 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004301 if (doit) {
4302 procs.add(app);
4303 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004304 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
4305 || app.processName.equals(packageName)
4306 || app.processName.startsWith(procNamePrefix)) {
4307 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004308 if (!doit) {
4309 return true;
4310 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004311 app.removed = true;
4312 procs.add(app);
4313 }
4314 }
4315 }
4316 }
4317
4318 int N = procs.size();
4319 for (int i=0; i<N; i++) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004320 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004321 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004322 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08004323 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004324
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004325 private final boolean forceStopPackageLocked(String name, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07004326 boolean callerWillRestart, boolean purgeCache, boolean doit,
4327 boolean evenPersistent) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07004328 int i;
4329 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 if (uid < 0) {
4332 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004333 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334 } catch (RemoteException e) {
4335 }
4336 }
4337
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004338 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004339 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004340
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004341 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
4342 while (badApps.hasNext()) {
4343 SparseArray<Long> ba = badApps.next();
4344 if (ba.get(uid) != null) {
4345 badApps.remove();
4346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 }
4348 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004349
4350 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004351 callerWillRestart, false, doit, evenPersistent, "force stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004353 TaskRecord lastTask = null;
4354 for (i=0; i<mMainStack.mHistory.size(); i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004355 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004356 final boolean samePackage = r.packageName.equals(name);
4357 if ((samePackage || r.task == lastTask)
Christopher Tate3dacd842011-08-19 14:56:15 -07004358 && (r.app == null || evenPersistent || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004359 if (!doit) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004360 if (r.finishing) {
4361 // If this activity is just finishing, then it is not
4362 // interesting as far as something to stop.
4363 continue;
4364 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004365 return true;
4366 }
4367 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004368 Slog.i(TAG, " Force finishing activity " + r);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004369 if (samePackage) {
4370 if (r.app != null) {
4371 r.app.removed = true;
4372 }
4373 r.app = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 }
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004375 lastTask = r.task;
4376 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
4377 null, "force-stop")) {
4378 i--;
4379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 }
4381 }
4382
4383 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
Amith Yamasani742a6712011-05-04 14:49:28 -07004384 int userId = UserId.getUserId(uid);
4385 for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
Christopher Tate064d8422011-07-26 15:38:07 -07004386 if (service.packageName.equals(name)
Christopher Tate3dacd842011-08-19 14:56:15 -07004387 && (service.app == null || evenPersistent || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004388 if (!doit) {
4389 return true;
4390 }
4391 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004392 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 if (service.app != null) {
4394 service.app.removed = true;
4395 }
4396 service.app = null;
4397 services.add(service);
4398 }
4399 }
4400
4401 N = services.size();
4402 for (i=0; i<N; i++) {
4403 bringDownServiceLocked(services.get(i), true);
4404 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07004405
4406 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
4407 for (ContentProviderRecord provider : mProvidersByClass.values()) {
4408 if (provider.info.packageName.equals(name)
4409 && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
4410 if (!doit) {
4411 return true;
4412 }
4413 didSomething = true;
4414 providers.add(provider);
4415 }
4416 }
4417
4418 N = providers.size();
4419 for (i=0; i<N; i++) {
4420 removeDyingProviderLocked(null, providers.get(i));
4421 }
4422
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004423 if (doit) {
4424 if (purgeCache) {
4425 AttributeCache ac = AttributeCache.instance();
4426 if (ac != null) {
4427 ac.removePackage(name);
4428 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004429 }
Dianne Hackborn38cc8962011-10-13 11:33:55 -07004430 if (mBooted) {
4431 mMainStack.resumeTopActivityLocked(null);
4432 mMainStack.scheduleIdleLocked();
4433 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004434 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004435
4436 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 }
4438
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004439 private final boolean removeProcessLocked(ProcessRecord app,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004440 boolean callerWillRestart, boolean allowRestart, String reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 final String name = app.processName;
4442 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004443 if (DEBUG_PROCESSES) Slog.d(
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004444 TAG, "Force removing proc " + app.toShortString() + " (" + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 + "/" + uid + ")");
4446
4447 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004448 if (mHeavyWeightProcess == app) {
4449 mHeavyWeightProcess = null;
4450 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 boolean needRestart = false;
4453 if (app.pid > 0 && app.pid != MY_PID) {
4454 int pid = app.pid;
4455 synchronized (mPidsSelfLocked) {
4456 mPidsSelfLocked.remove(pid);
4457 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4458 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004459 Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004460 handleAppDiedLocked(app, true, allowRestart);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004461 mLruProcesses.remove(app);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004462 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463
4464 if (app.persistent) {
4465 if (!callerWillRestart) {
4466 addAppLocked(app.info);
4467 } else {
4468 needRestart = true;
4469 }
4470 }
4471 } else {
4472 mRemovedProcesses.add(app);
4473 }
4474
4475 return needRestart;
4476 }
4477
4478 private final void processStartTimedOutLocked(ProcessRecord app) {
4479 final int pid = app.pid;
4480 boolean gone = false;
4481 synchronized (mPidsSelfLocked) {
4482 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
4483 if (knownApp != null && knownApp.thread == null) {
4484 mPidsSelfLocked.remove(pid);
4485 gone = true;
4486 }
4487 }
4488
4489 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004490 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004491 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004492 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004494 if (mHeavyWeightProcess == app) {
4495 mHeavyWeightProcess = null;
4496 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4497 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004498 // Take care of any launching providers waiting for this process.
4499 checkAppInLaunchingProvidersLocked(app, true);
4500 // Take care of any services that are waiting for the process.
4501 for (int i=0; i<mPendingServices.size(); i++) {
4502 ServiceRecord sr = mPendingServices.get(i);
4503 if (app.info.uid == sr.appInfo.uid
4504 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004505 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004506 mPendingServices.remove(i);
4507 i--;
4508 bringDownServiceLocked(sr, true);
4509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004511 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
4512 app.processName, app.setAdj, "start timeout");
4513 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07004514 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004515 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07004516 try {
4517 IBackupManager bm = IBackupManager.Stub.asInterface(
4518 ServiceManager.getService(Context.BACKUP_SERVICE));
4519 bm.agentDisconnected(app.info.packageName);
4520 } catch (RemoteException e) {
4521 // Can't happen; the backup manager is local
4522 }
4523 }
Christopher Tatef46723b2012-01-26 14:19:24 -08004524 if (isPendingBroadcastProcessLocked(pid)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004525 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Christopher Tatef46723b2012-01-26 14:19:24 -08004526 skipPendingBroadcastLocked(pid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004529 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 }
4531 }
4532
4533 private final boolean attachApplicationLocked(IApplicationThread thread,
4534 int pid) {
4535
4536 // Find the application record that is being attached... either via
4537 // the pid if we are running in multiple processes, or just pull the
4538 // next app record if we are emulating process with anonymous threads.
4539 ProcessRecord app;
4540 if (pid != MY_PID && pid >= 0) {
4541 synchronized (mPidsSelfLocked) {
4542 app = mPidsSelfLocked.get(pid);
4543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 } else {
4545 app = null;
4546 }
4547
4548 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004549 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004551 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004553 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 } else {
4555 try {
4556 thread.scheduleExit();
4557 } catch (Exception e) {
4558 // Ignore exceptions.
4559 }
4560 }
4561 return false;
4562 }
4563
4564 // If this application record is still attached to a previous
4565 // process, clean it up now.
4566 if (app.thread != null) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004567 handleAppDiedLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 }
4569
4570 // Tell the process all about itself.
4571
Joe Onorato8a9b2202010-02-26 18:56:32 -08004572 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 TAG, "Binding process pid " + pid + " to record " + app);
4574
4575 String processName = app.processName;
4576 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07004577 AppDeathRecipient adr = new AppDeathRecipient(
4578 app, pid, thread);
4579 thread.asBinder().linkToDeath(adr, 0);
4580 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 } catch (RemoteException e) {
4582 app.resetPackageList();
4583 startProcessLocked(app, "link fail", processName);
4584 return false;
4585 }
4586
Doug Zongker2bec3d42009-12-04 12:52:44 -08004587 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588
4589 app.thread = thread;
4590 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08004591 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
4592 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 app.forcingToForeground = null;
4594 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07004595 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 app.debugging = false;
4597
4598 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4599
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004600 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004601 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004603 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004604 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004605 }
4606
Joe Onorato8a9b2202010-02-26 18:56:32 -08004607 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 TAG, "New app record " + app
4609 + " thread=" + thread.asBinder() + " pid=" + pid);
4610 try {
4611 int testMode = IApplicationThread.DEBUG_OFF;
4612 if (mDebugApp != null && mDebugApp.equals(processName)) {
4613 testMode = mWaitForDebugger
4614 ? IApplicationThread.DEBUG_WAIT
4615 : IApplicationThread.DEBUG_ON;
4616 app.debugging = true;
4617 if (mDebugTransient) {
4618 mDebugApp = mOrigDebugApp;
4619 mWaitForDebugger = mOrigWaitForDebugger;
4620 }
4621 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004622 String profileFile = app.instrumentationProfileFile;
4623 ParcelFileDescriptor profileFd = null;
4624 boolean profileAutoStop = false;
4625 if (mProfileApp != null && mProfileApp.equals(processName)) {
4626 mProfileProc = app;
4627 profileFile = mProfileFile;
4628 profileFd = mProfileFd;
4629 profileAutoStop = mAutoStopProfiler;
4630 }
4631
Christopher Tate181fafa2009-05-14 11:12:14 -07004632 // If the app is being launched for restore or full backup, set it up specially
4633 boolean isRestrictedBackupMode = false;
4634 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
4635 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07004636 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07004637 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
4638 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004639
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07004640 ensurePackageDexOpt(app.instrumentationInfo != null
4641 ? app.instrumentationInfo.packageName
4642 : app.info.packageName);
4643 if (app.instrumentationClass != null) {
4644 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004645 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004646 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07004647 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004648 ApplicationInfo appInfo = app.instrumentationInfo != null
4649 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07004650 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004651 if (profileFd != null) {
4652 profileFd = profileFd.dup();
4653 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004654 thread.bindApplication(processName, appInfo, providers,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004655 app.instrumentationClass, profileFile, profileFd, profileAutoStop,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn5d927c22011-09-02 12:22:18 -07004657 isRestrictedBackupMode || !normalMode, app.persistent,
Dianne Hackborn813075a62011-11-14 17:45:19 -08004658 new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08004659 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004660 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004661 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 } catch (Exception e) {
4663 // todo: Yikes! What should we do? For now we will try to
4664 // start another process, but that could easily get us in
4665 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004666 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667
4668 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07004669 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 startProcessLocked(app, "bind fail", processName);
4671 return false;
4672 }
4673
4674 // Remove this record from the list of starting applications.
4675 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004676 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
4677 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 mProcessesOnHold.remove(app);
4679
4680 boolean badApp = false;
4681 boolean didSomething = false;
4682
4683 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004684 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07004685 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
4687 && processName.equals(hr.processName)) {
4688 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004689 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004690 didSomething = true;
4691 }
4692 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004693 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 + hr.intent.getComponent().flattenToShortString(), e);
4695 badApp = true;
4696 }
4697 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004698 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699 }
4700 }
4701
4702 // Find any services that should be running in this process...
4703 if (!badApp && mPendingServices.size() > 0) {
4704 ServiceRecord sr = null;
4705 try {
4706 for (int i=0; i<mPendingServices.size(); i++) {
4707 sr = mPendingServices.get(i);
4708 if (app.info.uid != sr.appInfo.uid
4709 || !processName.equals(sr.processName)) {
4710 continue;
4711 }
4712
4713 mPendingServices.remove(i);
4714 i--;
4715 realStartServiceLocked(sr, app);
4716 didSomething = true;
4717 }
4718 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004719 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 + sr.shortName, e);
4721 badApp = true;
4722 }
4723 }
4724
Christopher Tatef46723b2012-01-26 14:19:24 -08004725 // Check if a next-broadcast receiver is in this process...
4726 if (!badApp && isPendingBroadcastProcessLocked(pid)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 try {
Christopher Tatef46723b2012-01-26 14:19:24 -08004728 didSomething = sendPendingBroadcastsLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 } catch (Exception e) {
Christopher Tatef46723b2012-01-26 14:19:24 -08004730 // If the app died trying to launch the receiver we declare it 'bad'
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 badApp = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 }
4733 }
4734
Christopher Tate181fafa2009-05-14 11:12:14 -07004735 // Check whether the next backup agent is in this process...
4736 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004737 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004738 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07004739 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004740 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
4741 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
4742 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07004743 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004744 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07004745 e.printStackTrace();
4746 }
4747 }
4748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 if (badApp) {
4750 // todo: Also need to kill application to deal with all
4751 // kinds of exceptions.
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004752 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753 return false;
4754 }
4755
4756 if (!didSomething) {
4757 updateOomAdjLocked();
4758 }
4759
4760 return true;
4761 }
4762
4763 public final void attachApplication(IApplicationThread thread) {
4764 synchronized (this) {
4765 int callingPid = Binder.getCallingPid();
4766 final long origId = Binder.clearCallingIdentity();
4767 attachApplicationLocked(thread, callingPid);
4768 Binder.restoreCallingIdentity(origId);
4769 }
4770 }
4771
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004772 public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004774 ActivityRecord r = mMainStack.activityIdleInternal(token, false, config);
4775 if (stopProfiling) {
4776 synchronized (this) {
4777 if (mProfileProc == r.app) {
4778 if (mProfileFd != null) {
4779 try {
4780 mProfileFd.close();
4781 } catch (IOException e) {
4782 }
4783 clearProfilerLocked();
4784 }
4785 }
4786 }
4787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 Binder.restoreCallingIdentity(origId);
4789 }
4790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08004792 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004793 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 mWindowManager.enableScreenAfterBoot();
4795 }
4796
Dianne Hackborn661cd522011-08-22 00:26:20 -07004797 public void showBootMessage(final CharSequence msg, final boolean always) {
4798 mWindowManager.showBootMessage(msg, always);
4799 }
4800
Dianne Hackborn90c52de2011-09-23 12:57:44 -07004801 public void dismissKeyguardOnNextActivity() {
4802 synchronized (this) {
4803 mMainStack.dismissKeyguardOnNextActivityLocked();
4804 }
4805 }
4806
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004807 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004808 IntentFilter pkgFilter = new IntentFilter();
4809 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
4810 pkgFilter.addDataScheme("package");
4811 mContext.registerReceiver(new BroadcastReceiver() {
4812 @Override
4813 public void onReceive(Context context, Intent intent) {
4814 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4815 if (pkgs != null) {
4816 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004817 synchronized (ActivityManagerService.this) {
Christopher Tate3dacd842011-08-19 14:56:15 -07004818 if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004819 setResultCode(Activity.RESULT_OK);
4820 return;
4821 }
4822 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004823 }
4824 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004825 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004826 }, pkgFilter);
4827
4828 synchronized (this) {
4829 // Ensure that any processes we had put on hold are now started
4830 // up.
4831 final int NP = mProcessesOnHold.size();
4832 if (NP > 0) {
4833 ArrayList<ProcessRecord> procs =
4834 new ArrayList<ProcessRecord>(mProcessesOnHold);
4835 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004836 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
4837 + procs.get(ip));
4838 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004839 }
4840 }
4841
4842 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07004843 // Start looking for apps that are abusing wake locks.
4844 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07004845 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004846 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07004847 SystemProperties.set("sys.boot_completed", "1");
Guang Zhu191713a2012-01-12 12:02:22 -08004848 SystemProperties.set("dev.bootcomplete", "1");
Amith Yamasani742a6712011-05-04 14:49:28 -07004849 /* TODO: Send this to all users that are to be logged in on startup */
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004850 broadcastIntentLocked(null, null,
4851 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
4852 null, null, 0, null, null,
4853 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
Amith Yamasani742a6712011-05-04 14:49:28 -07004854 false, false, MY_PID, Process.SYSTEM_UID, Binder.getOrigCallingUser());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004855 }
4856 }
4857 }
4858
4859 final void ensureBootCompleted() {
4860 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004861 boolean enableScreen;
4862 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004863 booting = mBooting;
4864 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004865 enableScreen = !mBooted;
4866 mBooted = true;
4867 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004868
4869 if (booting) {
4870 finishBooting();
4871 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004872
4873 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004874 enableScreenAfterBoot();
4875 }
4876 }
4877
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004878 public final void activityPaused(IBinder token) {
4879 final long origId = Binder.clearCallingIdentity();
4880 mMainStack.activityPaused(token, false);
4881 Binder.restoreCallingIdentity(origId);
4882 }
4883
4884 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
4885 CharSequence description) {
4886 if (localLOGV) Slog.v(
4887 TAG, "Activity stopped: token=" + token);
4888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004889 // Refuse possible leaked file descriptors
4890 if (icicle != null && icicle.hasFileDescriptors()) {
4891 throw new IllegalArgumentException("File descriptors passed in Bundle");
4892 }
4893
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004894 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895
4896 final long origId = Binder.clearCallingIdentity();
4897
4898 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004899 r = mMainStack.isInStackLocked(token);
4900 if (r != null) {
4901 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 }
4903 }
4904
4905 if (r != null) {
4906 sendPendingThumbnail(r, null, null, null, false);
4907 }
4908
4909 trimApplications();
4910
4911 Binder.restoreCallingIdentity(origId);
4912 }
4913
4914 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004915 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004916 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 }
4918
4919 public String getCallingPackage(IBinder token) {
4920 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004921 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07004922 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 }
4924 }
4925
4926 public ComponentName getCallingActivity(IBinder token) {
4927 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004928 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 return r != null ? r.intent.getComponent() : null;
4930 }
4931 }
4932
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004933 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004934 ActivityRecord r = mMainStack.isInStackLocked(token);
4935 if (r == null) {
4936 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004938 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 }
4940
4941 public ComponentName getActivityClassForToken(IBinder token) {
4942 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004943 ActivityRecord r = mMainStack.isInStackLocked(token);
4944 if (r == null) {
4945 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004947 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 }
4949 }
4950
4951 public String getPackageForToken(IBinder token) {
4952 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004953 ActivityRecord r = mMainStack.isInStackLocked(token);
4954 if (r == null) {
4955 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004957 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 }
4959 }
4960
4961 public IIntentSender getIntentSender(int type,
4962 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004963 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004965 if (intents != null) {
4966 if (intents.length < 1) {
4967 throw new IllegalArgumentException("Intents array length must be >= 1");
4968 }
4969 for (int i=0; i<intents.length; i++) {
4970 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004971 if (intent != null) {
4972 if (intent.hasFileDescriptors()) {
4973 throw new IllegalArgumentException("File descriptors passed in Intent");
4974 }
4975 if (type == INTENT_SENDER_BROADCAST &&
4976 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4977 throw new IllegalArgumentException(
4978 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4979 }
4980 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004981 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004982 }
4983 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004984 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004985 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004986 }
4987 }
4988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 synchronized(this) {
4990 int callingUid = Binder.getCallingUid();
4991 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004992 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004993 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 .getPackageUid(packageName);
Amith Yamasani742a6712011-05-04 14:49:28 -07004995 if (UserId.getAppId(callingUid) != uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 String msg = "Permission Denial: getIntentSender() from pid="
4997 + Binder.getCallingPid()
4998 + ", uid=" + Binder.getCallingUid()
4999 + ", (need uid=" + uid + ")"
5000 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005001 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 throw new SecurityException(msg);
5003 }
5004 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005005
Amith Yamasani742a6712011-05-04 14:49:28 -07005006 if (DEBUG_MU)
5007 Slog.i(TAG_MU, "Getting intent sender for origCallingUid="
5008 + Binder.getOrigCallingUid());
5009 return getIntentSenderLocked(type, packageName, Binder.getOrigCallingUid(),
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005010 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 } catch (RemoteException e) {
5013 throw new SecurityException(e);
5014 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005015 }
5016 }
5017
5018 IIntentSender getIntentSenderLocked(int type,
5019 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005020 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Amith Yamasani742a6712011-05-04 14:49:28 -07005021 if (DEBUG_MU)
5022 Slog.v(TAG_MU, "getIntentSenderLocked(): uid=" + callingUid);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005023 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005024 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005025 activity = mMainStack.isInStackLocked(token);
5026 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005027 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005029 if (activity.finishing) {
5030 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005032 }
5033
5034 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5035 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5036 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5037 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5038 |PendingIntent.FLAG_UPDATE_CURRENT);
5039
5040 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5041 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005042 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005043 WeakReference<PendingIntentRecord> ref;
5044 ref = mIntentSenderRecords.get(key);
5045 PendingIntentRecord rec = ref != null ? ref.get() : null;
5046 if (rec != null) {
5047 if (!cancelCurrent) {
5048 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005049 if (rec.key.requestIntent != null) {
5050 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
5051 }
5052 if (intents != null) {
5053 intents[intents.length-1] = rec.key.requestIntent;
5054 rec.key.allIntents = intents;
5055 rec.key.allResolvedTypes = resolvedTypes;
5056 } else {
5057 rec.key.allIntents = null;
5058 rec.key.allResolvedTypes = null;
5059 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 return rec;
5062 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005063 rec.canceled = true;
5064 mIntentSenderRecords.remove(key);
5065 }
5066 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 return rec;
5068 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005069 rec = new PendingIntentRecord(this, key, callingUid);
5070 mIntentSenderRecords.put(key, rec.ref);
5071 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5072 if (activity.pendingResults == null) {
5073 activity.pendingResults
5074 = new HashSet<WeakReference<PendingIntentRecord>>();
5075 }
5076 activity.pendingResults.add(rec.ref);
5077 }
5078 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 }
5080
5081 public void cancelIntentSender(IIntentSender sender) {
5082 if (!(sender instanceof PendingIntentRecord)) {
5083 return;
5084 }
5085 synchronized(this) {
5086 PendingIntentRecord rec = (PendingIntentRecord)sender;
5087 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005088 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 .getPackageUid(rec.key.packageName);
5090 if (uid != Binder.getCallingUid()) {
5091 String msg = "Permission Denial: cancelIntentSender() from pid="
5092 + Binder.getCallingPid()
5093 + ", uid=" + Binder.getCallingUid()
5094 + " is not allowed to cancel packges "
5095 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005096 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 throw new SecurityException(msg);
5098 }
5099 } catch (RemoteException e) {
5100 throw new SecurityException(e);
5101 }
5102 cancelIntentSenderLocked(rec, true);
5103 }
5104 }
5105
5106 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5107 rec.canceled = true;
5108 mIntentSenderRecords.remove(rec.key);
5109 if (cleanActivity && rec.key.activity != null) {
5110 rec.key.activity.pendingResults.remove(rec.ref);
5111 }
5112 }
5113
5114 public String getPackageForIntentSender(IIntentSender pendingResult) {
5115 if (!(pendingResult instanceof PendingIntentRecord)) {
5116 return null;
5117 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07005118 try {
5119 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5120 return res.key.packageName;
5121 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 }
5123 return null;
5124 }
5125
Dianne Hackborn6c418d52011-06-29 14:05:33 -07005126 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
5127 if (!(pendingResult instanceof PendingIntentRecord)) {
5128 return false;
5129 }
5130 try {
5131 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5132 if (res.key.allIntents == null) {
5133 return false;
5134 }
5135 for (int i=0; i<res.key.allIntents.length; i++) {
5136 Intent intent = res.key.allIntents[i];
5137 if (intent.getPackage() != null && intent.getComponent() != null) {
5138 return false;
5139 }
5140 }
5141 return true;
5142 } catch (ClassCastException e) {
5143 }
5144 return false;
5145 }
5146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 public void setProcessLimit(int max) {
5148 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5149 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005150 synchronized (this) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07005151 mProcessLimit = max < 0 ? ProcessList.MAX_HIDDEN_APPS : max;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005152 mProcessLimitOverride = max;
5153 }
5154 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 }
5156
5157 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005158 synchronized (this) {
5159 return mProcessLimitOverride;
5160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005161 }
5162
5163 void foregroundTokenDied(ForegroundToken token) {
5164 synchronized (ActivityManagerService.this) {
5165 synchronized (mPidsSelfLocked) {
5166 ForegroundToken cur
5167 = mForegroundProcesses.get(token.pid);
5168 if (cur != token) {
5169 return;
5170 }
5171 mForegroundProcesses.remove(token.pid);
5172 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5173 if (pr == null) {
5174 return;
5175 }
5176 pr.forcingToForeground = null;
5177 pr.foregroundServices = false;
5178 }
5179 updateOomAdjLocked();
5180 }
5181 }
5182
5183 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5184 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5185 "setProcessForeground()");
5186 synchronized(this) {
5187 boolean changed = false;
5188
5189 synchronized (mPidsSelfLocked) {
5190 ProcessRecord pr = mPidsSelfLocked.get(pid);
5191 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005192 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 return;
5194 }
5195 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5196 if (oldToken != null) {
5197 oldToken.token.unlinkToDeath(oldToken, 0);
5198 mForegroundProcesses.remove(pid);
5199 pr.forcingToForeground = null;
5200 changed = true;
5201 }
5202 if (isForeground && token != null) {
5203 ForegroundToken newToken = new ForegroundToken() {
5204 public void binderDied() {
5205 foregroundTokenDied(this);
5206 }
5207 };
5208 newToken.pid = pid;
5209 newToken.token = token;
5210 try {
5211 token.linkToDeath(newToken, 0);
5212 mForegroundProcesses.put(pid, newToken);
5213 pr.forcingToForeground = token;
5214 changed = true;
5215 } catch (RemoteException e) {
5216 // If the process died while doing this, we will later
5217 // do the cleanup with the process death link.
5218 }
5219 }
5220 }
5221
5222 if (changed) {
5223 updateOomAdjLocked();
5224 }
5225 }
5226 }
5227
5228 // =========================================================
5229 // PERMISSIONS
5230 // =========================================================
5231
5232 static class PermissionController extends IPermissionController.Stub {
5233 ActivityManagerService mActivityManagerService;
5234 PermissionController(ActivityManagerService activityManagerService) {
5235 mActivityManagerService = activityManagerService;
5236 }
5237
5238 public boolean checkPermission(String permission, int pid, int uid) {
5239 return mActivityManagerService.checkPermission(permission, pid,
5240 uid) == PackageManager.PERMISSION_GRANTED;
5241 }
5242 }
5243
5244 /**
5245 * This can be called with or without the global lock held.
5246 */
5247 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005248 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 // We might be performing an operation on behalf of an indirect binder
5250 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
5251 // client identity accordingly before proceeding.
5252 Identity tlsIdentity = sCallerIdentity.get();
5253 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005254 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
5256 uid = tlsIdentity.uid;
5257 pid = tlsIdentity.pid;
5258 }
5259
5260 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07005261 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005262 return PackageManager.PERMISSION_GRANTED;
5263 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005264 // If there is a uid that owns whatever is being accessed, it has
5265 // blanket access to it regardless of the permissions it requires.
Amith Yamasani742a6712011-05-04 14:49:28 -07005266 if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005267 return PackageManager.PERMISSION_GRANTED;
5268 }
5269 // If the target is not exported, then nobody else can get to it.
5270 if (!exported) {
5271 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 return PackageManager.PERMISSION_DENIED;
5273 }
5274 if (permission == null) {
5275 return PackageManager.PERMISSION_GRANTED;
5276 }
5277 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005278 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 .checkUidPermission(permission, uid);
5280 } catch (RemoteException e) {
5281 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005282 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 }
5284 return PackageManager.PERMISSION_DENIED;
5285 }
5286
5287 /**
5288 * As the only public entry point for permissions checking, this method
5289 * can enforce the semantic that requesting a check on a null global
5290 * permission is automatically denied. (Internally a null permission
5291 * string is used when calling {@link #checkComponentPermission} in cases
5292 * when only uid-based security is needed.)
5293 *
5294 * This can be called with or without the global lock held.
5295 */
5296 public int checkPermission(String permission, int pid, int uid) {
5297 if (permission == null) {
5298 return PackageManager.PERMISSION_DENIED;
5299 }
Amith Yamasani742a6712011-05-04 14:49:28 -07005300 return checkComponentPermission(permission, pid, UserId.getAppId(uid), -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302
5303 /**
5304 * Binder IPC calls go through the public entry point.
5305 * This can be called with or without the global lock held.
5306 */
5307 int checkCallingPermission(String permission) {
5308 return checkPermission(permission,
5309 Binder.getCallingPid(),
Amith Yamasani742a6712011-05-04 14:49:28 -07005310 UserId.getAppId(Binder.getCallingUid()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 }
5312
5313 /**
5314 * This can be called with or without the global lock held.
5315 */
5316 void enforceCallingPermission(String permission, String func) {
5317 if (checkCallingPermission(permission)
5318 == PackageManager.PERMISSION_GRANTED) {
5319 return;
5320 }
5321
5322 String msg = "Permission Denial: " + func + " from pid="
5323 + Binder.getCallingPid()
5324 + ", uid=" + Binder.getCallingUid()
5325 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005326 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 throw new SecurityException(msg);
5328 }
5329
5330 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07005331 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
5332 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
5333 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
5334 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5335 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005336 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07005337 // Is the component private from the target uid?
5338 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
5339
5340 // Acceptable if the there is no read permission needed from the
5341 // target or the target is holding the read permission.
5342 if (!readPerm) {
5343 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07005345 == PackageManager.PERMISSION_GRANTED)) {
5346 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 }
5348 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07005349
5350 // Acceptable if the there is no write permission needed from the
5351 // target or the target is holding the read permission.
5352 if (!writePerm) {
5353 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07005355 == PackageManager.PERMISSION_GRANTED)) {
5356 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 }
5358 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07005359
5360 // Acceptable if there is a path permission matching the URI that
5361 // the target holds the permission on.
5362 PathPermission[] pps = pi.pathPermissions;
5363 if (pps != null && (!readPerm || !writePerm)) {
5364 final String path = uri.getPath();
5365 int i = pps.length;
5366 while (i > 0 && (!readPerm || !writePerm)) {
5367 i--;
5368 PathPermission pp = pps[i];
5369 if (!readPerm) {
5370 final String pprperm = pp.getReadPermission();
5371 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
5372 + pprperm + " for " + pp.getPath()
5373 + ": match=" + pp.match(path)
5374 + " check=" + pm.checkUidPermission(pprperm, uid));
5375 if (pprperm != null && pp.match(path) &&
5376 (pm.checkUidPermission(pprperm, uid)
5377 == PackageManager.PERMISSION_GRANTED)) {
5378 readPerm = true;
5379 }
5380 }
5381 if (!writePerm) {
5382 final String ppwperm = pp.getWritePermission();
5383 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
5384 + ppwperm + " for " + pp.getPath()
5385 + ": match=" + pp.match(path)
5386 + " check=" + pm.checkUidPermission(ppwperm, uid));
5387 if (ppwperm != null && pp.match(path) &&
5388 (pm.checkUidPermission(ppwperm, uid)
5389 == PackageManager.PERMISSION_GRANTED)) {
5390 writePerm = true;
5391 }
5392 }
5393 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07005394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 } catch (RemoteException e) {
5396 return false;
5397 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07005398
5399 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 }
5401
5402 private final boolean checkUriPermissionLocked(Uri uri, int uid,
5403 int modeFlags) {
5404 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07005405 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 return true;
5407 }
5408 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
5409 if (perms == null) return false;
5410 UriPermission perm = perms.get(uri);
5411 if (perm == null) return false;
5412 return (modeFlags&perm.modeFlags) == modeFlags;
5413 }
5414
5415 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
5416 // Another redirected-binder-call permissions check as in
5417 // {@link checkComponentPermission}.
5418 Identity tlsIdentity = sCallerIdentity.get();
5419 if (tlsIdentity != null) {
5420 uid = tlsIdentity.uid;
5421 pid = tlsIdentity.pid;
5422 }
5423
Amith Yamasani742a6712011-05-04 14:49:28 -07005424 uid = UserId.getAppId(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 // Our own process gets to do everything.
5426 if (pid == MY_PID) {
5427 return PackageManager.PERMISSION_GRANTED;
5428 }
5429 synchronized(this) {
5430 return checkUriPermissionLocked(uri, uid, modeFlags)
5431 ? PackageManager.PERMISSION_GRANTED
5432 : PackageManager.PERMISSION_DENIED;
5433 }
5434 }
5435
Dianne Hackborn39792d22010-08-19 18:01:52 -07005436 /**
5437 * Check if the targetPkg can be granted permission to access uri by
5438 * the callingUid using the given modeFlags. Throws a security exception
5439 * if callingUid is not allowed to do this. Returns the uid of the target
5440 * if the URI permission grant should be performed; returns -1 if it is not
5441 * needed (for example targetPkg already has permission to access the URI).
5442 */
5443 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
5444 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5446 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5447 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005448 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 }
5450
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005451 if (targetPkg != null) {
5452 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5453 "Checking grant " + targetPkg + " permission to " + uri);
5454 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005455
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005456 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457
5458 // If this is not a content: uri, we can't do anything with it.
5459 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005460 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005461 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07005462 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 }
5464
5465 String name = uri.getAuthority();
5466 ProviderInfo pi = null;
Amith Yamasani742a6712011-05-04 14:49:28 -07005467 ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
5468 UserId.getUserId(callingUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 if (cpr != null) {
5470 pi = cpr.info;
5471 } else {
5472 try {
5473 pi = pm.resolveContentProvider(name,
5474 PackageManager.GET_URI_PERMISSION_PATTERNS);
5475 } catch (RemoteException ex) {
5476 }
5477 }
5478 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005479 Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString());
Dianne Hackborn39792d22010-08-19 18:01:52 -07005480 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 }
5482
5483 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005484 if (targetPkg != null) {
5485 try {
5486 targetUid = pm.getPackageUid(targetPkg);
5487 if (targetUid < 0) {
5488 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5489 "Can't grant URI permission no uid for: " + targetPkg);
5490 return -1;
5491 }
5492 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005493 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005495 } else {
5496 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 }
5498
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005499 if (targetUid >= 0) {
5500 // First... does the target actually need this permission?
5501 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
5502 // No need to grant the target this permission.
5503 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5504 "Target " + targetPkg + " already has full permission to " + uri);
5505 return -1;
5506 }
5507 } else {
5508 // First... there is no target package, so can anyone access it?
5509 boolean allowed = pi.exported;
5510 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5511 if (pi.readPermission != null) {
5512 allowed = false;
5513 }
5514 }
5515 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5516 if (pi.writePermission != null) {
5517 allowed = false;
5518 }
5519 }
5520 if (allowed) {
5521 return -1;
5522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 }
5524
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005525 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 if (!pi.grantUriPermissions) {
5527 throw new SecurityException("Provider " + pi.packageName
5528 + "/" + pi.name
5529 + " does not allow granting of Uri permissions (uri "
5530 + uri + ")");
5531 }
5532 if (pi.uriPermissionPatterns != null) {
5533 final int N = pi.uriPermissionPatterns.length;
5534 boolean allowed = false;
5535 for (int i=0; i<N; i++) {
5536 if (pi.uriPermissionPatterns[i] != null
5537 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
5538 allowed = true;
5539 break;
5540 }
5541 }
5542 if (!allowed) {
5543 throw new SecurityException("Provider " + pi.packageName
5544 + "/" + pi.name
5545 + " does not allow granting of permission to path of Uri "
5546 + uri);
5547 }
5548 }
5549
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005550 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005552 if (callingUid != Process.myUid()) {
5553 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
5554 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5555 throw new SecurityException("Uid " + callingUid
5556 + " does not have permission to uri " + uri);
5557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 }
5559 }
5560
Dianne Hackborn39792d22010-08-19 18:01:52 -07005561 return targetUid;
5562 }
5563
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005564 public int checkGrantUriPermission(int callingUid, String targetPkg,
5565 Uri uri, int modeFlags) {
5566 synchronized(this) {
5567 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
5568 }
5569 }
5570
Dianne Hackborn39792d22010-08-19 18:01:52 -07005571 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
5572 Uri uri, int modeFlags, UriPermissionOwner owner) {
5573 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5574 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5575 if (modeFlags == 0) {
5576 return;
5577 }
5578
5579 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 // to the uri, and the target doesn't. Let's now give this to
5581 // the target.
5582
Joe Onorato8a9b2202010-02-26 18:56:32 -08005583 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07005584 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 HashMap<Uri, UriPermission> targetUris
5587 = mGrantedUriPermissions.get(targetUid);
5588 if (targetUris == null) {
5589 targetUris = new HashMap<Uri, UriPermission>();
5590 mGrantedUriPermissions.put(targetUid, targetUris);
5591 }
5592
5593 UriPermission perm = targetUris.get(uri);
5594 if (perm == null) {
5595 perm = new UriPermission(targetUid, uri);
5596 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07005598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07005600 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08005602 } else {
5603 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5604 perm.readOwners.add(owner);
5605 owner.addReadPermission(perm);
5606 }
5607 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5608 perm.writeOwners.add(owner);
5609 owner.addWritePermission(perm);
5610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 }
5612 }
5613
Dianne Hackborn39792d22010-08-19 18:01:52 -07005614 void grantUriPermissionLocked(int callingUid,
5615 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005616 if (targetPkg == null) {
5617 throw new NullPointerException("targetPkg");
5618 }
5619
Dianne Hackborn39792d22010-08-19 18:01:52 -07005620 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
5621 if (targetUid < 0) {
5622 return;
5623 }
5624
5625 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
5626 }
5627
5628 /**
5629 * Like checkGrantUriPermissionLocked, but takes an Intent.
5630 */
5631 int checkGrantUriPermissionFromIntentLocked(int callingUid,
5632 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07005633 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07005634 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005635 + " from " + intent + "; flags=0x"
5636 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
5637
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005638 if (targetPkg == null) {
5639 throw new NullPointerException("targetPkg");
5640 }
5641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005643 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 }
5645 Uri data = intent.getData();
5646 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005647 return -1;
5648 }
5649 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
5650 intent.getFlags());
5651 }
5652
5653 /**
5654 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
5655 */
5656 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
5657 String targetPkg, Intent intent, UriPermissionOwner owner) {
5658 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
5659 intent.getFlags(), owner);
5660 }
5661
5662 void grantUriPermissionFromIntentLocked(int callingUid,
5663 String targetPkg, Intent intent, UriPermissionOwner owner) {
5664 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
5665 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 return;
5667 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07005668
5669 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 }
5671
5672 public void grantUriPermission(IApplicationThread caller, String targetPkg,
5673 Uri uri, int modeFlags) {
5674 synchronized(this) {
5675 final ProcessRecord r = getRecordForAppLocked(caller);
5676 if (r == null) {
5677 throw new SecurityException("Unable to find app for caller "
5678 + caller
5679 + " when granting permission to uri " + uri);
5680 }
5681 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07005682 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 }
5684 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07005685 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 }
5687
5688 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
5689 null);
5690 }
5691 }
5692
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005693 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
5695 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
5696 HashMap<Uri, UriPermission> perms
5697 = mGrantedUriPermissions.get(perm.uid);
5698 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005699 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005700 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 perms.remove(perm.uri);
5702 if (perms.size() == 0) {
5703 mGrantedUriPermissions.remove(perm.uid);
5704 }
5705 }
5706 }
5707 }
5708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 private void revokeUriPermissionLocked(int callingUid, Uri uri,
5710 int modeFlags) {
5711 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5712 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5713 if (modeFlags == 0) {
5714 return;
5715 }
5716
Joe Onorato8a9b2202010-02-26 18:56:32 -08005717 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005718 "Revoking all granted permissions to " + uri);
5719
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005720 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721
5722 final String authority = uri.getAuthority();
5723 ProviderInfo pi = null;
Amith Yamasani742a6712011-05-04 14:49:28 -07005724 ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
5725 UserId.getUserId(callingUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 if (cpr != null) {
5727 pi = cpr.info;
5728 } else {
5729 try {
5730 pi = pm.resolveContentProvider(authority,
5731 PackageManager.GET_URI_PERMISSION_PATTERNS);
5732 } catch (RemoteException ex) {
5733 }
5734 }
5735 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005736 Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005737 return;
5738 }
5739
5740 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07005741 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005742 // Right now, if you are not the original owner of the permission,
5743 // you are not allowed to revoke it.
5744 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5745 throw new SecurityException("Uid " + callingUid
5746 + " does not have permission to uri " + uri);
5747 //}
5748 }
5749
5750 // Go through all of the permissions and remove any that match.
5751 final List<String> SEGMENTS = uri.getPathSegments();
5752 if (SEGMENTS != null) {
5753 final int NS = SEGMENTS.size();
5754 int N = mGrantedUriPermissions.size();
5755 for (int i=0; i<N; i++) {
5756 HashMap<Uri, UriPermission> perms
5757 = mGrantedUriPermissions.valueAt(i);
5758 Iterator<UriPermission> it = perms.values().iterator();
5759 toploop:
5760 while (it.hasNext()) {
5761 UriPermission perm = it.next();
5762 Uri targetUri = perm.uri;
5763 if (!authority.equals(targetUri.getAuthority())) {
5764 continue;
5765 }
5766 List<String> targetSegments = targetUri.getPathSegments();
5767 if (targetSegments == null) {
5768 continue;
5769 }
5770 if (targetSegments.size() < NS) {
5771 continue;
5772 }
5773 for (int j=0; j<NS; j++) {
5774 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
5775 continue toploop;
5776 }
5777 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005778 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005779 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 perm.clearModes(modeFlags);
5781 if (perm.modeFlags == 0) {
5782 it.remove();
5783 }
5784 }
5785 if (perms.size() == 0) {
5786 mGrantedUriPermissions.remove(
5787 mGrantedUriPermissions.keyAt(i));
5788 N--;
5789 i--;
5790 }
5791 }
5792 }
5793 }
5794
5795 public void revokeUriPermission(IApplicationThread caller, Uri uri,
5796 int modeFlags) {
5797 synchronized(this) {
5798 final ProcessRecord r = getRecordForAppLocked(caller);
5799 if (r == null) {
5800 throw new SecurityException("Unable to find app for caller "
5801 + caller
5802 + " when revoking permission to uri " + uri);
5803 }
5804 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005805 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 return;
5807 }
5808
5809 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5810 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5811 if (modeFlags == 0) {
5812 return;
5813 }
5814
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005815 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816
5817 final String authority = uri.getAuthority();
5818 ProviderInfo pi = null;
Amith Yamasani742a6712011-05-04 14:49:28 -07005819 ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
5820 UserId.getUserId(r.info.uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 if (cpr != null) {
5822 pi = cpr.info;
5823 } else {
5824 try {
5825 pi = pm.resolveContentProvider(authority,
5826 PackageManager.GET_URI_PERMISSION_PATTERNS);
5827 } catch (RemoteException ex) {
5828 }
5829 }
5830 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005831 Slog.w(TAG, "No content provider found for permission revoke: "
5832 + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 return;
5834 }
5835
5836 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
5837 }
5838 }
5839
Dianne Hackborn7e269642010-08-25 19:50:20 -07005840 @Override
5841 public IBinder newUriPermissionOwner(String name) {
5842 synchronized(this) {
5843 UriPermissionOwner owner = new UriPermissionOwner(this, name);
5844 return owner.getExternalTokenLocked();
5845 }
5846 }
5847
5848 @Override
5849 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
5850 Uri uri, int modeFlags) {
5851 synchronized(this) {
5852 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5853 if (owner == null) {
5854 throw new IllegalArgumentException("Unknown owner: " + token);
5855 }
5856 if (fromUid != Binder.getCallingUid()) {
5857 if (Binder.getCallingUid() != Process.myUid()) {
5858 // Only system code can grant URI permissions on behalf
5859 // of other users.
5860 throw new SecurityException("nice try");
5861 }
5862 }
5863 if (targetPkg == null) {
5864 throw new IllegalArgumentException("null target");
5865 }
5866 if (uri == null) {
5867 throw new IllegalArgumentException("null uri");
5868 }
5869
5870 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
5871 }
5872 }
5873
5874 @Override
5875 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
5876 synchronized(this) {
5877 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5878 if (owner == null) {
5879 throw new IllegalArgumentException("Unknown owner: " + token);
5880 }
5881
5882 if (uri == null) {
5883 owner.removeUriPermissionsLocked(mode);
5884 } else {
5885 owner.removeUriPermissionLocked(uri, mode);
5886 }
5887 }
5888 }
5889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
5891 synchronized (this) {
5892 ProcessRecord app =
5893 who != null ? getRecordForAppLocked(who) : null;
5894 if (app == null) return;
5895
5896 Message msg = Message.obtain();
5897 msg.what = WAIT_FOR_DEBUGGER_MSG;
5898 msg.obj = app;
5899 msg.arg1 = waiting ? 1 : 0;
5900 mHandler.sendMessage(msg);
5901 }
5902 }
5903
5904 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07005905 final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
5906 final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 outInfo.availMem = Process.getFreeMemory();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005908 outInfo.threshold = homeAppMem;
5909 outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
5910 outInfo.hiddenAppThreshold = hiddenAppMem;
5911 outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
Dianne Hackborne02c88a2011-10-28 13:58:15 -07005912 ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005913 outInfo.visibleAppThreshold = mProcessList.getMemLevel(
5914 ProcessList.VISIBLE_APP_ADJ);
5915 outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
5916 ProcessList.FOREGROUND_APP_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 }
5918
5919 // =========================================================
5920 // TASK MANAGEMENT
5921 // =========================================================
5922
5923 public List getTasks(int maxNum, int flags,
5924 IThumbnailReceiver receiver) {
5925 ArrayList list = new ArrayList();
5926
5927 PendingThumbnailsRecord pending = null;
5928 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005929 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930
5931 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005932 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
5934 + ", receiver=" + receiver);
5935
5936 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
5937 != PackageManager.PERMISSION_GRANTED) {
5938 if (receiver != null) {
5939 // If the caller wants to wait for pending thumbnails,
5940 // it ain't gonna get them.
5941 try {
5942 receiver.finished();
5943 } catch (RemoteException ex) {
5944 }
5945 }
5946 String msg = "Permission Denial: getTasks() from pid="
5947 + Binder.getCallingPid()
5948 + ", uid=" + Binder.getCallingUid()
5949 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005950 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 throw new SecurityException(msg);
5952 }
5953
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005954 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005955 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005956 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005957 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 TaskRecord curTask = null;
5959 int numActivities = 0;
5960 int numRunning = 0;
5961 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005962 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005964 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965
5966 // Initialize state for next task if needed.
5967 if (top == null ||
5968 (top.state == ActivityState.INITIALIZING
5969 && top.task == r.task)) {
5970 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 curTask = r.task;
5972 numActivities = numRunning = 0;
5973 }
5974
5975 // Add 'r' into the current task.
5976 numActivities++;
5977 if (r.app != null && r.app.thread != null) {
5978 numRunning++;
5979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005980
Joe Onorato8a9b2202010-02-26 18:56:32 -08005981 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005982 TAG, r.intent.getComponent().flattenToShortString()
5983 + ": task=" + r.task);
5984
5985 // If the next one is a different task, generate a new
5986 // TaskInfo entry for what we have.
5987 if (next == null || next.task != curTask) {
5988 ActivityManager.RunningTaskInfo ci
5989 = new ActivityManager.RunningTaskInfo();
5990 ci.id = curTask.taskId;
5991 ci.baseActivity = r.intent.getComponent();
5992 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005993 if (top.thumbHolder != null) {
5994 ci.description = top.thumbHolder.lastDescription;
5995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 ci.numActivities = numActivities;
5997 ci.numRunning = numRunning;
5998 //System.out.println(
5999 // "#" + maxNum + ": " + " descr=" + ci.description);
6000 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006001 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 TAG, "State=" + top.state + "Idle=" + top.idle
6003 + " app=" + top.app
6004 + " thr=" + (top.app != null ? top.app.thread : null));
6005 if (top.state == ActivityState.RESUMED
6006 || top.state == ActivityState.PAUSING) {
6007 if (top.idle && top.app != null
6008 && top.app.thread != null) {
6009 topRecord = top;
6010 topThumbnail = top.app.thread;
6011 } else {
6012 top.thumbnailNeeded = true;
6013 }
6014 }
6015 if (pending == null) {
6016 pending = new PendingThumbnailsRecord(receiver);
6017 }
6018 pending.pendingRecords.add(top);
6019 }
6020 list.add(ci);
6021 maxNum--;
6022 top = null;
6023 }
6024 }
6025
6026 if (pending != null) {
6027 mPendingThumbnails.add(pending);
6028 }
6029 }
6030
Joe Onorato8a9b2202010-02-26 18:56:32 -08006031 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032
6033 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006034 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006035 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08006036 topThumbnail.requestThumbnail(topRecord.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006038 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08006039 sendPendingThumbnail(null, topRecord.appToken, null, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006040 }
6041 }
6042
6043 if (pending == null && receiver != null) {
6044 // In this case all thumbnails were available and the client
6045 // is being asked to be told when the remaining ones come in...
6046 // which is unusually, since the top-most currently running
6047 // activity should never have a canned thumbnail! Oh well.
6048 try {
6049 receiver.finished();
6050 } catch (RemoteException ex) {
6051 }
6052 }
6053
6054 return list;
6055 }
6056
6057 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6058 int flags) {
Amith Yamasani742a6712011-05-04 14:49:28 -07006059 final int callingUid = Binder.getCallingUid();
6060 // If it's the system uid asking, then use the current user id.
6061 // TODO: Make sure that there aren't any other legitimate calls from the system uid that
6062 // require the entire list.
6063 final int callingUserId = callingUid == Process.SYSTEM_UID
6064 ? mCurrentUserId : UserId.getUserId(callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 synchronized (this) {
6066 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6067 "getRecentTasks()");
6068
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006069 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 final int N = mRecentTasks.size();
6072 ArrayList<ActivityManager.RecentTaskInfo> res
6073 = new ArrayList<ActivityManager.RecentTaskInfo>(
6074 maxNum < N ? maxNum : N);
6075 for (int i=0; i<N && maxNum > 0; i++) {
6076 TaskRecord tr = mRecentTasks.get(i);
Amith Yamasani742a6712011-05-04 14:49:28 -07006077 // Only add calling user's recent tasks
6078 if (tr.userId != callingUserId) continue;
Dianne Hackborn905577f2011-09-07 18:31:28 -07006079 // Return the entry if desired by the caller. We always return
6080 // the first entry, because callers always expect this to be the
Amith Yamasani742a6712011-05-04 14:49:28 -07006081 // foreground app. We may filter others if the caller has
Dianne Hackborn905577f2011-09-07 18:31:28 -07006082 // not supplied RECENT_WITH_EXCLUDED and there is some reason
6083 // we should exclude the entry.
Amith Yamasani742a6712011-05-04 14:49:28 -07006084
Dianne Hackborn905577f2011-09-07 18:31:28 -07006085 if (i == 0
6086 || ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 || (tr.intent == null)
6088 || ((tr.intent.getFlags()
6089 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6090 ActivityManager.RecentTaskInfo rti
6091 = new ActivityManager.RecentTaskInfo();
6092 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08006093 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 rti.baseIntent = new Intent(
6095 tr.intent != null ? tr.intent : tr.affinityIntent);
6096 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08006097 rti.description = tr.lastDescription;
6098
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006099 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6100 // Check whether this activity is currently available.
6101 try {
6102 if (rti.origActivity != null) {
6103 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6104 continue;
6105 }
6106 } else if (rti.baseIntent != null) {
6107 if (pm.queryIntentActivities(rti.baseIntent,
6108 null, 0) == null) {
6109 continue;
6110 }
6111 }
6112 } catch (RemoteException e) {
6113 // Will never happen.
6114 }
6115 }
6116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 res.add(rti);
6118 maxNum--;
6119 }
6120 }
6121 return res;
6122 }
6123 }
6124
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006125 private TaskRecord taskForIdLocked(int id) {
6126 final int N = mRecentTasks.size();
6127 for (int i=0; i<N; i++) {
6128 TaskRecord tr = mRecentTasks.get(i);
6129 if (tr.taskId == id) {
6130 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08006131 }
6132 }
6133 return null;
6134 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006135
6136 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
6137 synchronized (this) {
6138 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
6139 "getTaskThumbnails()");
6140 TaskRecord tr = taskForIdLocked(id);
6141 if (tr != null) {
6142 return mMainStack.getTaskThumbnailsLocked(tr);
6143 }
6144 }
6145 return null;
6146 }
6147
6148 public boolean removeSubTask(int taskId, int subTaskIndex) {
6149 synchronized (this) {
6150 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
6151 "removeSubTask()");
6152 long ident = Binder.clearCallingIdentity();
6153 try {
6154 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
6155 } finally {
6156 Binder.restoreCallingIdentity(ident);
6157 }
6158 }
6159 }
6160
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006161 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006162 TaskRecord tr = root.task;
6163 Intent baseIntent = new Intent(
6164 tr.intent != null ? tr.intent : tr.affinityIntent);
6165 ComponentName component = baseIntent.getComponent();
6166 if (component == null) {
6167 Slog.w(TAG, "Now component for base intent of task: " + tr);
6168 return;
6169 }
6170
6171 // Find any running services associated with this app.
6172 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
Amith Yamasani742a6712011-05-04 14:49:28 -07006173 for (ServiceRecord sr : mServiceMap.getAllServices(root.userId)) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006174 if (sr.packageName.equals(component.getPackageName())) {
6175 services.add(sr);
6176 }
6177 }
6178
6179 // Take care of any running services associated with the app.
6180 for (int i=0; i<services.size(); i++) {
6181 ServiceRecord sr = services.get(i);
6182 if (sr.startRequested) {
6183 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006184 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006185 stopServiceLocked(sr);
6186 } else {
6187 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
6188 sr.makeNextStartId(), baseIntent, -1));
6189 if (sr.app != null && sr.app.thread != null) {
6190 sendServiceArgsLocked(sr, false);
6191 }
6192 }
6193 }
6194 }
6195
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006196 if (killProcesses) {
6197 // Find any running processes associated with this app.
6198 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
6199 SparseArray<ProcessRecord> appProcs
6200 = mProcessNames.getMap().get(component.getPackageName());
6201 if (appProcs != null) {
6202 for (int i=0; i<appProcs.size(); i++) {
6203 procs.add(appProcs.valueAt(i));
6204 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006205 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006206
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006207 // Kill the running processes.
6208 for (int i=0; i<procs.size(); i++) {
6209 ProcessRecord pr = procs.get(i);
6210 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
6211 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
6212 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
6213 pr.processName, pr.setAdj, "remove task");
6214 Process.killProcessQuiet(pr.pid);
6215 } else {
6216 pr.waitingToKill = "remove task";
6217 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006218 }
6219 }
6220 }
6221
6222 public boolean removeTask(int taskId, int flags) {
6223 synchronized (this) {
6224 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
6225 "removeTask()");
6226 long ident = Binder.clearCallingIdentity();
6227 try {
6228 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
6229 if (r != null) {
6230 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006231 cleanUpRemovedTaskLocked(r,
6232 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006233 return true;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -07006234 } else {
6235 TaskRecord tr = null;
6236 int i=0;
6237 while (i < mRecentTasks.size()) {
6238 TaskRecord t = mRecentTasks.get(i);
6239 if (t.taskId == taskId) {
6240 tr = t;
6241 break;
6242 }
6243 i++;
6244 }
6245 if (tr != null) {
6246 if (tr.numActivities <= 0) {
6247 // Caller is just removing a recent task that is
6248 // not actively running. That is easy!
6249 mRecentTasks.remove(i);
6250 } else {
6251 Slog.w(TAG, "removeTask: task " + taskId
6252 + " does not have activities to remove, "
6253 + " but numActivities=" + tr.numActivities
6254 + ": " + tr);
6255 }
6256 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006257 }
6258 } finally {
6259 Binder.restoreCallingIdentity(ident);
6260 }
6261 }
6262 return false;
6263 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08006264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6266 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006267 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 TaskRecord jt = startTask;
6269
6270 // First look backwards
6271 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006272 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 if (r.task != jt) {
6274 jt = r.task;
6275 if (affinity.equals(jt.affinity)) {
6276 return j;
6277 }
6278 }
6279 }
6280
6281 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006282 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006283 jt = startTask;
6284 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006285 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006286 if (r.task != jt) {
6287 if (affinity.equals(jt.affinity)) {
6288 return j;
6289 }
6290 jt = r.task;
6291 }
6292 }
6293
6294 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006295 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 return N-1;
6297 }
6298
6299 return -1;
6300 }
6301
6302 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006303 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08006305 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6307 "moveTaskToFront()");
6308
6309 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006310 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6311 Binder.getCallingUid(), "Task to front")) {
6312 return;
6313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 final long origId = Binder.clearCallingIdentity();
6315 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006316 TaskRecord tr = taskForIdLocked(task);
6317 if (tr != null) {
6318 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
6319 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006321 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
6322 // Caller wants the home activity moved with it. To accomplish this,
6323 // we'll just move the home task to the top first.
6324 mMainStack.moveHomeToFrontLocked();
6325 }
6326 mMainStack.moveTaskToFrontLocked(tr, null);
6327 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006329 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6330 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08006332 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
6333 mMainStack.mUserLeaving = true;
6334 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08006335 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
6336 // Caller wants the home activity moved with it. To accomplish this,
6337 // we'll just move the home task to the top first.
6338 mMainStack.moveHomeToFrontLocked();
6339 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006340 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 return;
6342 }
6343 }
6344 } finally {
6345 Binder.restoreCallingIdentity(origId);
6346 }
6347 }
6348 }
6349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006350 public void moveTaskToBack(int task) {
6351 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6352 "moveTaskToBack()");
6353
6354 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006355 if (mMainStack.mResumedActivity != null
6356 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006357 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6358 Binder.getCallingUid(), "Task to back")) {
6359 return;
6360 }
6361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006363 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 Binder.restoreCallingIdentity(origId);
6365 }
6366 }
6367
6368 /**
6369 * Moves an activity, and all of the other activities within the same task, to the bottom
6370 * of the history stack. The activity's order within the task is unchanged.
6371 *
6372 * @param token A reference to the activity we wish to move
6373 * @param nonRoot If false then this only works if the activity is the root
6374 * of a task; if true it will work for any activity in a task.
6375 * @return Returns true if the move completed, false if not.
6376 */
6377 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
6378 synchronized(this) {
6379 final long origId = Binder.clearCallingIdentity();
6380 int taskId = getTaskForActivityLocked(token, !nonRoot);
6381 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006382 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 }
6384 Binder.restoreCallingIdentity(origId);
6385 }
6386 return false;
6387 }
6388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006389 public void moveTaskBackwards(int task) {
6390 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6391 "moveTaskBackwards()");
6392
6393 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006394 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6395 Binder.getCallingUid(), "Task backwards")) {
6396 return;
6397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 final long origId = Binder.clearCallingIdentity();
6399 moveTaskBackwardsLocked(task);
6400 Binder.restoreCallingIdentity(origId);
6401 }
6402 }
6403
6404 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006405 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 }
6407
6408 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
6409 synchronized(this) {
6410 return getTaskForActivityLocked(token, onlyRoot);
6411 }
6412 }
6413
6414 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006415 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 TaskRecord lastTask = null;
6417 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006418 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08006419 if (r.appToken == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 if (!onlyRoot || lastTask != r.task) {
6421 return r.task.taskId;
6422 }
6423 return -1;
6424 }
6425 lastTask = r.task;
6426 }
6427
6428 return -1;
6429 }
6430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 public void finishOtherInstances(IBinder token, ComponentName className) {
6432 synchronized(this) {
6433 final long origId = Binder.clearCallingIdentity();
6434
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006435 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 TaskRecord lastTask = null;
6437 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006438 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 if (r.realActivity.equals(className)
Dianne Hackbornbe707852011-11-11 14:32:10 -08006440 && r.appToken != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006441 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 null, "others")) {
6443 i--;
6444 N--;
6445 }
6446 }
6447 lastTask = r.task;
6448 }
6449
6450 Binder.restoreCallingIdentity(origId);
6451 }
6452 }
6453
6454 // =========================================================
6455 // THUMBNAILS
6456 // =========================================================
6457
6458 public void reportThumbnail(IBinder token,
6459 Bitmap thumbnail, CharSequence description) {
6460 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
6461 final long origId = Binder.clearCallingIdentity();
6462 sendPendingThumbnail(null, token, thumbnail, description, true);
6463 Binder.restoreCallingIdentity(origId);
6464 }
6465
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006466 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 Bitmap thumbnail, CharSequence description, boolean always) {
6468 TaskRecord task = null;
6469 ArrayList receivers = null;
6470
6471 //System.out.println("Send pending thumbnail: " + r);
6472
6473 synchronized(this) {
6474 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006475 r = mMainStack.isInStackLocked(token);
6476 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 return;
6478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006479 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07006480 if (thumbnail == null && r.thumbHolder != null) {
6481 thumbnail = r.thumbHolder.lastThumbnail;
6482 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 }
6484 if (thumbnail == null && !always) {
6485 // If there is no thumbnail, and this entry is not actually
6486 // going away, then abort for now and pick up the next
6487 // thumbnail we get.
6488 return;
6489 }
6490 task = r.task;
6491
6492 int N = mPendingThumbnails.size();
6493 int i=0;
6494 while (i<N) {
6495 PendingThumbnailsRecord pr =
6496 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
6497 //System.out.println("Looking in " + pr.pendingRecords);
6498 if (pr.pendingRecords.remove(r)) {
6499 if (receivers == null) {
6500 receivers = new ArrayList();
6501 }
6502 receivers.add(pr);
6503 if (pr.pendingRecords.size() == 0) {
6504 pr.finished = true;
6505 mPendingThumbnails.remove(i);
6506 N--;
6507 continue;
6508 }
6509 }
6510 i++;
6511 }
6512 }
6513
6514 if (receivers != null) {
6515 final int N = receivers.size();
6516 for (int i=0; i<N; i++) {
6517 try {
6518 PendingThumbnailsRecord pr =
6519 (PendingThumbnailsRecord)receivers.get(i);
6520 pr.receiver.newThumbnail(
6521 task != null ? task.taskId : -1, thumbnail, description);
6522 if (pr.finished) {
6523 pr.receiver.finished();
6524 }
6525 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006526 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006527 }
6528 }
6529 }
6530 }
6531
6532 // =========================================================
6533 // CONTENT PROVIDERS
6534 // =========================================================
6535
Jeff Brown10e89712011-07-08 18:52:57 -07006536 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
6537 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006538 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006539 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006541 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 } catch (RemoteException ex) {
6543 }
Amith Yamasani742a6712011-05-04 14:49:28 -07006544 if (DEBUG_MU)
6545 Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.info.uid);
6546 int userId = UserId.getUserId(app.info.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006547 if (providers != null) {
6548 final int N = providers.size();
6549 for (int i=0; i<N; i++) {
6550 ProviderInfo cpi =
6551 (ProviderInfo)providers.get(i);
Amith Yamasani742a6712011-05-04 14:49:28 -07006552
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006553 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
Amith Yamasani742a6712011-05-04 14:49:28 -07006554 ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 if (cpr == null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006556 cpr = new ContentProviderRecord(cpi, app.info, comp);
Amith Yamasani742a6712011-05-04 14:49:28 -07006557 mProviderMap.putProviderByClass(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 }
Amith Yamasani742a6712011-05-04 14:49:28 -07006559 if (DEBUG_MU)
6560 Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 app.pubProviders.put(cpi.name, cpr);
6562 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07006563 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 }
6565 }
6566 return providers;
6567 }
6568
6569 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07006570 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
6572 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
6573 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006574 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07006575 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 return null;
6577 }
6578 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006579 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 == PackageManager.PERMISSION_GRANTED) {
6581 return null;
6582 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07006583
6584 PathPermission[] pps = cpi.pathPermissions;
6585 if (pps != null) {
6586 int i = pps.length;
6587 while (i > 0) {
6588 i--;
6589 PathPermission pp = pps[i];
6590 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006591 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07006592 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07006593 return null;
6594 }
6595 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006596 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07006597 == PackageManager.PERMISSION_GRANTED) {
6598 return null;
6599 }
6600 }
6601 }
6602
Dianne Hackbornb424b632010-08-18 15:59:05 -07006603 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
6604 if (perms != null) {
6605 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
6606 if (uri.getKey().getAuthority().equals(cpi.authority)) {
6607 return null;
6608 }
6609 }
6610 }
6611
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006612 String msg;
6613 if (!cpi.exported) {
6614 msg = "Permission Denial: opening provider " + cpi.name
6615 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
6616 + ", uid=" + callingUid + ") that is not exported from uid "
6617 + cpi.applicationInfo.uid;
6618 } else {
6619 msg = "Permission Denial: opening provider " + cpi.name
6620 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
6621 + ", uid=" + callingUid + ") requires "
6622 + cpi.readPermission + " or " + cpi.writePermission;
6623 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006624 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006625 return msg;
6626 }
6627
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006628 boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
6629 if (r != null) {
6630 Integer cnt = r.conProviders.get(cpr);
6631 if (DEBUG_PROVIDER) Slog.v(TAG,
6632 "Adding provider requested by "
6633 + r.processName + " from process "
6634 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
6635 + " cnt=" + (cnt == null ? 1 : cnt));
6636 if (cnt == null) {
6637 cpr.clients.add(r);
6638 r.conProviders.put(cpr, new Integer(1));
6639 return true;
6640 } else {
6641 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
6642 }
6643 } else {
6644 cpr.externals++;
6645 }
6646 return false;
6647 }
6648
6649 boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
6650 if (r != null) {
6651 Integer cnt = r.conProviders.get(cpr);
6652 if (DEBUG_PROVIDER) Slog.v(TAG,
6653 "Removing provider requested by "
6654 + r.processName + " from process "
6655 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
6656 + " cnt=" + cnt);
6657 if (cnt == null || cnt.intValue() <= 1) {
6658 cpr.clients.remove(r);
6659 r.conProviders.remove(cpr);
6660 return true;
6661 } else {
6662 r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
6663 }
6664 } else {
6665 cpr.externals++;
6666 }
6667 return false;
6668 }
6669
Amith Yamasani742a6712011-05-04 14:49:28 -07006670 private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
6671 String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006672 ContentProviderRecord cpr;
6673 ProviderInfo cpi = null;
6674
6675 synchronized(this) {
6676 ProcessRecord r = null;
6677 if (caller != null) {
6678 r = getRecordForAppLocked(caller);
6679 if (r == null) {
6680 throw new SecurityException(
6681 "Unable to find app for caller " + caller
6682 + " (pid=" + Binder.getCallingPid()
6683 + ") when getting content provider " + name);
6684 }
6685 }
6686
6687 // First check if this content provider has been published...
Amith Yamasani742a6712011-05-04 14:49:28 -07006688 int userId = UserId.getUserId(r != null ? r.info.uid : Binder.getCallingUid());
6689 cpr = mProviderMap.getProviderByName(name, userId);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006690 boolean providerRunning = cpr != null;
6691 if (providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006692 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07006693 String msg;
6694 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
6695 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006696 }
6697
6698 if (r != null && cpr.canRunHere(r)) {
6699 // This provider has been published or is in the process
6700 // of being published... but it is also allowed to run
6701 // in the caller's process, so don't make a connection
6702 // and just let the caller instantiate its own instance.
6703 if (cpr.provider != null) {
6704 // don't give caller the provider object, it needs
6705 // to make its own.
6706 cpr = new ContentProviderRecord(cpr);
6707 }
6708 return cpr;
6709 }
6710
6711 final long origId = Binder.clearCallingIdentity();
6712
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006713 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 // return it right away.
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006715 final boolean countChanged = incProviderCount(r, cpr);
6716 if (countChanged) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006717 if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006718 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07006719 // make sure to count it as being accessed and thus
6720 // back up on the LRU list. This is good because
6721 // content providers are often expensive to start.
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006722 updateLruProcessLocked(cpr.proc, false, true);
Dianne Hackborn906497c2010-05-10 15:57:38 -07006723 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07006724 }
6725
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006726 if (cpr.proc != null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006727 if (false) {
6728 if (cpr.name.flattenToShortString().equals(
6729 "com.android.providers.calendar/.CalendarProvider2")) {
6730 Slog.v(TAG, "****************** KILLING "
6731 + cpr.name.flattenToShortString());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006732 Process.killProcess(cpr.proc.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006733 }
6734 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006735 boolean success = updateOomAdjLocked(cpr.proc);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006736 if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
6737 // NOTE: there is still a race here where a signal could be
6738 // pending on the process even though we managed to update its
6739 // adj level. Not sure what to do about this, but at least
6740 // the race is now smaller.
6741 if (!success) {
6742 // Uh oh... it looks like the provider's process
6743 // has been killed on us. We need to wait for a new
6744 // process to be started, and make sure its death
6745 // doesn't kill our process.
6746 Slog.i(TAG,
6747 "Existing provider " + cpr.name.flattenToShortString()
6748 + " is crashing; detaching " + r);
6749 boolean lastRef = decProviderCount(r, cpr);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006750 appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006751 if (!lastRef) {
6752 // This wasn't the last ref our process had on
6753 // the provider... we have now been killed, bail.
6754 return null;
6755 }
6756 providerRunning = false;
6757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 }
6759
6760 Binder.restoreCallingIdentity(origId);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006763 if (!providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006765 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006766 resolveContentProvider(name,
6767 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 } catch (RemoteException ex) {
6769 }
6770 if (cpi == null) {
6771 return null;
6772 }
6773
Amith Yamasani742a6712011-05-04 14:49:28 -07006774 cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo,
6775 Binder.getOrigCallingUser());
6776
Dianne Hackbornb424b632010-08-18 15:59:05 -07006777 String msg;
6778 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
6779 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780 }
6781
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006782 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006783 && !cpi.processName.equals("system")) {
6784 // If this content provider does not run in the system
6785 // process, and the system is not yet ready to run other
6786 // processes, then fail fast instead of hanging.
6787 throw new IllegalArgumentException(
6788 "Attempt to launch content provider before system ready");
6789 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006790
6791 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
Amith Yamasani742a6712011-05-04 14:49:28 -07006792 cpr = mProviderMap.getProviderByClass(comp, Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 final boolean firstClass = cpr == null;
6794 if (firstClass) {
6795 try {
6796 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006797 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006798 getApplicationInfo(
6799 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006800 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006802 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803 + cpi.name);
6804 return null;
6805 }
Amith Yamasani742a6712011-05-04 14:49:28 -07006806 ai = getAppInfoForUser(ai, Binder.getOrigCallingUser());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006807 cpr = new ContentProviderRecord(cpi, ai, comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 } catch (RemoteException ex) {
6809 // pm is in same process, this will never happen.
6810 }
6811 }
6812
6813 if (r != null && cpr.canRunHere(r)) {
6814 // If this is a multiprocess provider, then just return its
6815 // info and allow the caller to instantiate it. Only do
6816 // this if the provider is the same user as the caller's
6817 // process, or can run as root (so can be in any process).
6818 return cpr;
6819 }
6820
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006821 if (DEBUG_PROVIDER) {
6822 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006823 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006824 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006825 }
6826
6827 // This is single process, and our app is now connecting to it.
6828 // See if we are already in the process of launching this
6829 // provider.
6830 final int N = mLaunchingProviders.size();
6831 int i;
6832 for (i=0; i<N; i++) {
6833 if (mLaunchingProviders.get(i) == cpr) {
6834 break;
6835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 }
6837
6838 // If the provider is not already being launched, then get it
6839 // started.
6840 if (i >= N) {
6841 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08006842
6843 try {
6844 // Content provider is now in use, its package can't be stopped.
6845 try {
6846 AppGlobals.getPackageManager().setPackageStoppedState(
6847 cpr.appInfo.packageName, false);
6848 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006849 } catch (IllegalArgumentException e) {
6850 Slog.w(TAG, "Failed trying to unstop package "
6851 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006852 }
6853
6854 ProcessRecord proc = startProcessLocked(cpi.processName,
6855 cpr.appInfo, false, 0, "content provider",
6856 new ComponentName(cpi.applicationInfo.packageName,
6857 cpi.name), false);
6858 if (proc == null) {
6859 Slog.w(TAG, "Unable to launch app "
6860 + cpi.applicationInfo.packageName + "/"
6861 + cpi.applicationInfo.uid + " for provider "
6862 + name + ": process is bad");
6863 return null;
6864 }
6865 cpr.launchingApp = proc;
6866 mLaunchingProviders.add(cpr);
6867 } finally {
6868 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 }
6871
6872 // Make sure the provider is published (the same provider class
6873 // may be published under multiple names).
6874 if (firstClass) {
Amith Yamasani742a6712011-05-04 14:49:28 -07006875 mProviderMap.putProviderByClass(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 }
Amith Yamasani742a6712011-05-04 14:49:28 -07006877 mProviderMap.putProviderByName(name, cpr);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006878 incProviderCount(r, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 }
6880 }
6881
6882 // Wait for the provider to be published...
6883 synchronized (cpr) {
6884 while (cpr.provider == null) {
6885 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006886 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006887 + cpi.applicationInfo.packageName + "/"
6888 + cpi.applicationInfo.uid + " for provider "
6889 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006890 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 cpi.applicationInfo.packageName,
6892 cpi.applicationInfo.uid, name);
6893 return null;
6894 }
6895 try {
Amith Yamasani742a6712011-05-04 14:49:28 -07006896 if (DEBUG_MU) {
6897 Slog.v(TAG_MU, "Waiting to start provider " + cpr + " launchingApp="
6898 + cpr.launchingApp);
6899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 cpr.wait();
6901 } catch (InterruptedException ex) {
6902 }
6903 }
6904 }
6905 return cpr;
6906 }
6907
6908 public final ContentProviderHolder getContentProvider(
6909 IApplicationThread caller, String name) {
6910 if (caller == null) {
6911 String msg = "null IApplicationThread when getting content provider "
6912 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006913 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 throw new SecurityException(msg);
6915 }
6916
Amith Yamasani742a6712011-05-04 14:49:28 -07006917 ContentProviderHolder contentProvider = getContentProviderImpl(caller, name);
6918 return contentProvider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006919 }
6920
6921 private ContentProviderHolder getContentProviderExternal(String name) {
6922 return getContentProviderImpl(null, name);
6923 }
6924
6925 /**
6926 * Drop a content provider from a ProcessRecord's bookkeeping
6927 * @param cpr
6928 */
6929 public void removeContentProvider(IApplicationThread caller, String name) {
6930 synchronized (this) {
Amith Yamasani742a6712011-05-04 14:49:28 -07006931 int userId = UserId.getUserId(Binder.getCallingUid());
6932 ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006933 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006934 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006935 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006936 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 return;
6938 }
6939 final ProcessRecord r = getRecordForAppLocked(caller);
6940 if (r == null) {
6941 throw new SecurityException(
6942 "Unable to find app for caller " + caller +
6943 " when removing content provider " + name);
6944 }
6945 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006946 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
Amith Yamasani742a6712011-05-04 14:49:28 -07006947 ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp, userId);
6948 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
6949 + r.info.processName + " from process "
6950 + localCpr.appInfo.processName);
6951 if (localCpr.launchingApp == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08006953 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006954 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955 return;
6956 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006957 if (decProviderCount(r, localCpr)) {
6958 updateOomAdjLocked();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07006959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 }
6962 }
6963
6964 private void removeContentProviderExternal(String name) {
6965 synchronized (this) {
Amith Yamasani742a6712011-05-04 14:49:28 -07006966 ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
6967 Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 if(cpr == null) {
6969 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006970 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 return;
6972 }
6973
6974 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006975 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
Amith Yamasani742a6712011-05-04 14:49:28 -07006976 ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp,
6977 Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006978 localCpr.externals--;
6979 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006980 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006981 }
6982 updateOomAdjLocked();
6983 }
6984 }
6985
6986 public final void publishContentProviders(IApplicationThread caller,
6987 List<ContentProviderHolder> providers) {
6988 if (providers == null) {
6989 return;
6990 }
6991
6992 synchronized(this) {
6993 final ProcessRecord r = getRecordForAppLocked(caller);
Amith Yamasani742a6712011-05-04 14:49:28 -07006994 if (DEBUG_MU)
6995 Slog.v(TAG_MU, "ProcessRecord uid = " + r.info.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 if (r == null) {
6997 throw new SecurityException(
6998 "Unable to find app for caller " + caller
6999 + " (pid=" + Binder.getCallingPid()
7000 + ") when publishing content providers");
7001 }
7002
7003 final long origId = Binder.clearCallingIdentity();
7004
7005 final int N = providers.size();
7006 for (int i=0; i<N; i++) {
7007 ContentProviderHolder src = providers.get(i);
7008 if (src == null || src.info == null || src.provider == null) {
7009 continue;
7010 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07007011 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
Amith Yamasani742a6712011-05-04 14:49:28 -07007012 if (DEBUG_MU)
7013 Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 if (dst != null) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007015 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
Amith Yamasani742a6712011-05-04 14:49:28 -07007016 mProviderMap.putProviderByClass(comp, dst);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007017 String names[] = dst.info.authority.split(";");
7018 for (int j = 0; j < names.length; j++) {
Amith Yamasani742a6712011-05-04 14:49:28 -07007019 mProviderMap.putProviderByName(names[j], dst);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 }
7021
7022 int NL = mLaunchingProviders.size();
7023 int j;
7024 for (j=0; j<NL; j++) {
7025 if (mLaunchingProviders.get(j) == dst) {
7026 mLaunchingProviders.remove(j);
7027 j--;
7028 NL--;
7029 }
7030 }
7031 synchronized (dst) {
7032 dst.provider = src.provider;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07007033 dst.proc = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 dst.notifyAll();
7035 }
7036 updateOomAdjLocked(r);
7037 }
7038 }
7039
7040 Binder.restoreCallingIdentity(origId);
7041 }
7042 }
7043
7044 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07007045 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06007046 synchronized (mSelf) {
7047 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7048 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08007049 if (providers != null) {
7050 for (int i=providers.size()-1; i>=0; i--) {
7051 ProviderInfo pi = (ProviderInfo)providers.get(i);
7052 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
7053 Slog.w(TAG, "Not installing system proc provider " + pi.name
7054 + ": not system .apk");
7055 providers.remove(i);
7056 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007057 }
7058 }
7059 }
Josh Bartel2ecce342010-02-25 10:55:48 -06007060 if (providers != null) {
7061 mSystemThread.installSystemProviders(providers);
7062 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08007063
7064 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
Mark Brophyc6350272011-08-05 16:16:39 +01007065
7066 mSelf.mUsageStatsService.monitorPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 }
7068
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07007069 /**
7070 * Allows app to retrieve the MIME type of a URI without having permission
7071 * to access its content provider.
7072 *
7073 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
7074 *
7075 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
7076 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
7077 */
7078 public String getProviderMimeType(Uri uri) {
7079 final String name = uri.getAuthority();
7080 final long ident = Binder.clearCallingIdentity();
7081 ContentProviderHolder holder = null;
7082
7083 try {
7084 holder = getContentProviderExternal(name);
7085 if (holder != null) {
7086 return holder.provider.getType(uri);
7087 }
7088 } catch (RemoteException e) {
7089 Log.w(TAG, "Content provider dead retrieving " + uri, e);
7090 return null;
7091 } finally {
7092 if (holder != null) {
7093 removeContentProviderExternal(name);
7094 }
7095 Binder.restoreCallingIdentity(ident);
7096 }
7097
7098 return null;
7099 }
7100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007101 // =========================================================
7102 // GLOBAL MANAGEMENT
7103 // =========================================================
7104
7105 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7106 ApplicationInfo info, String customProcess) {
7107 String proc = customProcess != null ? customProcess : info.processName;
7108 BatteryStatsImpl.Uid.Proc ps = null;
7109 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7110 synchronized (stats) {
7111 ps = stats.getProcessStatsLocked(info.uid, proc);
7112 }
7113 return new ProcessRecord(ps, thread, info, proc);
7114 }
7115
7116 final ProcessRecord addAppLocked(ApplicationInfo info) {
7117 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7118
7119 if (app == null) {
7120 app = newProcessRecordLocked(null, info, null);
7121 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007122 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 }
7124
Dianne Hackborne7f97212011-02-24 14:40:20 -08007125 // This package really, really can not be stopped.
7126 try {
7127 AppGlobals.getPackageManager().setPackageStoppedState(
7128 info.packageName, false);
7129 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08007130 } catch (IllegalArgumentException e) {
7131 Slog.w(TAG, "Failed trying to unstop package "
7132 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007133 }
7134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7136 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7137 app.persistent = true;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007138 app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 }
7140 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7141 mPersistentStartingProcesses.add(app);
7142 startProcessLocked(app, "added application", app.processName);
7143 }
7144
7145 return app;
7146 }
7147
7148 public void unhandledBack() {
7149 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7150 "unhandledBack()");
7151
7152 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007153 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007154 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 TAG, "Performing unhandledBack(): stack size = " + count);
7156 if (count > 1) {
7157 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007158 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007159 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7160 Binder.restoreCallingIdentity(origId);
7161 }
7162 }
7163 }
7164
7165 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7166 String name = uri.getAuthority();
7167 ContentProviderHolder cph = getContentProviderExternal(name);
7168 ParcelFileDescriptor pfd = null;
7169 if (cph != null) {
7170 // We record the binder invoker's uid in thread-local storage before
7171 // going to the content provider to open the file. Later, in the code
7172 // that handles all permissions checks, we look for this uid and use
7173 // that rather than the Activity Manager's own uid. The effect is that
7174 // we do the check against the caller's permissions even though it looks
7175 // to the content provider like the Activity Manager itself is making
7176 // the request.
7177 sCallerIdentity.set(new Identity(
7178 Binder.getCallingPid(), Binder.getCallingUid()));
7179 try {
7180 pfd = cph.provider.openFile(uri, "r");
7181 } catch (FileNotFoundException e) {
7182 // do nothing; pfd will be returned null
7183 } finally {
7184 // Ensure that whatever happens, we clean up the identity state
7185 sCallerIdentity.remove();
7186 }
7187
7188 // We've got the fd now, so we're done with the provider.
7189 removeContentProviderExternal(name);
7190 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007191 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 }
7193 return pfd;
7194 }
7195
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007196 // Actually is sleeping or shutting down or whatever else in the future
7197 // is an inactive state.
7198 public boolean isSleeping() {
7199 return mSleeping || mShuttingDown;
7200 }
7201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202 public void goingToSleep() {
7203 synchronized(this) {
7204 mSleeping = true;
7205 mWindowManager.setEventDispatching(false);
7206
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007207 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07007208
7209 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07007210 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07007211 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
7212 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007213 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007214 }
7215 }
7216
Dianne Hackborn55280a92009-05-07 15:53:46 -07007217 public boolean shutdown(int timeout) {
7218 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7219 != PackageManager.PERMISSION_GRANTED) {
7220 throw new SecurityException("Requires permission "
7221 + android.Manifest.permission.SHUTDOWN);
7222 }
7223
7224 boolean timedout = false;
7225
7226 synchronized(this) {
7227 mShuttingDown = true;
7228 mWindowManager.setEventDispatching(false);
7229
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007230 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007231 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07007232 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007233 while (mMainStack.mResumedActivity != null
7234 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007235 long delay = endTime - System.currentTimeMillis();
7236 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007237 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07007238 timedout = true;
7239 break;
7240 }
7241 try {
7242 this.wait();
7243 } catch (InterruptedException e) {
7244 }
7245 }
7246 }
7247 }
7248
7249 mUsageStatsService.shutdown();
7250 mBatteryStatsService.shutdown();
7251
7252 return timedout;
7253 }
7254
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007255 public final void activitySlept(IBinder token) {
7256 if (localLOGV) Slog.v(
7257 TAG, "Activity slept: token=" + token);
7258
7259 ActivityRecord r = null;
7260
7261 final long origId = Binder.clearCallingIdentity();
7262
7263 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07007264 r = mMainStack.isInStackLocked(token);
7265 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007266 mMainStack.activitySleptLocked(r);
7267 }
7268 }
7269
7270 Binder.restoreCallingIdentity(origId);
7271 }
7272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 public void wakingUp() {
7274 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 mWindowManager.setEventDispatching(true);
7276 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007277 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007278 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 }
7280 }
7281
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007282 public void stopAppSwitches() {
7283 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7284 != PackageManager.PERMISSION_GRANTED) {
7285 throw new SecurityException("Requires permission "
7286 + android.Manifest.permission.STOP_APP_SWITCHES);
7287 }
7288
7289 synchronized(this) {
7290 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
7291 + APP_SWITCH_DELAY_TIME;
7292 mDidAppSwitch = false;
7293 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7294 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7295 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
7296 }
7297 }
7298
7299 public void resumeAppSwitches() {
7300 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7301 != PackageManager.PERMISSION_GRANTED) {
7302 throw new SecurityException("Requires permission "
7303 + android.Manifest.permission.STOP_APP_SWITCHES);
7304 }
7305
7306 synchronized(this) {
7307 // Note that we don't execute any pending app switches... we will
7308 // let those wait until either the timeout, or the next start
7309 // activity request.
7310 mAppSwitchesAllowedTime = 0;
7311 }
7312 }
7313
7314 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
7315 String name) {
7316 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
7317 return true;
7318 }
7319
7320 final int perm = checkComponentPermission(
7321 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08007322 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007323 if (perm == PackageManager.PERMISSION_GRANTED) {
7324 return true;
7325 }
7326
Joe Onorato8a9b2202010-02-26 18:56:32 -08007327 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007328 return false;
7329 }
7330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 public void setDebugApp(String packageName, boolean waitForDebugger,
7332 boolean persistent) {
7333 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
7334 "setDebugApp()");
7335
7336 // Note that this is not really thread safe if there are multiple
7337 // callers into it at the same time, but that's not a situation we
7338 // care about.
7339 if (persistent) {
7340 final ContentResolver resolver = mContext.getContentResolver();
7341 Settings.System.putString(
7342 resolver, Settings.System.DEBUG_APP,
7343 packageName);
7344 Settings.System.putInt(
7345 resolver, Settings.System.WAIT_FOR_DEBUGGER,
7346 waitForDebugger ? 1 : 0);
7347 }
7348
7349 synchronized (this) {
7350 if (!persistent) {
7351 mOrigDebugApp = mDebugApp;
7352 mOrigWaitForDebugger = mWaitForDebugger;
7353 }
7354 mDebugApp = packageName;
7355 mWaitForDebugger = waitForDebugger;
7356 mDebugTransient = !persistent;
7357 if (packageName != null) {
7358 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -07007359 forceStopPackageLocked(packageName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 Binder.restoreCallingIdentity(origId);
7361 }
7362 }
7363 }
7364
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07007365 void setProfileApp(ApplicationInfo app, String processName, String profileFile,
7366 ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
7367 synchronized (this) {
7368 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
7369 if (!isDebuggable) {
7370 if ((app.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
7371 throw new SecurityException("Process not debuggable: " + app.packageName);
7372 }
7373 }
7374 mProfileApp = processName;
7375 mProfileFile = profileFile;
7376 if (mProfileFd != null) {
7377 try {
7378 mProfileFd.close();
7379 } catch (IOException e) {
7380 }
7381 mProfileFd = null;
7382 }
7383 mProfileFd = profileFd;
7384 mProfileType = 0;
7385 mAutoStopProfiler = autoStopProfiler;
7386 }
7387 }
7388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 public void setAlwaysFinish(boolean enabled) {
7390 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
7391 "setAlwaysFinish()");
7392
7393 Settings.System.putInt(
7394 mContext.getContentResolver(),
7395 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
7396
7397 synchronized (this) {
7398 mAlwaysFinishActivities = enabled;
7399 }
7400 }
7401
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007402 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007404 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007405 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007406 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 }
7408 }
7409
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08007410 public boolean isUserAMonkey() {
7411 // For now the fact that there is a controller implies
7412 // we have a monkey.
7413 synchronized (this) {
7414 return mController != null;
7415 }
7416 }
7417
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007418 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06007419 synchronized (this) {
7420 mWatchers.register(watcher);
7421 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007422 }
7423
7424 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06007425 synchronized (this) {
7426 mWatchers.unregister(watcher);
7427 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007428 }
7429
Jeff Sharkeya4620792011-05-20 15:29:23 -07007430 public void registerProcessObserver(IProcessObserver observer) {
7431 mProcessObservers.register(observer);
7432 }
7433
7434 public void unregisterProcessObserver(IProcessObserver observer) {
7435 mProcessObservers.unregister(observer);
7436 }
7437
Daniel Sandler69a48172010-06-23 16:29:36 -04007438 public void setImmersive(IBinder token, boolean immersive) {
7439 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07007440 ActivityRecord r = mMainStack.isInStackLocked(token);
7441 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04007442 throw new IllegalArgumentException();
7443 }
Daniel Sandler69a48172010-06-23 16:29:36 -04007444 r.immersive = immersive;
7445 }
7446 }
7447
7448 public boolean isImmersive(IBinder token) {
7449 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07007450 ActivityRecord r = mMainStack.isInStackLocked(token);
7451 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04007452 throw new IllegalArgumentException();
7453 }
Daniel Sandler69a48172010-06-23 16:29:36 -04007454 return r.immersive;
7455 }
7456 }
7457
7458 public boolean isTopActivityImmersive() {
7459 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007460 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04007461 return (r != null) ? r.immersive : false;
7462 }
7463 }
7464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 public final void enterSafeMode() {
7466 synchronized(this) {
7467 // It only makes sense to do this before the system is ready
7468 // and started launching other packages.
7469 if (!mSystemReady) {
7470 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007471 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 } catch (RemoteException e) {
7473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 }
7475 }
7476 }
7477
Jeff Brownb09abc12011-01-13 21:08:27 -08007478 public final void showSafeModeOverlay() {
7479 View v = LayoutInflater.from(mContext).inflate(
7480 com.android.internal.R.layout.safe_mode, null);
7481 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
7482 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
7483 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
7484 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
7485 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
7486 lp.format = v.getBackground().getOpacity();
7487 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
7488 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
7489 ((WindowManager)mContext.getSystemService(
7490 Context.WINDOW_SERVICE)).addView(v, lp);
7491 }
7492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 public void noteWakeupAlarm(IIntentSender sender) {
7494 if (!(sender instanceof PendingIntentRecord)) {
7495 return;
7496 }
7497 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7498 synchronized (stats) {
7499 if (mBatteryStatsService.isOnBattery()) {
7500 mBatteryStatsService.enforceCallingPermission();
7501 PendingIntentRecord rec = (PendingIntentRecord)sender;
7502 int MY_UID = Binder.getCallingUid();
7503 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
7504 BatteryStatsImpl.Uid.Pkg pkg =
7505 stats.getPackageStatsLocked(uid, rec.key.packageName);
7506 pkg.incWakeupsLocked();
7507 }
7508 }
7509 }
7510
Dianne Hackborn64825172011-03-02 21:32:58 -08007511 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007513 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007515 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 // XXX Note: don't acquire main activity lock here, because the window
7517 // manager calls in with its locks held.
7518
7519 boolean killed = false;
7520 synchronized (mPidsSelfLocked) {
7521 int[] types = new int[pids.length];
7522 int worstType = 0;
7523 for (int i=0; i<pids.length; i++) {
7524 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7525 if (proc != null) {
7526 int type = proc.setAdj;
7527 types[i] = type;
7528 if (type > worstType) {
7529 worstType = type;
7530 }
7531 }
7532 }
7533
Dianne Hackborn64825172011-03-02 21:32:58 -08007534 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 // then constrain it so we will kill all hidden procs.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007536 if (worstType < ProcessList.HIDDEN_APP_MAX_ADJ
7537 && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07007538 worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
Dianne Hackborn64825172011-03-02 21:32:58 -08007540
7541 // If this is not a secure call, don't let it kill processes that
7542 // are important.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007543 if (!secure && worstType < ProcessList.SERVICE_ADJ) {
7544 worstType = ProcessList.SERVICE_ADJ;
Dianne Hackborn64825172011-03-02 21:32:58 -08007545 }
7546
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007547 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 for (int i=0; i<pids.length; i++) {
7549 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7550 if (proc == null) {
7551 continue;
7552 }
7553 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07007554 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007555 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007556 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
7557 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07007559 proc.killedBackground = true;
7560 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 }
7562 }
7563 }
7564 return killed;
7565 }
7566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 public final void startRunning(String pkg, String cls, String action,
7568 String data) {
7569 synchronized(this) {
7570 if (mStartRunning) {
7571 return;
7572 }
7573 mStartRunning = true;
7574 mTopComponent = pkg != null && cls != null
7575 ? new ComponentName(pkg, cls) : null;
7576 mTopAction = action != null ? action : Intent.ACTION_MAIN;
7577 mTopData = data;
7578 if (!mSystemReady) {
7579 return;
7580 }
7581 }
7582
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007583 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 }
7585
7586 private void retrieveSettings() {
7587 final ContentResolver resolver = mContext.getContentResolver();
7588 String debugApp = Settings.System.getString(
7589 resolver, Settings.System.DEBUG_APP);
7590 boolean waitForDebugger = Settings.System.getInt(
7591 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
7592 boolean alwaysFinishActivities = Settings.System.getInt(
7593 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
7594
7595 Configuration configuration = new Configuration();
7596 Settings.System.getConfiguration(resolver, configuration);
7597
7598 synchronized (this) {
7599 mDebugApp = mOrigDebugApp = debugApp;
7600 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
7601 mAlwaysFinishActivities = alwaysFinishActivities;
7602 // This happens before any activities are started, so we can
7603 // change mConfiguration in-place.
Dianne Hackborn813075a62011-11-14 17:45:19 -08007604 updateConfigurationLocked(configuration, null, false, true);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007605 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 }
7607 }
7608
7609 public boolean testIsSystemReady() {
7610 // no need to synchronize(this) just to read & return the value
7611 return mSystemReady;
7612 }
7613
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007614 private static File getCalledPreBootReceiversFile() {
7615 File dataDir = Environment.getDataDirectory();
7616 File systemDir = new File(dataDir, "system");
7617 File fname = new File(systemDir, "called_pre_boots.dat");
7618 return fname;
7619 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07007620
7621 static final int LAST_DONE_VERSION = 10000;
7622
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007623 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
7624 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
7625 File file = getCalledPreBootReceiversFile();
7626 FileInputStream fis = null;
7627 try {
7628 fis = new FileInputStream(file);
7629 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07007630 int fvers = dis.readInt();
7631 if (fvers == LAST_DONE_VERSION) {
7632 String vers = dis.readUTF();
7633 String codename = dis.readUTF();
7634 String build = dis.readUTF();
7635 if (android.os.Build.VERSION.RELEASE.equals(vers)
7636 && android.os.Build.VERSION.CODENAME.equals(codename)
7637 && android.os.Build.VERSION.INCREMENTAL.equals(build)) {
7638 int num = dis.readInt();
7639 while (num > 0) {
7640 num--;
7641 String pkg = dis.readUTF();
7642 String cls = dis.readUTF();
7643 lastDoneReceivers.add(new ComponentName(pkg, cls));
7644 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007645 }
7646 }
7647 } catch (FileNotFoundException e) {
7648 } catch (IOException e) {
7649 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
7650 } finally {
7651 if (fis != null) {
7652 try {
7653 fis.close();
7654 } catch (IOException e) {
7655 }
7656 }
7657 }
7658 return lastDoneReceivers;
7659 }
7660
7661 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
7662 File file = getCalledPreBootReceiversFile();
7663 FileOutputStream fos = null;
7664 DataOutputStream dos = null;
7665 try {
7666 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
7667 fos = new FileOutputStream(file);
7668 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07007669 dos.writeInt(LAST_DONE_VERSION);
7670 dos.writeUTF(android.os.Build.VERSION.RELEASE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007671 dos.writeUTF(android.os.Build.VERSION.CODENAME);
Dianne Hackborn661cd522011-08-22 00:26:20 -07007672 dos.writeUTF(android.os.Build.VERSION.INCREMENTAL);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007673 dos.writeInt(list.size());
7674 for (int i=0; i<list.size(); i++) {
7675 dos.writeUTF(list.get(i).getPackageName());
7676 dos.writeUTF(list.get(i).getClassName());
7677 }
7678 } catch (IOException e) {
7679 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
7680 file.delete();
7681 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07007682 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007683 if (dos != null) {
7684 try {
7685 dos.close();
7686 } catch (IOException e) {
7687 // TODO Auto-generated catch block
7688 e.printStackTrace();
7689 }
7690 }
7691 }
7692 }
7693
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007694 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 synchronized(this) {
7696 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007697 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 return;
7699 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007700
7701 // Check to see if there are any update receivers to run.
7702 if (!mDidUpdate) {
7703 if (mWaitingUpdate) {
7704 return;
7705 }
7706 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
7707 List<ResolveInfo> ris = null;
7708 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007709 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007710 intent, null, 0);
7711 } catch (RemoteException e) {
7712 }
7713 if (ris != null) {
7714 for (int i=ris.size()-1; i>=0; i--) {
7715 if ((ris.get(i).activityInfo.applicationInfo.flags
7716 &ApplicationInfo.FLAG_SYSTEM) == 0) {
7717 ris.remove(i);
7718 }
7719 }
7720 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007721
7722 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
7723
7724 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007725 for (int i=0; i<ris.size(); i++) {
7726 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007727 ComponentName comp = new ComponentName(ai.packageName, ai.name);
7728 if (lastDoneReceivers.contains(comp)) {
7729 ris.remove(i);
7730 i--;
7731 }
7732 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07007733
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007734 for (int i=0; i<ris.size(); i++) {
7735 ActivityInfo ai = ris.get(i).activityInfo;
7736 ComponentName comp = new ComponentName(ai.packageName, ai.name);
7737 doneReceivers.add(comp);
7738 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007739 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08007740 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007741 finisher = new IIntentReceiver.Stub() {
7742 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07007743 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07007744 boolean sticky) {
7745 // The raw IIntentReceiver interface is called
7746 // with the AM lock held, so redispatch to
7747 // execute our code without the lock.
7748 mHandler.post(new Runnable() {
7749 public void run() {
7750 synchronized (ActivityManagerService.this) {
7751 mDidUpdate = true;
7752 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007753 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn661cd522011-08-22 00:26:20 -07007754 showBootMessage(mContext.getText(
7755 R.string.android_upgrading_complete),
7756 false);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07007757 systemReady(goingCallback);
7758 }
7759 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007760 }
7761 };
7762 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007763 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Amith Yamasani742a6712011-05-04 14:49:28 -07007764 /* TODO: Send this to all users */
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007765 broadcastIntentLocked(null, null, intent, null, finisher,
Amith Yamasani742a6712011-05-04 14:49:28 -07007766 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
7767 Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08007768 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007769 mWaitingUpdate = true;
7770 }
7771 }
7772 }
7773 if (mWaitingUpdate) {
7774 return;
7775 }
7776 mDidUpdate = true;
7777 }
7778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 mSystemReady = true;
7780 if (!mStartRunning) {
7781 return;
7782 }
7783 }
7784
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007785 ArrayList<ProcessRecord> procsToKill = null;
7786 synchronized(mPidsSelfLocked) {
7787 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
7788 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
7789 if (!isAllowedWhileBooting(proc.info)){
7790 if (procsToKill == null) {
7791 procsToKill = new ArrayList<ProcessRecord>();
7792 }
7793 procsToKill.add(proc);
7794 }
7795 }
7796 }
7797
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007798 synchronized(this) {
7799 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007800 for (int i=procsToKill.size()-1; i>=0; i--) {
7801 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007802 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007803 removeProcessLocked(proc, true, false, "system update done");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007804 }
7805 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007806
7807 // Now that we have cleaned up any update processes, we
7808 // are ready to start launching real processes and know that
7809 // we won't trample on them any more.
7810 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007811 }
7812
Joe Onorato8a9b2202010-02-26 18:56:32 -08007813 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007814 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 SystemClock.uptimeMillis());
7816
7817 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007818 // Make sure we have no pre-ready processes sitting around.
7819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
7821 ResolveInfo ri = mContext.getPackageManager()
7822 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07007823 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824 CharSequence errorMsg = null;
7825 if (ri != null) {
7826 ActivityInfo ai = ri.activityInfo;
7827 ApplicationInfo app = ai.applicationInfo;
7828 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7829 mTopAction = Intent.ACTION_FACTORY_TEST;
7830 mTopData = null;
7831 mTopComponent = new ComponentName(app.packageName,
7832 ai.name);
7833 } else {
7834 errorMsg = mContext.getResources().getText(
7835 com.android.internal.R.string.factorytest_not_system);
7836 }
7837 } else {
7838 errorMsg = mContext.getResources().getText(
7839 com.android.internal.R.string.factorytest_no_action);
7840 }
7841 if (errorMsg != null) {
7842 mTopAction = null;
7843 mTopData = null;
7844 mTopComponent = null;
7845 Message msg = Message.obtain();
7846 msg.what = SHOW_FACTORY_ERROR_MSG;
7847 msg.getData().putCharSequence("msg", errorMsg);
7848 mHandler.sendMessage(msg);
7849 }
7850 }
7851 }
7852
7853 retrieveSettings();
7854
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007855 if (goingCallback != null) goingCallback.run();
7856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 synchronized (this) {
7858 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
7859 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007860 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007861 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 if (apps != null) {
7863 int N = apps.size();
7864 int i;
7865 for (i=0; i<N; i++) {
7866 ApplicationInfo info
7867 = (ApplicationInfo)apps.get(i);
7868 if (info != null &&
7869 !info.packageName.equals("android")) {
7870 addAppLocked(info);
7871 }
7872 }
7873 }
7874 } catch (RemoteException ex) {
7875 // pm is in same process, this will never happen.
7876 }
7877 }
7878
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007879 // Start up initial activity.
7880 mBooting = true;
7881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007883 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 Message msg = Message.obtain();
7885 msg.what = SHOW_UID_ERROR_MSG;
7886 mHandler.sendMessage(msg);
7887 }
7888 } catch (RemoteException e) {
7889 }
7890
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007891 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
7893 }
7894
Dan Egnorb7f03672009-12-09 16:22:32 -08007895 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007896 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007898 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007899 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 startAppProblemLocked(app);
7901 app.stopFreezingAllLocked();
7902 return handleAppCrashLocked(app);
7903 }
7904
Dan Egnorb7f03672009-12-09 16:22:32 -08007905 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007906 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007908 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007909 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
7910 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 startAppProblemLocked(app);
7912 app.stopFreezingAllLocked();
7913 }
7914
7915 /**
7916 * Generate a process error record, suitable for attachment to a ProcessRecord.
7917 *
7918 * @param app The ProcessRecord in which the error occurred.
7919 * @param condition Crashing, Application Not Responding, etc. Values are defined in
7920 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08007921 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 * @param shortMsg Short message describing the crash.
7923 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08007924 * @param stackTrace Full crash stack trace, may be null.
7925 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926 * @return Returns a fully-formed AppErrorStateInfo record.
7927 */
7928 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007929 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007930 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08007931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 report.condition = condition;
7933 report.processName = app.processName;
7934 report.pid = app.pid;
7935 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08007936 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 report.shortMsg = shortMsg;
7938 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08007939 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940
7941 return report;
7942 }
7943
Dan Egnor42471dd2010-01-07 17:25:22 -08007944 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 synchronized (this) {
7946 app.crashing = false;
7947 app.crashingReport = null;
7948 app.notResponding = false;
7949 app.notRespondingReport = null;
7950 if (app.anrDialog == fromDialog) {
7951 app.anrDialog = null;
7952 }
7953 if (app.waitDialog == fromDialog) {
7954 app.waitDialog = null;
7955 }
7956 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08007957 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007958 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07007959 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
7960 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007961 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007963 }
7964 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007965
Dan Egnorb7f03672009-12-09 16:22:32 -08007966 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 long now = SystemClock.uptimeMillis();
7968
7969 Long crashTime = mProcessCrashTimes.get(app.info.processName,
7970 app.info.uid);
Dianne Hackborn7d608422011-08-07 16:24:18 -07007971 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007972 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007973 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007974 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007975 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007977 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
7978 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007979 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007980 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007982 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007983 }
7984 }
7985 if (!app.persistent) {
7986 // We don't want to start this process again until the user
7987 // explicitly does so... but for persistent process, we really
7988 // need to keep it running. If a persistent process is actually
7989 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08007990 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007991 app.info.processName);
7992 mBadProcesses.put(app.info.processName, app.info.uid, now);
7993 app.bad = true;
7994 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
7995 app.removed = true;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07007996 // Don't let services in this process be restarted and potentially
7997 // annoy the user repeatedly. Unless it is persistent, since those
7998 // processes run critical code.
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007999 removeProcessLocked(app, false, false, "crash");
Dianne Hackborncb44d962011-03-10 17:02:27 -08008000 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 return false;
8002 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08008003 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008004 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008005 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008006 if (r.app == app) {
8007 // If the top running activity is from this crashing
8008 // process, then terminate it to avoid getting in a loop.
8009 Slog.w(TAG, " Force finishing activity "
8010 + r.intent.getComponent().flattenToShortString());
Dianne Hackbornbe707852011-11-11 14:32:10 -08008011 int index = mMainStack.indexOfActivityLocked(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008012 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008013 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08008014 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008015 // stopped, to avoid a situation where one will get
8016 // re-start our crashing activity once it gets resumed again.
8017 index--;
8018 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008019 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008020 if (r.state == ActivityState.RESUMED
8021 || r.state == ActivityState.PAUSING
8022 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08008023 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008024 Slog.w(TAG, " Force finishing activity "
8025 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008026 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008027 Activity.RESULT_CANCELED, null, "crashed");
8028 }
8029 }
8030 }
8031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 }
8033
8034 // Bump up the crash count of any services currently running in the proc.
8035 if (app.services.size() != 0) {
8036 // Any services running in the application need to be placed
8037 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008038 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008039 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008040 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 sr.crashCount++;
8042 }
8043 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02008044
8045 // If the crashing process is what we consider to be the "home process" and it has been
8046 // replaced by a third-party app, clear the package preferred activities from packages
8047 // with a home activity running in the process to prevent a repeatedly crashing app
8048 // from blocking the user to manually clear the list.
8049 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
8050 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
8051 Iterator it = mHomeProcess.activities.iterator();
8052 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07008053 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02008054 if (r.isHomeActivity) {
8055 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
8056 try {
8057 ActivityThread.getPackageManager()
8058 .clearPackagePreferredActivities(r.packageName);
8059 } catch (RemoteException c) {
8060 // pm is in same process, this will never happen.
8061 }
8062 }
8063 }
8064 }
8065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8067 return true;
8068 }
8069
8070 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008071 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8072 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 skipCurrentReceiverLocked(app);
8074 }
8075
8076 void skipCurrentReceiverLocked(ProcessRecord app) {
Christopher Tatef46723b2012-01-26 14:19:24 -08008077 for (BroadcastQueue queue : mBroadcastQueues) {
8078 queue.skipCurrentReceiverLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008079 }
8080 }
8081
Dan Egnor60d87622009-12-16 16:32:58 -08008082 /**
8083 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8084 * The application process will exit immediately after this call returns.
8085 * @param app object of the crashing app, null for the system server
8086 * @param crashInfo describing the exception
8087 */
8088 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08008089 ProcessRecord r = findAppProcess(app, "Crash");
Jeff Sharkeya353d262011-10-28 11:12:06 -07008090 final String processName = app == null ? "system_server"
8091 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08008092
8093 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07008094 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08008095 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008096 crashInfo.exceptionClassName,
8097 crashInfo.exceptionMessage,
8098 crashInfo.throwFileName,
8099 crashInfo.throwLineNumber);
8100
Jeff Sharkeya353d262011-10-28 11:12:06 -07008101 addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008102
8103 crashApplication(r, crashInfo);
8104 }
8105
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008106 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008107 IBinder app,
8108 int violationMask,
8109 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08008110 ProcessRecord r = findAppProcess(app, "StrictMode");
8111 if (r == null) {
8112 return;
8113 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008114
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008115 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08008116 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008117 boolean logIt = true;
8118 synchronized (mAlreadyLoggedViolatedStacks) {
8119 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
8120 logIt = false;
8121 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008122 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008123 // the relative pain numbers, without logging all
8124 // the stack traces repeatedly. We'd want to do
8125 // likewise in the client code, which also does
8126 // dup suppression, before the Binder call.
8127 } else {
8128 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
8129 mAlreadyLoggedViolatedStacks.clear();
8130 }
8131 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
8132 }
8133 }
8134 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008135 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008136 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008137 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008138
8139 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
8140 AppErrorResult result = new AppErrorResult();
8141 synchronized (this) {
8142 final long origId = Binder.clearCallingIdentity();
8143
8144 Message msg = Message.obtain();
8145 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
8146 HashMap<String, Object> data = new HashMap<String, Object>();
8147 data.put("result", result);
8148 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008149 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008150 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008151 msg.obj = data;
8152 mHandler.sendMessage(msg);
8153
8154 Binder.restoreCallingIdentity(origId);
8155 }
8156 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07008157 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008158 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008159 }
8160
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008161 // Depending on the policy in effect, there could be a bunch of
8162 // these in quick succession so we try to batch these together to
8163 // minimize disk writes, number of dropbox entries, and maximize
8164 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008165 private void logStrictModeViolationToDropBox(
8166 ProcessRecord process,
8167 StrictMode.ViolationInfo info) {
8168 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008169 return;
8170 }
8171 final boolean isSystemApp = process == null ||
8172 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
8173 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07008174 final String processName = process == null ? "unknown" : process.processName;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008175 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
8176 final DropBoxManager dbox = (DropBoxManager)
8177 mContext.getSystemService(Context.DROPBOX_SERVICE);
8178
8179 // Exit early if the dropbox isn't configured to accept this report type.
8180 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
8181
8182 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008183 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008184 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
8185 synchronized (sb) {
8186 bufferWasEmpty = sb.length() == 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07008187 appendDropBoxProcessHeaders(process, processName, sb);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008188 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8189 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008190 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
8191 if (info.violationNumThisLoop != 0) {
8192 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
8193 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07008194 if (info.numAnimationsRunning != 0) {
8195 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
8196 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07008197 if (info.broadcastIntentAction != null) {
8198 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
8199 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08008200 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008201 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008202 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08008203 if (info.numInstances != -1) {
8204 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
8205 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08008206 if (info.tags != null) {
8207 for (String tag : info.tags) {
8208 sb.append("Span-Tag: ").append(tag).append("\n");
8209 }
8210 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008211 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008212 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
8213 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008214 }
8215 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008216
8217 // Only buffer up to ~64k. Various logging bits truncate
8218 // things at 128k.
8219 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008220 }
8221
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008222 // Flush immediately if the buffer's grown too large, or this
8223 // is a non-system app. Non-system apps are isolated with a
8224 // different tag & policy and not batched.
8225 //
8226 // Batching is useful during internal testing with
8227 // StrictMode settings turned up high. Without batching,
8228 // thousands of separate files could be created on boot.
8229 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008230 new Thread("Error dump: " + dropboxTag) {
8231 @Override
8232 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008233 String report;
8234 synchronized (sb) {
8235 report = sb.toString();
8236 sb.delete(0, sb.length());
8237 sb.trimToSize();
8238 }
8239 if (report.length() != 0) {
8240 dbox.addText(dropboxTag, report);
8241 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008242 }
8243 }.start();
8244 return;
8245 }
8246
8247 // System app batching:
8248 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008249 // An existing dropbox-writing thread is outstanding, so
8250 // we don't need to start it up. The existing thread will
8251 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008252 return;
8253 }
8254
8255 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
8256 // (After this point, we shouldn't access AMS internal data structures.)
8257 new Thread("Error dump: " + dropboxTag) {
8258 @Override
8259 public void run() {
8260 // 5 second sleep to let stacks arrive and be batched together
8261 try {
8262 Thread.sleep(5000); // 5 seconds
8263 } catch (InterruptedException e) {}
8264
8265 String errorReport;
8266 synchronized (mStrictModeBuffer) {
8267 errorReport = mStrictModeBuffer.toString();
8268 if (errorReport.length() == 0) {
8269 return;
8270 }
8271 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
8272 mStrictModeBuffer.trimToSize();
8273 }
8274 dbox.addText(dropboxTag, errorReport);
8275 }
8276 }.start();
8277 }
8278
Dan Egnor60d87622009-12-16 16:32:58 -08008279 /**
8280 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8281 * @param app object of the crashing app, null for the system server
8282 * @param tag reported by the caller
8283 * @param crashInfo describing the context of the error
8284 * @return true if the process should exit immediately (WTF is fatal)
8285 */
8286 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008287 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08008288 ProcessRecord r = findAppProcess(app, "WTF");
Jeff Sharkeya353d262011-10-28 11:12:06 -07008289 final String processName = app == null ? "system_server"
8290 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08008291
8292 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07008293 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08008294 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008295 tag, crashInfo.exceptionMessage);
8296
Jeff Sharkeya353d262011-10-28 11:12:06 -07008297 addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008298
Dianne Hackborn1ab43772011-03-15 14:38:02 -07008299 if (r != null && r.pid != Process.myPid() &&
8300 Settings.Secure.getInt(mContext.getContentResolver(),
8301 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008302 crashApplication(r, crashInfo);
8303 return true;
8304 } else {
8305 return false;
8306 }
8307 }
8308
8309 /**
8310 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8311 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8312 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08008313 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08008314 if (app == null) {
8315 return null;
8316 }
8317
8318 synchronized (this) {
8319 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8320 final int NA = apps.size();
8321 for (int ia=0; ia<NA; ia++) {
8322 ProcessRecord p = apps.valueAt(ia);
8323 if (p.thread != null && p.thread.asBinder() == app) {
8324 return p;
8325 }
8326 }
8327 }
8328
Dianne Hackborncb44d962011-03-10 17:02:27 -08008329 Slog.w(TAG, "Can't find mystery application for " + reason
8330 + " from pid=" + Binder.getCallingPid()
8331 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008332 return null;
8333 }
8334 }
8335
8336 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008337 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
8338 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08008339 */
Jeff Sharkeya353d262011-10-28 11:12:06 -07008340 private void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
8341 StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08008342 // Watchdog thread ends up invoking this function (with
8343 // a null ProcessRecord) to add the stack file to dropbox.
8344 // Do not acquire a lock on this (am) in such cases, as it
8345 // could cause a potential deadlock, if and when watchdog
8346 // is invoked due to unavailability of lock on am and it
8347 // would prevent watchdog from killing system_server.
8348 if (process == null) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07008349 sb.append("Process: ").append(processName).append("\n");
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08008350 return;
8351 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07008352 // Note: ProcessRecord 'process' is guarded by the service
8353 // instance. (notably process.pkgList, which could otherwise change
8354 // concurrently during execution of this method)
8355 synchronized (this) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07008356 sb.append("Process: ").append(processName).append("\n");
Dan Egnora455d192010-03-12 08:52:28 -08008357 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008358 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08008359 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8360 for (String pkg : process.pkgList) {
8361 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08008362 try {
Dan Egnora455d192010-03-12 08:52:28 -08008363 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8364 if (pi != null) {
8365 sb.append(" v").append(pi.versionCode);
8366 if (pi.versionName != null) {
8367 sb.append(" (").append(pi.versionName).append(")");
8368 }
8369 }
8370 } catch (RemoteException e) {
8371 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008372 }
Dan Egnora455d192010-03-12 08:52:28 -08008373 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08008374 }
Dan Egnora455d192010-03-12 08:52:28 -08008375 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008376 }
8377
8378 private static String processClass(ProcessRecord process) {
8379 if (process == null || process.pid == MY_PID) {
8380 return "system_server";
8381 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
8382 return "system_app";
8383 } else {
8384 return "data_app";
8385 }
8386 }
8387
8388 /**
8389 * Write a description of an error (crash, WTF, ANR) to the drop box.
8390 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
8391 * @param process which caused the error, null means the system server
8392 * @param activity which triggered the error, null if unknown
8393 * @param parent activity related to the error, null if unknown
8394 * @param subject line related to the error, null if absent
8395 * @param report in long form describing the error, null if absent
8396 * @param logFile to include in the report, null if none
8397 * @param crashInfo giving an application stack trace, null if absent
8398 */
8399 public void addErrorToDropBox(String eventType,
Jeff Sharkeya353d262011-10-28 11:12:06 -07008400 ProcessRecord process, String processName, ActivityRecord activity,
8401 ActivityRecord parent, String subject,
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008402 final String report, final File logFile,
8403 final ApplicationErrorReport.CrashInfo crashInfo) {
8404 // NOTE -- this must never acquire the ActivityManagerService lock,
8405 // otherwise the watchdog may be prevented from resetting the system.
8406
8407 final String dropboxTag = processClass(process) + "_" + eventType;
8408 final DropBoxManager dbox = (DropBoxManager)
8409 mContext.getSystemService(Context.DROPBOX_SERVICE);
8410
8411 // Exit early if the dropbox isn't configured to accept this report type.
8412 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
8413
8414 final StringBuilder sb = new StringBuilder(1024);
Jeff Sharkeya353d262011-10-28 11:12:06 -07008415 appendDropBoxProcessHeaders(process, processName, sb);
Dan Egnora455d192010-03-12 08:52:28 -08008416 if (activity != null) {
8417 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8418 }
8419 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8420 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8421 }
8422 if (parent != null && parent != activity) {
8423 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8424 }
8425 if (subject != null) {
8426 sb.append("Subject: ").append(subject).append("\n");
8427 }
8428 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02008429 if (Debug.isDebuggerConnected()) {
8430 sb.append("Debugger: Connected\n");
8431 }
Dan Egnora455d192010-03-12 08:52:28 -08008432 sb.append("\n");
8433
8434 // Do the rest in a worker thread to avoid blocking the caller on I/O
8435 // (After this point, we shouldn't access AMS internal data structures.)
8436 Thread worker = new Thread("Error dump: " + dropboxTag) {
8437 @Override
8438 public void run() {
8439 if (report != null) {
8440 sb.append(report);
8441 }
8442 if (logFile != null) {
8443 try {
8444 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8445 } catch (IOException e) {
8446 Slog.e(TAG, "Error reading " + logFile, e);
8447 }
8448 }
8449 if (crashInfo != null && crashInfo.stackTrace != null) {
8450 sb.append(crashInfo.stackTrace);
8451 }
8452
8453 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
8454 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
8455 if (lines > 0) {
8456 sb.append("\n");
8457
8458 // Merge several logcat streams, and take the last N lines
8459 InputStreamReader input = null;
8460 try {
8461 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
8462 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
8463 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
8464
8465 try { logcat.getOutputStream().close(); } catch (IOException e) {}
8466 try { logcat.getErrorStream().close(); } catch (IOException e) {}
8467 input = new InputStreamReader(logcat.getInputStream());
8468
8469 int num;
8470 char[] buf = new char[8192];
8471 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
8472 } catch (IOException e) {
8473 Slog.e(TAG, "Error running logcat", e);
8474 } finally {
8475 if (input != null) try { input.close(); } catch (IOException e) {}
8476 }
8477 }
8478
8479 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08008480 }
Dan Egnora455d192010-03-12 08:52:28 -08008481 };
8482
8483 if (process == null || process.pid == MY_PID) {
8484 worker.run(); // We may be about to die -- need to run this synchronously
8485 } else {
8486 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08008487 }
8488 }
8489
8490 /**
8491 * Bring up the "unexpected error" dialog box for a crashing app.
8492 * Deal with edge cases (intercepts from instrumented applications,
8493 * ActivityController, error intent receivers, that sort of thing).
8494 * @param r the application crashing
8495 * @param crashInfo describing the failure
8496 */
8497 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008498 long timeMillis = System.currentTimeMillis();
8499 String shortMsg = crashInfo.exceptionClassName;
8500 String longMsg = crashInfo.exceptionMessage;
8501 String stackTrace = crashInfo.stackTrace;
8502 if (shortMsg != null && longMsg != null) {
8503 longMsg = shortMsg + ": " + longMsg;
8504 } else if (shortMsg != null) {
8505 longMsg = shortMsg;
8506 }
8507
Dan Egnor60d87622009-12-16 16:32:58 -08008508 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008510 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008511 try {
8512 String name = r != null ? r.processName : null;
8513 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008514 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008515 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008516 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 + " at watcher's request");
8518 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008519 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 }
8521 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008522 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008523 }
8524 }
8525
8526 final long origId = Binder.clearCallingIdentity();
8527
8528 // If this process is running instrumentation, finish it.
8529 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008530 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008532 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
8533 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 Bundle info = new Bundle();
8535 info.putString("shortMsg", shortMsg);
8536 info.putString("longMsg", longMsg);
8537 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8538 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008539 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 }
8541
Dan Egnor60d87622009-12-16 16:32:58 -08008542 // If we can't identify the process or it's already exceeded its crash quota,
8543 // quit right away without showing a crash dialog.
8544 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008546 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008547 }
8548
8549 Message msg = Message.obtain();
8550 msg.what = SHOW_ERROR_MSG;
8551 HashMap data = new HashMap();
8552 data.put("result", result);
8553 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 msg.obj = data;
8555 mHandler.sendMessage(msg);
8556
8557 Binder.restoreCallingIdentity(origId);
8558 }
8559
8560 int res = result.get();
8561
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008562 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 synchronized (this) {
8564 if (r != null) {
8565 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8566 SystemClock.uptimeMillis());
8567 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008568 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008569 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008570 }
8571 }
8572
8573 if (appErrorIntent != null) {
8574 try {
8575 mContext.startActivity(appErrorIntent);
8576 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008577 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580 }
Dan Egnorb7f03672009-12-09 16:22:32 -08008581
8582 Intent createAppErrorIntentLocked(ProcessRecord r,
8583 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
8584 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008585 if (report == null) {
8586 return null;
8587 }
8588 Intent result = new Intent(Intent.ACTION_APP_ERROR);
8589 result.setComponent(r.errorReportReceiver);
8590 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
8591 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8592 return result;
8593 }
8594
Dan Egnorb7f03672009-12-09 16:22:32 -08008595 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
8596 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008597 if (r.errorReportReceiver == null) {
8598 return null;
8599 }
8600
8601 if (!r.crashing && !r.notResponding) {
8602 return null;
8603 }
8604
Dan Egnorb7f03672009-12-09 16:22:32 -08008605 ApplicationErrorReport report = new ApplicationErrorReport();
8606 report.packageName = r.info.packageName;
8607 report.installerPackageName = r.errorReportReceiver.getPackageName();
8608 report.processName = r.processName;
8609 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01008610 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008611
Dan Egnorb7f03672009-12-09 16:22:32 -08008612 if (r.crashing) {
8613 report.type = ApplicationErrorReport.TYPE_CRASH;
8614 report.crashInfo = crashInfo;
8615 } else if (r.notResponding) {
8616 report.type = ApplicationErrorReport.TYPE_ANR;
8617 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008618
Dan Egnorb7f03672009-12-09 16:22:32 -08008619 report.anrInfo.activity = r.notRespondingReport.tag;
8620 report.anrInfo.cause = r.notRespondingReport.shortMsg;
8621 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008622 }
8623
Dan Egnorb7f03672009-12-09 16:22:32 -08008624 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008625 }
8626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
8628 // assume our apps are happy - lazy create the list
8629 List<ActivityManager.ProcessErrorStateInfo> errList = null;
8630
8631 synchronized (this) {
8632
8633 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008634 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8635 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 if ((app.thread != null) && (app.crashing || app.notResponding)) {
8637 // This one's in trouble, so we'll generate a report for it
8638 // crashes are higher priority (in case there's a crash *and* an anr)
8639 ActivityManager.ProcessErrorStateInfo report = null;
8640 if (app.crashing) {
8641 report = app.crashingReport;
8642 } else if (app.notResponding) {
8643 report = app.notRespondingReport;
8644 }
8645
8646 if (report != null) {
8647 if (errList == null) {
8648 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
8649 }
8650 errList.add(report);
8651 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008652 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 " crashing = " + app.crashing +
8654 " notResponding = " + app.notResponding);
8655 }
8656 }
8657 }
8658 }
8659
8660 return errList;
8661 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07008662
8663 static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008664 if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07008665 if (currApp != null) {
8666 currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
8667 }
8668 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008669 } else if (adj >= ProcessList.SERVICE_B_ADJ) {
8670 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008671 } else if (adj >= ProcessList.HOME_APP_ADJ) {
8672 if (currApp != null) {
8673 currApp.lru = 0;
8674 }
8675 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008676 } else if (adj >= ProcessList.SERVICE_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07008677 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
8678 } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
8679 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
8680 } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
8681 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
8682 } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
8683 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
8684 } else {
8685 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
8686 }
8687 }
8688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
8690 // Lazy instantiation of list
8691 List<ActivityManager.RunningAppProcessInfo> runList = null;
8692 synchronized (this) {
8693 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008694 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8695 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008696 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
8697 // Generate process state info for running application
8698 ActivityManager.RunningAppProcessInfo currApp =
8699 new ActivityManager.RunningAppProcessInfo(app.processName,
8700 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07008701 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07008702 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07008703 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07008704 }
Dianne Hackborn42499172010-10-15 18:45:07 -07008705 if (app.persistent) {
8706 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
8707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 int adj = app.curAdj;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008709 currApp.importance = oomAdjToImportance(adj, currApp);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008710 currApp.importanceReasonCode = app.adjTypeCode;
8711 if (app.adjSource instanceof ProcessRecord) {
8712 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008713 currApp.importanceReasonImportance = oomAdjToImportance(
8714 app.adjSourceOom, null);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008715 } else if (app.adjSource instanceof ActivityRecord) {
8716 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008717 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
8718 }
8719 if (app.adjTarget instanceof ComponentName) {
8720 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
8721 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008722 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 // + " lru=" + currApp.lru);
8724 if (runList == null) {
8725 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
8726 }
8727 runList.add(currApp);
8728 }
8729 }
8730 }
8731 return runList;
8732 }
8733
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008734 public List<ApplicationInfo> getRunningExternalApplications() {
8735 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
8736 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
8737 if (runningApps != null && runningApps.size() > 0) {
8738 Set<String> extList = new HashSet<String>();
8739 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
8740 if (app.pkgList != null) {
8741 for (String pkg : app.pkgList) {
8742 extList.add(pkg);
8743 }
8744 }
8745 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008746 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008747 for (String pkg : extList) {
8748 try {
8749 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
8750 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
8751 retList.add(info);
8752 }
8753 } catch (RemoteException e) {
8754 }
8755 }
8756 }
8757 return retList;
8758 }
8759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008760 @Override
8761 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008762 if (checkCallingPermission(android.Manifest.permission.DUMP)
8763 != PackageManager.PERMISSION_GRANTED) {
8764 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8765 + Binder.getCallingPid()
8766 + ", uid=" + Binder.getCallingUid()
8767 + " without permission "
8768 + android.Manifest.permission.DUMP);
8769 return;
8770 }
8771
8772 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008773 boolean dumpClient = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008774 String dumpPackage = null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008775
8776 int opti = 0;
8777 while (opti < args.length) {
8778 String opt = args[opti];
8779 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
8780 break;
8781 }
8782 opti++;
8783 if ("-a".equals(opt)) {
8784 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008785 } else if ("-c".equals(opt)) {
8786 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008787 } else if ("-h".equals(opt)) {
8788 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008789 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008790 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008791 pw.println(" a[ctivities]: activity stack state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008792 pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
8793 pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
8794 pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008795 pw.println(" o[om]: out of memory management");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008796 pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
Marco Nelissen18cb2872011-11-15 11:19:53 -08008797 pw.println(" provider [COMP_SPEC]: provider client-side state");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008798 pw.println(" s[ervices] [COMP_SPEC ...]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008799 pw.println(" service [COMP_SPEC]: service client-side state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008800 pw.println(" package [PACKAGE_NAME]: all state related to given package");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008801 pw.println(" all: dump all activities");
8802 pw.println(" top: dump the top activity");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008803 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008804 pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
8805 pw.println(" a partial substring in a component name, a");
8806 pw.println(" hex object identifier.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008807 pw.println(" -a: include all available server state.");
8808 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008810 } else {
8811 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008813 }
8814
8815 // Is the caller requesting to dump a particular piece of data?
8816 if (opti < args.length) {
8817 String cmd = args[opti];
8818 opti++;
8819 if ("activities".equals(cmd) || "a".equals(cmd)) {
8820 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008821 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008823 return;
8824 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008825 String[] newArgs;
8826 String name;
8827 if (opti >= args.length) {
8828 name = null;
8829 newArgs = EMPTY_STRING_ARRAY;
8830 } else {
8831 name = args[opti];
8832 opti++;
8833 newArgs = new String[args.length - opti];
8834 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8835 args.length - opti);
8836 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008837 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008838 dumpBroadcastsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008839 }
8840 return;
8841 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008842 String[] newArgs;
8843 String name;
8844 if (opti >= args.length) {
8845 name = null;
8846 newArgs = EMPTY_STRING_ARRAY;
8847 } else {
8848 name = args[opti];
8849 opti++;
8850 newArgs = new String[args.length - opti];
8851 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8852 args.length - opti);
8853 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008854 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008855 dumpPendingIntentsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008856 }
8857 return;
8858 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008859 String[] newArgs;
8860 String name;
8861 if (opti >= args.length) {
8862 name = null;
8863 newArgs = EMPTY_STRING_ARRAY;
8864 } else {
8865 name = args[opti];
8866 opti++;
8867 newArgs = new String[args.length - opti];
8868 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8869 args.length - opti);
8870 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008871 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008872 dumpProcessesLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008873 }
8874 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008875 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
8876 synchronized (this) {
8877 dumpOomLocked(fd, pw, args, opti, true);
8878 }
8879 return;
Marco Nelissen18cb2872011-11-15 11:19:53 -08008880 } else if ("provider".equals(cmd)) {
8881 String[] newArgs;
8882 String name;
8883 if (opti >= args.length) {
8884 name = null;
8885 newArgs = EMPTY_STRING_ARRAY;
8886 } else {
8887 name = args[opti];
8888 opti++;
8889 newArgs = new String[args.length - opti];
8890 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8891 }
8892 if (!dumpProvider(fd, pw, name, newArgs, 0, dumpAll)) {
8893 pw.println("No providers match: " + name);
8894 pw.println("Use -h for help.");
8895 }
8896 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008897 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
8898 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008899 dumpProvidersLocked(fd, pw, args, opti, true, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008900 }
8901 return;
8902 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008903 String[] newArgs;
8904 String name;
8905 if (opti >= args.length) {
8906 name = null;
8907 newArgs = EMPTY_STRING_ARRAY;
8908 } else {
8909 name = args[opti];
8910 opti++;
8911 newArgs = new String[args.length - opti];
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008912 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8913 args.length - opti);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008914 }
8915 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
8916 pw.println("No services match: " + name);
8917 pw.println("Use -h for help.");
8918 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008919 return;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008920 } else if ("package".equals(cmd)) {
8921 String[] newArgs;
8922 if (opti >= args.length) {
8923 pw.println("package: no package name specified");
8924 pw.println("Use -h for help.");
8925 return;
8926 } else {
8927 dumpPackage = args[opti];
8928 opti++;
8929 newArgs = new String[args.length - opti];
8930 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8931 args.length - opti);
8932 args = newArgs;
8933 opti = 0;
8934 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008935 } else if ("services".equals(cmd) || "s".equals(cmd)) {
8936 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008937 dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008938 }
8939 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07008940 } else {
8941 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008942 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
8943 pw.println("Bad activity command, or no activities match: " + cmd);
8944 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008945 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008946 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008948 }
8949
8950 // No piece of data specified, dump everything.
8951 synchronized (this) {
8952 boolean needSep;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008953 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008954 if (needSep) {
8955 pw.println(" ");
8956 }
8957 if (dumpAll) {
8958 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008959 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008960 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008961 if (needSep) {
8962 pw.println(" ");
8963 }
8964 if (dumpAll) {
8965 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008966 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008967 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008968 if (needSep) {
8969 pw.println(" ");
8970 }
8971 if (dumpAll) {
8972 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008973 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008974 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008975 if (needSep) {
8976 pw.println(" ");
8977 }
8978 if (dumpAll) {
8979 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008980 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008981 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008982 if (needSep) {
8983 pw.println(" ");
8984 }
8985 if (dumpAll) {
8986 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008987 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008988 dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008989 }
8990 }
8991
8992 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008993 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008994 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
8995 pw.println(" Main stack:");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008996 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient,
8997 dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008998 pw.println(" ");
8999 pw.println(" Running activities (most recent first):");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009000 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false,
9001 dumpPackage);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009002 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009003 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009004 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009005 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009006 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009007 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009008 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009009 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009010 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009011 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009012 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009013 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08009014 if (mMainStack.mGoingToSleepActivities.size() > 0) {
9015 pw.println(" ");
9016 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009017 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009018 !dumpAll, false, dumpPackage);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08009019 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009020 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009021 pw.println(" ");
9022 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009023 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009024 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009026
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009027 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009028 if (mMainStack.mPausingActivity != null) {
9029 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
9030 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009031 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009032 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009033 if (dumpAll) {
9034 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
9035 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009036 pw.println(" mDismissKeyguardOnNextActivity: "
9037 + mMainStack.mDismissKeyguardOnNextActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009039
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009040 if (mRecentTasks.size() > 0) {
9041 pw.println();
9042 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009043
9044 final int N = mRecentTasks.size();
9045 for (int i=0; i<N; i++) {
9046 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009047 if (dumpPackage != null) {
9048 if (tr.realActivity == null ||
9049 !dumpPackage.equals(tr.realActivity)) {
9050 continue;
9051 }
9052 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009053 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9054 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009055 if (dumpAll) {
9056 mRecentTasks.get(i).dump(pw, " ");
9057 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009058 }
9059 }
9060
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009061 if (dumpAll) {
9062 pw.println(" ");
9063 pw.println(" mCurTask: " + mCurTask);
9064 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009065
9066 return true;
9067 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009068
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009069 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009070 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009071 boolean needSep = false;
9072 int numPers = 0;
9073
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009074 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
9075
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009076 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9078 final int NA = procs.size();
9079 for (int ia=0; ia<NA; ia++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009080 ProcessRecord r = procs.valueAt(ia);
9081 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9082 continue;
9083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 if (!needSep) {
9085 pw.println(" All known processes:");
9086 needSep = true;
9087 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009088 pw.print(r.persistent ? " *PERS*" : " *APP*");
9089 pw.print(" UID "); pw.print(procs.keyAt(ia));
9090 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 r.dump(pw, " ");
9092 if (r.persistent) {
9093 numPers++;
9094 }
9095 }
9096 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009097 }
9098
9099 if (mLruProcesses.size() > 0) {
9100 if (needSep) pw.println(" ");
9101 needSep = true;
Dianne Hackborn905577f2011-09-07 18:31:28 -07009102 pw.println(" Process LRU list (sorted by oom_adj):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07009103 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009104 "Proc", "PERS", false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009105 needSep = true;
9106 }
9107
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009108 if (dumpAll) {
9109 synchronized (mPidsSelfLocked) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009110 boolean printed = false;
9111 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9112 ProcessRecord r = mPidsSelfLocked.valueAt(i);
9113 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9114 continue;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009115 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009116 if (!printed) {
9117 if (needSep) pw.println(" ");
9118 needSep = true;
9119 pw.println(" PID mappings:");
9120 printed = true;
9121 }
9122 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9123 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 }
9125 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009126 }
9127
9128 if (mForegroundProcesses.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009129 synchronized (mPidsSelfLocked) {
9130 boolean printed = false;
9131 for (int i=0; i<mForegroundProcesses.size(); i++) {
9132 ProcessRecord r = mPidsSelfLocked.get(
9133 mForegroundProcesses.valueAt(i).pid);
9134 if (dumpPackage != null && (r == null
9135 || !dumpPackage.equals(r.info.packageName))) {
9136 continue;
9137 }
9138 if (!printed) {
9139 if (needSep) pw.println(" ");
9140 needSep = true;
9141 pw.println(" Foreground Processes:");
9142 printed = true;
9143 }
9144 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9145 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
9146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009148 }
9149
9150 if (mPersistentStartingProcesses.size() > 0) {
9151 if (needSep) pw.println(" ");
9152 needSep = true;
9153 pw.println(" Persisent processes that are starting:");
9154 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009155 "Starting Norm", "Restarting PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009158 if (mRemovedProcesses.size() > 0) {
9159 if (needSep) pw.println(" ");
9160 needSep = true;
9161 pw.println(" Processes that are being removed:");
9162 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009163 "Removed Norm", "Removed PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009164 }
9165
9166 if (mProcessesOnHold.size() > 0) {
9167 if (needSep) pw.println(" ");
9168 needSep = true;
9169 pw.println(" Processes that are on old until the system is ready:");
9170 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009171 "OnHold Norm", "OnHold PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009174 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009175
9176 if (mProcessCrashTimes.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009177 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009178 long now = SystemClock.uptimeMillis();
9179 for (Map.Entry<String, SparseArray<Long>> procs
9180 : mProcessCrashTimes.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009181 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009182 SparseArray<Long> uids = procs.getValue();
9183 final int N = uids.size();
9184 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009185 int puid = uids.keyAt(i);
9186 ProcessRecord r = mProcessNames.get(pname, puid);
9187 if (dumpPackage != null && (r == null
9188 || !dumpPackage.equals(r.info.packageName))) {
9189 continue;
9190 }
9191 if (!printed) {
9192 if (needSep) pw.println(" ");
9193 needSep = true;
9194 pw.println(" Time since processes crashed:");
9195 printed = true;
9196 }
9197 pw.print(" Process "); pw.print(pname);
9198 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009199 pw.print(": last crashed ");
9200 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009201 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009202 }
9203 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009205
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009206 if (mBadProcesses.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009207 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009208 for (Map.Entry<String, SparseArray<Long>> procs
9209 : mBadProcesses.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009210 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009211 SparseArray<Long> uids = procs.getValue();
9212 final int N = uids.size();
9213 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009214 int puid = uids.keyAt(i);
9215 ProcessRecord r = mProcessNames.get(pname, puid);
9216 if (dumpPackage != null && (r == null
9217 || !dumpPackage.equals(r.info.packageName))) {
9218 continue;
9219 }
9220 if (!printed) {
9221 if (needSep) pw.println(" ");
9222 needSep = true;
9223 pw.println(" Bad processes:");
9224 }
9225 pw.print(" Bad process "); pw.print(pname);
9226 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009227 pw.print(": crashed at time ");
9228 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229 }
9230 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009232
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009233 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009234 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009235 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn50685602011-12-01 12:23:37 -08009236 if (dumpAll) {
9237 StringBuilder sb = new StringBuilder(128);
9238 sb.append(" mPreviousProcessVisibleTime: ");
9239 TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
9240 pw.println(sb);
9241 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07009242 if (mHeavyWeightProcess != null) {
9243 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
9244 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009245 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009246 if (dumpAll) {
9247 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07009248 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009249 boolean printed = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07009250 for (Map.Entry<String, Integer> entry
9251 : mCompatModePackages.getPackages().entrySet()) {
9252 String pkg = entry.getKey();
9253 int mode = entry.getValue();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009254 if (dumpPackage != null && !dumpPackage.equals(pkg)) {
9255 continue;
9256 }
9257 if (!printed) {
9258 pw.println(" mScreenCompatPackages:");
9259 printed = true;
9260 }
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07009261 pw.print(" "); pw.print(pkg); pw.print(": ");
9262 pw.print(mode); pw.println();
9263 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07009264 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009265 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009266 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9267 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9268 || mOrigWaitForDebugger) {
9269 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9270 + " mDebugTransient=" + mDebugTransient
9271 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9272 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07009273 if (mProfileApp != null || mProfileProc != null || mProfileFile != null
9274 || mProfileFd != null) {
9275 pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
9276 pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
9277 pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
9278 + mAutoStopProfiler);
9279 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009280 if (mAlwaysFinishActivities || mController != null) {
9281 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9282 + " mController=" + mController);
9283 }
9284 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009287 + " mProcessesReady=" + mProcessesReady
9288 + " mSystemReady=" + mSystemReady);
9289 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 + " mBooted=" + mBooted
9291 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009292 pw.print(" mLastPowerCheckRealtime=");
9293 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
9294 pw.println("");
9295 pw.print(" mLastPowerCheckUptime=");
9296 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
9297 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009298 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
9299 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07009300 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009301 pw.println(" mNumServiceProcs=" + mNumServiceProcs
9302 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009303 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009304
9305 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 }
9307
Dianne Hackborn287952c2010-09-22 22:34:31 -07009308 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009309 int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009310 if (mProcessesToGc.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009311 boolean printed = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009312 long now = SystemClock.uptimeMillis();
9313 for (int i=0; i<mProcessesToGc.size(); i++) {
9314 ProcessRecord proc = mProcessesToGc.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009315 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
9316 continue;
9317 }
9318 if (!printed) {
9319 if (needSep) pw.println(" ");
9320 needSep = true;
9321 pw.println(" Processes that are waiting to GC:");
9322 printed = true;
9323 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009324 pw.print(" Process "); pw.println(proc);
9325 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9326 pw.print(", last gced=");
9327 pw.print(now-proc.lastRequestedGc);
9328 pw.print(" ms ago, last lowMem=");
9329 pw.print(now-proc.lastLowMemory);
9330 pw.println(" ms ago");
9331
9332 }
9333 }
9334 return needSep;
9335 }
9336
9337 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9338 int opti, boolean dumpAll) {
9339 boolean needSep = false;
9340
9341 if (mLruProcesses.size() > 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009342 if (needSep) pw.println(" ");
9343 needSep = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009344 pw.println(" OOM levels:");
Dianne Hackborn7d608422011-08-07 16:24:18 -07009345 pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009346 pw.print(" PERSISTENT_PROC_ADJ: "); pw.println(ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009347 pw.print(" FOREGROUND_APP_ADJ: "); pw.println(ProcessList.FOREGROUND_APP_ADJ);
9348 pw.print(" VISIBLE_APP_ADJ: "); pw.println(ProcessList.VISIBLE_APP_ADJ);
9349 pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(ProcessList.PERCEPTIBLE_APP_ADJ);
9350 pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(ProcessList.HEAVY_WEIGHT_APP_ADJ);
9351 pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009352 pw.print(" SERVICE_ADJ: "); pw.println(ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009353 pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009354 pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009355 pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009356 pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009357 pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009358
9359 if (needSep) pw.println(" ");
9360 needSep = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009361 pw.println(" Process OOM control:");
Dianne Hackborn905577f2011-09-07 18:31:28 -07009362 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009363 "Proc", "PERS", true, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009364 needSep = true;
9365 }
9366
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009367 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009368
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009369 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07009370 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009371 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009372 if (mHeavyWeightProcess != null) {
9373 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
9374 }
9375
9376 return true;
9377 }
9378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 /**
9380 * There are three ways to call this:
9381 * - no service specified: dump all the services
9382 * - a flattened component name that matched an existing service was specified as the
9383 * first arg: dump that one service
9384 * - the first arg isn't the flattened component name of an existing service:
9385 * dump all services whose component contains the first arg as a substring
9386 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009387 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
9388 int opti, boolean dumpAll) {
9389 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009390
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009391 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07009392 synchronized (this) {
Amith Yamasani742a6712011-05-04 14:49:28 -07009393 try {
9394 List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
9395 for (UserInfo user : users) {
9396 for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
9397 services.add(r1);
9398 }
9399 }
9400 } catch (RemoteException re) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009401 }
9402 }
9403 } else {
9404 ComponentName componentName = name != null
9405 ? ComponentName.unflattenFromString(name) : null;
9406 int objectId = 0;
9407 if (componentName == null) {
9408 // Not a '/' separated full component name; maybe an object ID?
9409 try {
9410 objectId = Integer.parseInt(name, 16);
9411 name = null;
9412 componentName = null;
9413 } catch (RuntimeException e) {
9414 }
9415 }
9416
9417 synchronized (this) {
Amith Yamasani742a6712011-05-04 14:49:28 -07009418 try {
9419 List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
9420 for (UserInfo user : users) {
9421 for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
9422 if (componentName != null) {
9423 if (r1.name.equals(componentName)) {
9424 services.add(r1);
9425 }
9426 } else if (name != null) {
9427 if (r1.name.flattenToString().contains(name)) {
9428 services.add(r1);
9429 }
9430 } else if (System.identityHashCode(r1) == objectId) {
9431 services.add(r1);
9432 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009433 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07009434 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009435 } catch (RemoteException re) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 }
9437 }
9438 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009439
9440 if (services.size() <= 0) {
9441 return false;
9442 }
9443
9444 boolean needSep = false;
9445 for (int i=0; i<services.size(); i++) {
9446 if (needSep) {
9447 pw.println();
9448 }
9449 needSep = true;
9450 dumpService("", fd, pw, services.get(i), args, dumpAll);
9451 }
9452 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 }
9454
9455 /**
9456 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9457 * there is a thread associated with the service.
9458 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009459 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
9460 final ServiceRecord r, String[] args, boolean dumpAll) {
9461 String innerPrefix = prefix + " ";
9462 synchronized (this) {
9463 pw.print(prefix); pw.print("SERVICE ");
9464 pw.print(r.shortName); pw.print(" ");
9465 pw.print(Integer.toHexString(System.identityHashCode(r)));
9466 pw.print(" pid=");
9467 if (r.app != null) pw.println(r.app.pid);
9468 else pw.println("(not running)");
9469 if (dumpAll) {
9470 r.dump(pw, innerPrefix);
9471 }
9472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009474 pw.print(prefix); pw.println(" Client:");
9475 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009477 TransferPipe tp = new TransferPipe();
9478 try {
9479 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
9480 tp.setBufferPrefix(prefix + " ");
9481 tp.go(fd);
9482 } finally {
9483 tp.kill();
9484 }
9485 } catch (IOException e) {
9486 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009487 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009488 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 }
9490 }
9491 }
9492
Marco Nelissen18cb2872011-11-15 11:19:53 -08009493 /**
9494 * There are three ways to call this:
9495 * - no provider specified: dump all the providers
9496 * - a flattened component name that matched an existing provider was specified as the
9497 * first arg: dump that one provider
9498 * - the first arg isn't the flattened component name of an existing provider:
9499 * dump all providers whose component contains the first arg as a substring
9500 */
9501 protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
9502 int opti, boolean dumpAll) {
9503 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
9504
9505 if ("all".equals(name)) {
9506 synchronized (this) {
9507 for (ContentProviderRecord r1 : mProvidersByClass.values()) {
9508 providers.add(r1);
9509 }
9510 }
9511 } else {
9512 ComponentName componentName = name != null
9513 ? ComponentName.unflattenFromString(name) : null;
9514 int objectId = 0;
9515 if (componentName == null) {
9516 // Not a '/' separated full component name; maybe an object ID?
9517 try {
9518 objectId = Integer.parseInt(name, 16);
9519 name = null;
9520 componentName = null;
9521 } catch (RuntimeException e) {
9522 }
9523 }
9524
9525 synchronized (this) {
9526 for (ContentProviderRecord r1 : mProvidersByClass.values()) {
9527 if (componentName != null) {
9528 if (r1.name.equals(componentName)) {
9529 providers.add(r1);
9530 }
9531 } else if (name != null) {
9532 if (r1.name.flattenToString().contains(name)) {
9533 providers.add(r1);
9534 }
9535 } else if (System.identityHashCode(r1) == objectId) {
9536 providers.add(r1);
9537 }
9538 }
9539 }
9540 }
9541
9542 if (providers.size() <= 0) {
9543 return false;
9544 }
9545
9546 boolean needSep = false;
9547 for (int i=0; i<providers.size(); i++) {
9548 if (needSep) {
9549 pw.println();
9550 }
9551 needSep = true;
9552 dumpProvider("", fd, pw, providers.get(i), args, dumpAll);
9553 }
9554 return true;
9555 }
9556
9557 /**
9558 * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider if
9559 * there is a thread associated with the provider.
9560 */
9561 private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
9562 final ContentProviderRecord r, String[] args, boolean dumpAll) {
9563 String innerPrefix = prefix + " ";
9564 synchronized (this) {
9565 pw.print(prefix); pw.print("PROVIDER ");
9566 pw.print(r);
9567 pw.print(" pid=");
9568 if (r.proc != null) pw.println(r.proc.pid);
9569 else pw.println("(not running)");
9570 if (dumpAll) {
9571 r.dump(pw, innerPrefix);
9572 }
9573 }
9574 if (r.proc != null && r.proc.thread != null) {
9575 pw.println(" Client:");
9576 pw.flush();
9577 try {
9578 TransferPipe tp = new TransferPipe();
9579 try {
9580 r.proc.thread.dumpProvider(
9581 tp.getWriteFd().getFileDescriptor(), r.provider.asBinder(), args);
9582 tp.setBufferPrefix(" ");
9583 // Short timeout, since blocking here can
9584 // deadlock with the application.
9585 tp.go(fd, 2000);
9586 } finally {
9587 tp.kill();
9588 }
9589 } catch (IOException ex) {
9590 pw.println(" Failure while dumping the provider: " + ex);
9591 } catch (RemoteException ex) {
9592 pw.println(" Got a RemoteException while dumping the service");
9593 }
9594 }
9595 }
9596
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009597 static class ItemMatcher {
9598 ArrayList<ComponentName> components;
9599 ArrayList<String> strings;
9600 ArrayList<Integer> objects;
9601 boolean all;
9602
9603 ItemMatcher() {
9604 all = true;
9605 }
9606
9607 void build(String name) {
9608 ComponentName componentName = ComponentName.unflattenFromString(name);
9609 if (componentName != null) {
9610 if (components == null) {
9611 components = new ArrayList<ComponentName>();
9612 }
9613 components.add(componentName);
9614 all = false;
9615 } else {
9616 int objectId = 0;
9617 // Not a '/' separated full component name; maybe an object ID?
9618 try {
9619 objectId = Integer.parseInt(name, 16);
9620 if (objects == null) {
9621 objects = new ArrayList<Integer>();
9622 }
9623 objects.add(objectId);
9624 all = false;
9625 } catch (RuntimeException e) {
9626 // Not an integer; just do string match.
9627 if (strings == null) {
9628 strings = new ArrayList<String>();
9629 }
9630 strings.add(name);
9631 all = false;
9632 }
9633 }
9634 }
9635
9636 int build(String[] args, int opti) {
9637 for (; opti<args.length; opti++) {
9638 String name = args[opti];
9639 if ("--".equals(name)) {
9640 return opti+1;
9641 }
9642 build(name);
9643 }
9644 return opti;
9645 }
9646
9647 boolean match(Object object, ComponentName comp) {
9648 if (all) {
9649 return true;
9650 }
9651 if (components != null) {
9652 for (int i=0; i<components.size(); i++) {
9653 if (components.get(i).equals(comp)) {
9654 return true;
9655 }
9656 }
9657 }
9658 if (objects != null) {
9659 for (int i=0; i<objects.size(); i++) {
9660 if (System.identityHashCode(object) == objects.get(i)) {
9661 return true;
9662 }
9663 }
9664 }
9665 if (strings != null) {
9666 String flat = comp.flattenToString();
9667 for (int i=0; i<strings.size(); i++) {
9668 if (flat.contains(strings.get(i))) {
9669 return true;
9670 }
9671 }
9672 }
9673 return false;
9674 }
9675 }
9676
Dianne Hackborn625ac272010-09-17 18:29:22 -07009677 /**
9678 * There are three things that cmd can be:
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009679 * - a flattened component name that matches an existing activity
Dianne Hackborn625ac272010-09-17 18:29:22 -07009680 * - the cmd arg isn't the flattened component name of an existing activity:
9681 * dump all activity whose component contains the cmd as a substring
9682 * - A hex number of the ActivityRecord object instance.
9683 */
9684 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
9685 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07009686 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009687
9688 if ("all".equals(name)) {
9689 synchronized (this) {
9690 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07009691 activities.add(r1);
9692 }
9693 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07009694 } else if ("top".equals(name)) {
9695 synchronized (this) {
9696 final int N = mMainStack.mHistory.size();
9697 if (N > 0) {
9698 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
9699 }
9700 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009701 } else {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009702 ItemMatcher matcher = new ItemMatcher();
9703 matcher.build(name);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009704
9705 synchronized (this) {
9706 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009707 if (matcher.match(r1, r1.intent.getComponent())) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009708 activities.add(r1);
9709 }
9710 }
9711 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07009712 }
9713
9714 if (activities.size() <= 0) {
9715 return false;
9716 }
9717
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009718 String[] newArgs = new String[args.length - opti];
9719 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
9720
Dianne Hackborn30d71892010-12-11 10:37:55 -08009721 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009722 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08009723 for (int i=activities.size()-1; i>=0; i--) {
9724 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009725 if (needSep) {
9726 pw.println();
9727 }
9728 needSep = true;
9729 synchronized (this) {
9730 if (lastTask != r.task) {
9731 lastTask = r.task;
9732 pw.print("TASK "); pw.print(lastTask.affinity);
9733 pw.print(" id="); pw.println(lastTask.taskId);
9734 if (dumpAll) {
9735 lastTask.dump(pw, " ");
9736 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08009737 }
9738 }
9739 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07009740 }
9741 return true;
9742 }
9743
9744 /**
9745 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
9746 * there is a thread associated with the activity.
9747 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08009748 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009749 final ActivityRecord r, String[] args, boolean dumpAll) {
9750 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08009751 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009752 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
9753 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
9754 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08009755 if (r.app != null) pw.println(r.app.pid);
9756 else pw.println("(not running)");
9757 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009758 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07009759 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07009760 }
9761 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009762 // flush anything that is already in the PrintWriter since the thread is going
9763 // to write to the file descriptor directly
9764 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07009765 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009766 TransferPipe tp = new TransferPipe();
9767 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08009768 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
9769 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009770 tp.go(fd);
9771 } finally {
9772 tp.kill();
9773 }
9774 } catch (IOException e) {
9775 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07009776 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009777 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07009778 }
9779 }
9780 }
9781
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009782 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009783 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009784 boolean needSep = false;
9785
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009786 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009787 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 if (mRegisteredReceivers.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009789 boolean printed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790 Iterator it = mRegisteredReceivers.values().iterator();
9791 while (it.hasNext()) {
9792 ReceiverList r = (ReceiverList)it.next();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009793 if (dumpPackage != null && (r.app == null ||
9794 !dumpPackage.equals(r.app.info.packageName))) {
9795 continue;
9796 }
9797 if (!printed) {
9798 pw.println(" Registered Receivers:");
9799 needSep = true;
9800 printed = true;
9801 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009802 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009803 r.dump(pw, " ");
9804 }
9805 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009806
9807 if (mReceiverResolver.dump(pw, needSep ?
9808 "\n Receiver Resolver Table:" : " Receiver Resolver Table:",
9809 " ", dumpPackage, false)) {
9810 needSep = true;
9811 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009812 }
Christopher Tatef46723b2012-01-26 14:19:24 -08009813
9814 for (BroadcastQueue q : mBroadcastQueues) {
9815 needSep = q.dumpLocked(fd, pw, args, opti, dumpAll, dumpPackage, needSep);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009818 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009819
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009820 if (mStickyBroadcasts != null && dumpPackage == null) {
9821 if (needSep) {
9822 pw.println();
9823 }
9824 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009825 pw.println(" Sticky broadcasts:");
9826 StringBuilder sb = new StringBuilder(128);
9827 for (Map.Entry<String, ArrayList<Intent>> ent
9828 : mStickyBroadcasts.entrySet()) {
9829 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009830 if (dumpAll) {
9831 pw.println(":");
9832 ArrayList<Intent> intents = ent.getValue();
9833 final int N = intents.size();
9834 for (int i=0; i<N; i++) {
9835 sb.setLength(0);
9836 sb.append(" Intent: ");
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009837 intents.get(i).toShortString(sb, false, true, false);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009838 pw.println(sb.toString());
9839 Bundle bundle = intents.get(i).getExtras();
9840 if (bundle != null) {
9841 pw.print(" ");
9842 pw.println(bundle.toString());
9843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009845 } else {
9846 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 }
9848 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009849 needSep = true;
9850 }
9851
9852 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009853 pw.println();
Christopher Tatef46723b2012-01-26 14:19:24 -08009854 for (BroadcastQueue queue : mBroadcastQueues) {
9855 pw.println(" mBroadcastsScheduled [" + queue.mQueueName + "]="
9856 + queue.mBroadcastsScheduled);
9857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009858 pw.println(" mHandler:");
9859 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009860 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009861 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009862
9863 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 }
9865
Marco Nelissen18cb2872011-11-15 11:19:53 -08009866 /**
9867 * Prints a list of ServiceRecords (dumpsys activity services)
9868 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009869 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009870 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009871 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009873 ItemMatcher matcher = new ItemMatcher();
9874 matcher.build(args, opti);
9875
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009876 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
Amith Yamasani742a6712011-05-04 14:49:28 -07009877 try {
9878 List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
9879 for (UserInfo user : users) {
9880 if (mServiceMap.getAllServices(user.id).size() > 0) {
9881 boolean printed = false;
9882 long nowReal = SystemClock.elapsedRealtime();
9883 Iterator<ServiceRecord> it = mServiceMap.getAllServices(
9884 user.id).iterator();
9885 needSep = false;
9886 while (it.hasNext()) {
9887 ServiceRecord r = it.next();
9888 if (!matcher.match(r, r.name)) {
9889 continue;
9890 }
9891 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9892 continue;
9893 }
9894 if (!printed) {
9895 pw.println(" Active services:");
9896 printed = true;
9897 }
9898 if (needSep) {
9899 pw.println();
9900 }
9901 pw.print(" * ");
9902 pw.println(r);
9903 if (dumpAll) {
9904 r.dump(pw, " ");
9905 needSep = true;
9906 } else {
9907 pw.print(" app=");
9908 pw.println(r.app);
9909 pw.print(" created=");
9910 TimeUtils.formatDuration(r.createTime, nowReal, pw);
9911 pw.print(" started=");
9912 pw.print(r.startRequested);
9913 pw.print(" connections=");
9914 pw.println(r.connections.size());
9915 if (r.connections.size() > 0) {
9916 pw.println(" Connections:");
9917 for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
9918 for (int i = 0; i < clist.size(); i++) {
9919 ConnectionRecord conn = clist.get(i);
9920 pw.print(" ");
9921 pw.print(conn.binding.intent.intent.getIntent()
9922 .toShortString(false, false, false));
9923 pw.print(" -> ");
9924 ProcessRecord proc = conn.binding.client;
9925 pw.println(proc != null ? proc.toShortString() : "null");
9926 }
9927 }
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009928 }
9929 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009930 if (dumpClient && r.app != null && r.app.thread != null) {
9931 pw.println(" Client:");
9932 pw.flush();
9933 try {
9934 TransferPipe tp = new TransferPipe();
9935 try {
9936 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
9937 r, args);
9938 tp.setBufferPrefix(" ");
9939 // Short timeout, since blocking here can
9940 // deadlock with the application.
9941 tp.go(fd, 2000);
9942 } finally {
9943 tp.kill();
9944 }
9945 } catch (IOException e) {
9946 pw.println(" Failure while dumping the service: " + e);
9947 } catch (RemoteException e) {
9948 pw.println(" Got a RemoteException while dumping the service");
9949 }
9950 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009951 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009952 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009953 needSep = printed;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009955 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009956 } catch (RemoteException re) {
9957
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009959
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009960 if (mPendingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009961 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009962 for (int i=0; i<mPendingServices.size(); i++) {
9963 ServiceRecord r = mPendingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009964 if (!matcher.match(r, r.name)) {
9965 continue;
9966 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009967 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9968 continue;
9969 }
9970 if (!printed) {
9971 if (needSep) pw.println(" ");
9972 needSep = true;
9973 pw.println(" Pending services:");
9974 printed = true;
9975 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009976 pw.print(" * Pending "); pw.println(r);
9977 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009978 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009979 needSep = true;
9980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009982 if (mRestartingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009983 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009984 for (int i=0; i<mRestartingServices.size(); i++) {
9985 ServiceRecord r = mRestartingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009986 if (!matcher.match(r, r.name)) {
9987 continue;
9988 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009989 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9990 continue;
9991 }
9992 if (!printed) {
9993 if (needSep) pw.println(" ");
9994 needSep = true;
9995 pw.println(" Restarting services:");
9996 printed = true;
9997 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009998 pw.print(" * Restarting "); pw.println(r);
9999 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010001 needSep = true;
10002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010003
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010004 if (mStoppingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010005 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010006 for (int i=0; i<mStoppingServices.size(); i++) {
10007 ServiceRecord r = mStoppingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -070010008 if (!matcher.match(r, r.name)) {
10009 continue;
10010 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010011 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
10012 continue;
10013 }
10014 if (!printed) {
10015 if (needSep) pw.println(" ");
10016 needSep = true;
10017 pw.println(" Stopping services:");
10018 printed = true;
10019 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010020 pw.print(" * Stopping "); pw.println(r);
10021 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010023 needSep = true;
10024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010026 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027 if (mServiceConnections.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010028 boolean printed = false;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010029 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 = mServiceConnections.values().iterator();
10031 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010032 ArrayList<ConnectionRecord> r = it.next();
10033 for (int i=0; i<r.size(); i++) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -070010034 ConnectionRecord cr = r.get(i);
10035 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
10036 continue;
10037 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010038 if (dumpPackage != null && (cr.binding.client == null
10039 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
10040 continue;
10041 }
10042 if (!printed) {
10043 if (needSep) pw.println(" ");
10044 needSep = true;
10045 pw.println(" Connection bindings to services:");
10046 printed = true;
10047 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -070010048 pw.print(" * "); pw.println(cr);
10049 cr.dump(pw, " ");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010052 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 }
10054 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010055
10056 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010057 }
10058
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010059 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010060 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010061 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062
Dianne Hackborn1c9b2602011-08-19 14:08:43 -070010063 ItemMatcher matcher = new ItemMatcher();
10064 matcher.build(args, opti);
10065
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010066 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
Amith Yamasani742a6712011-05-04 14:49:28 -070010067
10068 mProviderMap.dumpProvidersLocked(pw, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010069
10070 if (mLaunchingProviders.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010071 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010072 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010073 ContentProviderRecord r = mLaunchingProviders.get(i);
10074 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
10075 continue;
10076 }
10077 if (!printed) {
10078 if (needSep) pw.println(" ");
10079 needSep = true;
10080 pw.println(" Launching content providers:");
10081 printed = true;
10082 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010083 pw.print(" Launching #"); pw.print(i); pw.print(": ");
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010084 pw.println(r);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010085 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010086 }
10087
10088 if (mGrantedUriPermissions.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010089 if (needSep) pw.println();
10090 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010091 pw.println("Granted Uri Permissions:");
10092 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10093 int uid = mGrantedUriPermissions.keyAt(i);
10094 HashMap<Uri, UriPermission> perms
10095 = mGrantedUriPermissions.valueAt(i);
10096 pw.print(" * UID "); pw.print(uid);
10097 pw.println(" holds:");
10098 for (UriPermission perm : perms.values()) {
10099 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010100 if (dumpAll) {
10101 perm.dump(pw, " ");
10102 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010103 }
10104 }
10105 needSep = true;
10106 }
10107
10108 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 }
10110
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010111 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010112 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010113 boolean needSep = false;
10114
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010115 if (mIntentSenderRecords.size() > 0) {
10116 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010117 Iterator<WeakReference<PendingIntentRecord>> it
10118 = mIntentSenderRecords.values().iterator();
10119 while (it.hasNext()) {
10120 WeakReference<PendingIntentRecord> ref = it.next();
10121 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010122 if (dumpPackage != null && (rec == null
10123 || !dumpPackage.equals(rec.key.packageName))) {
10124 continue;
10125 }
10126 if (!printed) {
10127 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
10128 printed = true;
10129 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010130 needSep = true;
10131 if (rec != null) {
10132 pw.print(" * "); pw.println(rec);
10133 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010134 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010136 } else {
10137 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138 }
10139 }
10140 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010141
10142 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 }
10144
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010145 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010146 String prefix, String label, boolean complete, boolean brief, boolean client,
10147 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010149 boolean needNL = false;
10150 final String innerPrefix = prefix + " ";
10151 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010153 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010154 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
10155 continue;
10156 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -070010157 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010158 if (needNL) {
10159 pw.println(" ");
10160 needNL = false;
10161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010162 if (lastTask != r.task) {
10163 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010164 pw.print(prefix);
10165 pw.print(full ? "* " : " ");
10166 pw.println(lastTask);
10167 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010168 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010169 } else if (complete) {
10170 // Complete + brief == give a summary. Isn't that obvious?!?
10171 if (lastTask.intent != null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010172 pw.print(prefix); pw.print(" ");
10173 pw.println(lastTask.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010174 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010177 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10178 pw.print(" #"); pw.print(i); pw.print(": ");
10179 pw.println(r);
10180 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010181 r.dump(pw, innerPrefix);
10182 } else if (complete) {
10183 // Complete + brief == give a summary. Isn't that obvious?!?
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010184 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010185 if (r.app != null) {
10186 pw.print(innerPrefix); pw.println(r.app);
10187 }
10188 }
10189 if (client && r.app != null && r.app.thread != null) {
10190 // flush anything that is already in the PrintWriter since the thread is going
10191 // to write to the file descriptor directly
10192 pw.flush();
10193 try {
10194 TransferPipe tp = new TransferPipe();
10195 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -080010196 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
10197 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010198 // Short timeout, since blocking here can
10199 // deadlock with the application.
10200 tp.go(fd, 2000);
10201 } finally {
10202 tp.kill();
10203 }
10204 } catch (IOException e) {
10205 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
10206 } catch (RemoteException e) {
10207 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
10208 }
10209 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 }
10212 }
10213
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010214 private static String buildOomTag(String prefix, String space, int val, int base) {
10215 if (val == base) {
10216 if (space == null) return prefix;
10217 return prefix + " ";
10218 }
10219 return prefix + "+" + Integer.toString(val-base);
10220 }
10221
10222 private static final int dumpProcessList(PrintWriter pw,
10223 ActivityManagerService service, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010224 String prefix, String normalLabel, String persistentLabel,
10225 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010227 final int N = list.size()-1;
10228 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010230 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
10231 continue;
10232 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070010233 pw.println(String.format("%s%s #%2d: %s",
10234 prefix, (r.persistent ? persistentLabel : normalLabel),
10235 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 if (r.persistent) {
10237 numPers++;
10238 }
10239 }
10240 return numPers;
10241 }
10242
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010243 private static final boolean dumpProcessOomList(PrintWriter pw,
Dianne Hackborn905577f2011-09-07 18:31:28 -070010244 ActivityManagerService service, List<ProcessRecord> origList,
Dianne Hackborn287952c2010-09-22 22:34:31 -070010245 String prefix, String normalLabel, String persistentLabel,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010246 boolean inclDetails, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010247
Dianne Hackborn905577f2011-09-07 18:31:28 -070010248 ArrayList<Pair<ProcessRecord, Integer>> list
10249 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
10250 for (int i=0; i<origList.size(); i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010251 ProcessRecord r = origList.get(i);
10252 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
10253 continue;
10254 }
Dianne Hackborn905577f2011-09-07 18:31:28 -070010255 list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
10256 }
10257
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010258 if (list.size() <= 0) {
10259 return false;
10260 }
10261
Dianne Hackborn905577f2011-09-07 18:31:28 -070010262 Comparator<Pair<ProcessRecord, Integer>> comparator
10263 = new Comparator<Pair<ProcessRecord, Integer>>() {
10264 @Override
10265 public int compare(Pair<ProcessRecord, Integer> object1,
10266 Pair<ProcessRecord, Integer> object2) {
10267 if (object1.first.setAdj != object2.first.setAdj) {
10268 return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
10269 }
10270 if (object1.second.intValue() != object2.second.intValue()) {
10271 return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
10272 }
10273 return 0;
10274 }
10275 };
10276
10277 Collections.sort(list, comparator);
10278
Dianne Hackborn287952c2010-09-22 22:34:31 -070010279 final long curRealtime = SystemClock.elapsedRealtime();
10280 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
10281 final long curUptime = SystemClock.uptimeMillis();
10282 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
10283
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010284 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070010285 ProcessRecord r = list.get(i).first;
Dianne Hackborn287952c2010-09-22 22:34:31 -070010286 String oomAdj;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010287 if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070010288 oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010289 } else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
10290 oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -070010291 } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
10292 oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010293 } else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
10294 oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010295 } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
10296 oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010297 } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010298 oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010299 } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
10300 oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
10301 } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
10302 oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
10303 } else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
10304 oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
10305 } else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
10306 oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010307 } else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
10308 oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010309 } else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
10310 oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010311 } else {
10312 oomAdj = Integer.toString(r.setAdj);
10313 }
10314 String schedGroup;
10315 switch (r.setSchedGroup) {
10316 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10317 schedGroup = "B";
10318 break;
10319 case Process.THREAD_GROUP_DEFAULT:
10320 schedGroup = "F";
10321 break;
10322 default:
10323 schedGroup = Integer.toString(r.setSchedGroup);
10324 break;
10325 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010326 String foreground;
10327 if (r.foregroundActivities) {
10328 foreground = "A";
10329 } else if (r.foregroundServices) {
10330 foreground = "S";
10331 } else {
10332 foreground = " ";
10333 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010334 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -070010335 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010336 (origList.size()-1)-list.get(i).second, oomAdj, schedGroup,
10337 foreground, r.trimMemoryLevel, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -070010338 if (r.adjSource != null || r.adjTarget != null) {
10339 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010340 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070010341 if (r.adjTarget instanceof ComponentName) {
10342 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10343 } else if (r.adjTarget != null) {
10344 pw.print(r.adjTarget.toString());
10345 } else {
10346 pw.print("{null}");
10347 }
10348 pw.print("<=");
10349 if (r.adjSource instanceof ProcessRecord) {
10350 pw.print("Proc{");
10351 pw.print(((ProcessRecord)r.adjSource).toShortString());
10352 pw.println("}");
10353 } else if (r.adjSource != null) {
10354 pw.println(r.adjSource.toString());
10355 } else {
10356 pw.println("{null}");
10357 }
10358 }
10359 if (inclDetails) {
10360 pw.print(prefix);
10361 pw.print(" ");
10362 pw.print("oom: max="); pw.print(r.maxAdj);
10363 pw.print(" hidden="); pw.print(r.hiddenAdj);
10364 pw.print(" curRaw="); pw.print(r.curRawAdj);
10365 pw.print(" setRaw="); pw.print(r.setRawAdj);
10366 pw.print(" cur="); pw.print(r.curAdj);
10367 pw.print(" set="); pw.println(r.setAdj);
10368 pw.print(prefix);
10369 pw.print(" ");
10370 pw.print("keeping="); pw.print(r.keeping);
10371 pw.print(" hidden="); pw.print(r.hidden);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010372 pw.print(" empty="); pw.print(r.empty);
10373 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010374
10375 if (!r.keeping) {
10376 if (r.lastWakeTime != 0) {
10377 long wtime;
10378 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
10379 synchronized (stats) {
10380 wtime = stats.getProcessWakeTime(r.info.uid,
10381 r.pid, curRealtime);
10382 }
10383 long timeUsed = wtime - r.lastWakeTime;
10384 pw.print(prefix);
10385 pw.print(" ");
10386 pw.print("keep awake over ");
10387 TimeUtils.formatDuration(realtimeSince, pw);
10388 pw.print(" used ");
10389 TimeUtils.formatDuration(timeUsed, pw);
10390 pw.print(" (");
10391 pw.print((timeUsed*100)/realtimeSince);
10392 pw.println("%)");
10393 }
10394 if (r.lastCpuTime != 0) {
10395 long timeUsed = r.curCpuTime - r.lastCpuTime;
10396 pw.print(prefix);
10397 pw.print(" ");
10398 pw.print("run cpu over ");
10399 TimeUtils.formatDuration(uptimeSince, pw);
10400 pw.print(" used ");
10401 TimeUtils.formatDuration(timeUsed, pw);
10402 pw.print(" (");
10403 pw.print((timeUsed*100)/uptimeSince);
10404 pw.println("%)");
10405 }
10406 }
10407 }
10408 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010409 return true;
Dianne Hackborn287952c2010-09-22 22:34:31 -070010410 }
10411
Dianne Hackbornb437e092011-08-05 17:50:29 -070010412 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010413 ArrayList<ProcessRecord> procs;
10414 synchronized (this) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010415 if (args != null && args.length > start
10416 && args[start].charAt(0) != '-') {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010417 procs = new ArrayList<ProcessRecord>();
10418 int pid = -1;
10419 try {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010420 pid = Integer.parseInt(args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010421 } catch (NumberFormatException e) {
10422
10423 }
10424 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10425 ProcessRecord proc = mLruProcesses.get(i);
10426 if (proc.pid == pid) {
10427 procs.add(proc);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010428 } else if (proc.processName.equals(args[start])) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010429 procs.add(proc);
10430 }
10431 }
10432 if (procs.size() <= 0) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010433 pw.println("No process found for: " + args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010434 return null;
10435 }
10436 } else {
10437 procs = new ArrayList<ProcessRecord>(mLruProcesses);
10438 }
10439 }
10440 return procs;
10441 }
10442
10443 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
10444 PrintWriter pw, String[] args) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010445 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010446 if (procs == null) {
10447 return;
10448 }
10449
10450 long uptime = SystemClock.uptimeMillis();
10451 long realtime = SystemClock.elapsedRealtime();
10452 pw.println("Applications Graphics Acceleration Info:");
10453 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10454
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010455 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
10456 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -070010457 if (r.thread != null) {
10458 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
10459 pw.flush();
10460 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010461 TransferPipe tp = new TransferPipe();
10462 try {
10463 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
10464 tp.go(fd);
10465 } finally {
10466 tp.kill();
10467 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010468 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010469 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010470 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -070010471 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010472 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -070010473 pw.flush();
10474 }
10475 }
10476 }
Chet Haase9c1e23b2011-03-24 10:51:31 -070010477 }
10478
Jeff Brown6754ba22011-12-14 20:20:01 -080010479 final void dumpDbInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
10480 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
10481 if (procs == null) {
10482 return;
10483 }
10484
10485 pw.println("Applications Database Info:");
10486
10487 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
10488 ProcessRecord r = procs.get(i);
10489 if (r.thread != null) {
10490 pw.println("\n** Database info for pid " + r.pid + " [" + r.processName + "] **");
10491 pw.flush();
10492 try {
10493 TransferPipe tp = new TransferPipe();
10494 try {
10495 r.thread.dumpDbInfo(tp.getWriteFd().getFileDescriptor(), args);
10496 tp.go(fd);
10497 } finally {
10498 tp.kill();
10499 }
10500 } catch (IOException e) {
10501 pw.println("Failure while dumping the app: " + r);
10502 pw.flush();
10503 } catch (RemoteException e) {
10504 pw.println("Got a RemoteException while dumping the app " + r);
10505 pw.flush();
10506 }
10507 }
10508 }
10509 }
10510
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010511 final static class MemItem {
10512 final String label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010513 final String shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010514 final long pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010515 final int id;
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010516 ArrayList<MemItem> subitems;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010517
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010518 public MemItem(String _label, String _shortLabel, long _pss, int _id) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010519 label = _label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010520 shortLabel = _shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010521 pss = _pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010522 id = _id;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010523 }
10524 }
10525
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010526 static final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
Dianne Hackbornb437e092011-08-05 17:50:29 -070010527 boolean sort) {
10528 if (sort) {
10529 Collections.sort(items, new Comparator<MemItem>() {
10530 @Override
10531 public int compare(MemItem lhs, MemItem rhs) {
10532 if (lhs.pss < rhs.pss) {
10533 return 1;
10534 } else if (lhs.pss > rhs.pss) {
10535 return -1;
10536 }
10537 return 0;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010538 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010539 });
10540 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010541
10542 for (int i=0; i<items.size(); i++) {
10543 MemItem mi = items.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010544 pw.print(prefix); pw.printf("%7d kB: ", mi.pss); pw.println(mi.label);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010545 if (mi.subitems != null) {
10546 dumpMemItems(pw, prefix + " ", mi.subitems, true);
10547 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010548 }
10549 }
10550
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010551 // These are in KB.
10552 static final long[] DUMP_MEM_BUCKETS = new long[] {
10553 5*1024, 7*1024, 10*1024, 15*1024, 20*1024, 30*1024, 40*1024, 80*1024,
10554 120*1024, 160*1024, 200*1024,
10555 250*1024, 300*1024, 350*1024, 400*1024, 500*1024, 600*1024, 800*1024,
10556 1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
10557 };
10558
Dianne Hackborn672342c2011-11-29 11:29:02 -080010559 static final void appendMemBucket(StringBuilder out, long memKB, String label,
10560 boolean stackLike) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010561 int start = label.lastIndexOf('.');
10562 if (start >= 0) start++;
10563 else start = 0;
10564 int end = label.length();
10565 for (int i=0; i<DUMP_MEM_BUCKETS.length; i++) {
10566 if (DUMP_MEM_BUCKETS[i] >= memKB) {
10567 long bucket = DUMP_MEM_BUCKETS[i]/1024;
10568 out.append(bucket);
Dianne Hackborn672342c2011-11-29 11:29:02 -080010569 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010570 out.append(label, start, end);
10571 return;
10572 }
10573 }
10574 out.append(memKB/1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -080010575 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010576 out.append(label, start, end);
10577 }
10578
10579 static final int[] DUMP_MEM_OOM_ADJ = new int[] {
10580 ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
10581 ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
10582 ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
10583 ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
10584 };
10585 static final String[] DUMP_MEM_OOM_LABEL = new String[] {
10586 "System", "Persistent", "Foreground",
10587 "Visible", "Perceptible", "Heavy Weight",
10588 "Backup", "A Services", "Home", "Previous",
10589 "B Services", "Background"
10590 };
10591
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010592 final void dumpApplicationMemoryUsage(FileDescriptor fd,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010593 PrintWriter pw, String prefix, String[] args, boolean brief,
Dianne Hackborn672342c2011-11-29 11:29:02 -080010594 PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010595 boolean dumpAll = false;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010596 boolean oomOnly = false;
Dianne Hackbornb437e092011-08-05 17:50:29 -070010597
10598 int opti = 0;
10599 while (opti < args.length) {
10600 String opt = args[opti];
10601 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10602 break;
10603 }
10604 opti++;
10605 if ("-a".equals(opt)) {
10606 dumpAll = true;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010607 } else if ("--oom".equals(opt)) {
10608 oomOnly = true;
Dianne Hackbornb437e092011-08-05 17:50:29 -070010609 } else if ("-h".equals(opt)) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010610 pw.println("meminfo dump options: [-a] [--oom] [process]");
Dianne Hackbornb437e092011-08-05 17:50:29 -070010611 pw.println(" -a: include all available information for each process.");
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010612 pw.println(" --oom: only show processes organized by oom adj.");
Dianne Hackbornb437e092011-08-05 17:50:29 -070010613 pw.println("If [process] is specified it can be the name or ");
10614 pw.println("pid of a specific process to dump.");
10615 return;
10616 } else {
10617 pw.println("Unknown argument: " + opt + "; use -h for help");
10618 }
10619 }
10620
10621 ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010622 if (procs == null) {
10623 return;
10624 }
10625
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010626 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010627 long uptime = SystemClock.uptimeMillis();
10628 long realtime = SystemClock.elapsedRealtime();
Dianne Hackbornb437e092011-08-05 17:50:29 -070010629
10630 if (procs.size() == 1 || isCheckinRequest) {
10631 dumpAll = true;
10632 }
10633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010634 if (isCheckinRequest) {
10635 // short checkin version
10636 pw.println(uptime + "," + realtime);
10637 pw.flush();
10638 } else {
10639 pw.println("Applications Memory Usage (kB):");
10640 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10641 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010642
Dianne Hackbornb437e092011-08-05 17:50:29 -070010643 String[] innerArgs = new String[args.length-opti];
10644 System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
10645
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010646 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
10647 long nativePss=0, dalvikPss=0, otherPss=0;
10648 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
10649
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010650 long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
10651 ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
10652 new ArrayList[DUMP_MEM_OOM_LABEL.length];
Dianne Hackbornb437e092011-08-05 17:50:29 -070010653
10654 long totalPss = 0;
10655
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010656 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
10657 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 if (r.thread != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010659 if (!isCheckinRequest && dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010660 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10661 pw.flush();
10662 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010663 Debug.MemoryInfo mi = null;
Dianne Hackbornb437e092011-08-05 17:50:29 -070010664 if (dumpAll) {
10665 try {
10666 mi = r.thread.dumpMemInfo(fd, isCheckinRequest, dumpAll, innerArgs);
10667 } catch (RemoteException e) {
10668 if (!isCheckinRequest) {
10669 pw.println("Got RemoteException!");
10670 pw.flush();
10671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010672 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010673 } else {
10674 mi = new Debug.MemoryInfo();
10675 Debug.getMemoryInfo(r.pid, mi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010677
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010678 if (!isCheckinRequest && mi != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010679 long myTotalPss = mi.getTotalPss();
10680 totalPss += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010681 MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010682 r.processName, myTotalPss, 0);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010683 procMems.add(pssItem);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010684
10685 nativePss += mi.nativePss;
10686 dalvikPss += mi.dalvikPss;
10687 otherPss += mi.otherPss;
10688 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
10689 long mem = mi.getOtherPss(j);
10690 miscPss[j] += mem;
10691 otherPss -= mem;
10692 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010693
10694 for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010695 if (r.setAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
10696 || oomIndex == (oomPss.length-1)) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010697 oomPss[oomIndex] += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010698 if (oomProcs[oomIndex] == null) {
10699 oomProcs[oomIndex] = new ArrayList<MemItem>();
10700 }
10701 oomProcs[oomIndex].add(pssItem);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010702 break;
10703 }
10704 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010706 }
10707 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010708
10709 if (!isCheckinRequest && procs.size() > 1) {
10710 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
10711
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010712 catMems.add(new MemItem("Native", "Native", nativePss, -1));
10713 catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, -2));
10714 catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010715 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010716 String label = Debug.MemoryInfo.getOtherLabel(j);
10717 catMems.add(new MemItem(label, label, miscPss[j], j));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010718 }
10719
Dianne Hackbornb437e092011-08-05 17:50:29 -070010720 ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
10721 for (int j=0; j<oomPss.length; j++) {
10722 if (oomPss[j] != 0) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010723 String label = DUMP_MEM_OOM_LABEL[j];
10724 MemItem item = new MemItem(label, label, oomPss[j],
10725 DUMP_MEM_OOM_ADJ[j]);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010726 item.subitems = oomProcs[j];
10727 oomMems.add(item);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010728 }
10729 }
10730
Dianne Hackborn672342c2011-11-29 11:29:02 -080010731 if (outTag != null || outStack != null) {
10732 if (outTag != null) {
10733 appendMemBucket(outTag, totalPss, "total", false);
10734 }
10735 if (outStack != null) {
10736 appendMemBucket(outStack, totalPss, "total", true);
10737 }
10738 boolean firstLine = true;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010739 for (int i=0; i<oomMems.size(); i++) {
10740 MemItem miCat = oomMems.get(i);
10741 if (miCat.subitems == null || miCat.subitems.size() < 1) {
10742 continue;
10743 }
10744 if (miCat.id < ProcessList.SERVICE_ADJ
10745 || miCat.id == ProcessList.HOME_APP_ADJ
10746 || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010747 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10748 outTag.append(" / ");
10749 }
10750 if (outStack != null) {
10751 if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10752 if (firstLine) {
10753 outStack.append(":");
10754 firstLine = false;
10755 }
10756 outStack.append("\n\t at ");
10757 } else {
10758 outStack.append("$");
10759 }
10760 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010761 for (int j=0; j<miCat.subitems.size(); j++) {
10762 MemItem mi = miCat.subitems.get(j);
10763 if (j > 0) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010764 if (outTag != null) {
10765 outTag.append(" ");
10766 }
10767 if (outStack != null) {
10768 outStack.append("$");
10769 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010770 }
Dianne Hackborn672342c2011-11-29 11:29:02 -080010771 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10772 appendMemBucket(outTag, mi.pss, mi.shortLabel, false);
10773 }
10774 if (outStack != null) {
10775 appendMemBucket(outStack, mi.pss, mi.shortLabel, true);
10776 }
10777 }
10778 if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10779 outStack.append("(");
10780 for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
10781 if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
10782 outStack.append(DUMP_MEM_OOM_LABEL[k]);
10783 outStack.append(":");
10784 outStack.append(DUMP_MEM_OOM_ADJ[k]);
10785 }
10786 }
10787 outStack.append(")");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010788 }
10789 }
10790 }
10791 }
10792
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010793 if (!brief && !oomOnly) {
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010794 pw.println();
10795 pw.println("Total PSS by process:");
10796 dumpMemItems(pw, " ", procMems, true);
10797 pw.println();
10798 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010799 pw.println("Total PSS by OOM adjustment:");
10800 dumpMemItems(pw, " ", oomMems, false);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010801 if (!oomOnly) {
10802 PrintWriter out = categoryPw != null ? categoryPw : pw;
10803 out.println();
10804 out.println("Total PSS by category:");
10805 dumpMemItems(out, " ", catMems, true);
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010806 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010807 pw.println();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010808 pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 }
10811
10812 /**
10813 * Searches array of arguments for the specified string
10814 * @param args array of argument strings
10815 * @param value value to search for
10816 * @return true if the value is contained in the array
10817 */
10818 private static boolean scanArgs(String[] args, String value) {
10819 if (args != null) {
10820 for (String arg : args) {
10821 if (value.equals(arg)) {
10822 return true;
10823 }
10824 }
10825 }
10826 return false;
10827 }
10828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 private final void killServicesLocked(ProcessRecord app,
10830 boolean allowRestart) {
10831 // Report disconnected services.
10832 if (false) {
10833 // XXX we are letting the client link to the service for
10834 // death notifications.
10835 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010836 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010838 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010840 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 = r.connections.values().iterator();
10842 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010843 ArrayList<ConnectionRecord> cl = jt.next();
10844 for (int i=0; i<cl.size(); i++) {
10845 ConnectionRecord c = cl.get(i);
10846 if (c.binding.client != app) {
10847 try {
10848 //c.conn.connected(r.className, null);
10849 } catch (Exception e) {
10850 // todo: this should be asynchronous!
10851 Slog.w(TAG, "Exception thrown disconnected servce "
10852 + r.shortName
10853 + " from app " + app.processName, e);
10854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 }
10856 }
10857 }
10858 }
10859 }
10860 }
10861 }
10862
10863 // Clean up any connections this application has to other services.
10864 if (app.connections.size() > 0) {
10865 Iterator<ConnectionRecord> it = app.connections.iterator();
10866 while (it.hasNext()) {
10867 ConnectionRecord r = it.next();
10868 removeConnectionLocked(r, app, null);
10869 }
10870 }
10871 app.connections.clear();
10872
10873 if (app.services.size() != 0) {
10874 // Any services running in the application need to be placed
10875 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010876 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010878 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 synchronized (sr.stats.getBatteryStats()) {
10880 sr.stats.stopLaunchedLocked();
10881 }
10882 sr.app = null;
10883 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010884 if (mStoppingServices.remove(sr)) {
10885 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
10886 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010887
10888 boolean hasClients = sr.bindings.size() > 0;
10889 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 Iterator<IntentBindRecord> bindings
10891 = sr.bindings.values().iterator();
10892 while (bindings.hasNext()) {
10893 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010894 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895 + ": shouldUnbind=" + b.hasBound);
10896 b.binder = null;
10897 b.requested = b.received = b.hasBound = false;
10898 }
10899 }
10900
Dianne Hackborn070783f2010-12-29 16:46:28 -080010901 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
10902 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010903 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010905 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 sr.crashCount, sr.shortName, app.pid);
10907 bringDownServiceLocked(sr, true);
10908 } else if (!allowRestart) {
10909 bringDownServiceLocked(sr, true);
10910 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010911 boolean canceled = scheduleServiceRestartLocked(sr, true);
10912
10913 // Should the service remain running? Note that in the
10914 // extreme case of so many attempts to deliver a command
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010915 // that it failed we also will stop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010916 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10917 if (sr.pendingStarts.size() == 0) {
10918 sr.startRequested = false;
10919 if (!hasClients) {
10920 // Whoops, no reason to restart!
10921 bringDownServiceLocked(sr, true);
10922 }
10923 }
10924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 }
10926 }
10927
10928 if (!allowRestart) {
10929 app.services.clear();
10930 }
10931 }
10932
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010933 // Make sure we have no more records on the stopping list.
10934 int i = mStoppingServices.size();
10935 while (i > 0) {
10936 i--;
10937 ServiceRecord sr = mStoppingServices.get(i);
10938 if (sr.app == app) {
10939 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010940 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010941 }
10942 }
10943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 app.executingServices.clear();
10945 }
10946
10947 private final void removeDyingProviderLocked(ProcessRecord proc,
10948 ContentProviderRecord cpr) {
10949 synchronized (cpr) {
10950 cpr.launchingApp = null;
10951 cpr.notifyAll();
10952 }
10953
Amith Yamasani742a6712011-05-04 14:49:28 -070010954 mProviderMap.removeProviderByClass(cpr.name, UserId.getUserId(cpr.uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 String names[] = cpr.info.authority.split(";");
10956 for (int j = 0; j < names.length; j++) {
Amith Yamasani742a6712011-05-04 14:49:28 -070010957 mProviderMap.removeProviderByName(names[j], UserId.getUserId(cpr.uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 }
10959
10960 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10961 while (cit.hasNext()) {
10962 ProcessRecord capp = cit.next();
10963 if (!capp.persistent && capp.thread != null
10964 && capp.pid != 0
10965 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010966 Slog.i(TAG, "Kill " + capp.processName
10967 + " (pid " + capp.pid + "): provider " + cpr.info.name
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010968 + " in dying process " + (proc != null ? proc.processName : "??"));
Dianne Hackborn8633e682010-04-22 16:03:41 -070010969 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010970 capp.processName, capp.setAdj, "dying provider "
10971 + cpr.name.toShortString());
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010972 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 }
10974 }
10975
10976 mLaunchingProviders.remove(cpr);
10977 }
10978
10979 /**
10980 * Main code for cleaning up a process when it has gone away. This is
10981 * called both as a result of the process dying, or directly when stopping
10982 * a process when running in single process mode.
10983 */
10984 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010985 boolean restarting, boolean allowRestart, int index) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010987 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 }
10989
Dianne Hackborn36124872009-10-08 16:22:03 -070010990 mProcessesToGc.remove(app);
10991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 // Dismiss any open dialogs.
10993 if (app.crashDialog != null) {
10994 app.crashDialog.dismiss();
10995 app.crashDialog = null;
10996 }
10997 if (app.anrDialog != null) {
10998 app.anrDialog.dismiss();
10999 app.anrDialog = null;
11000 }
11001 if (app.waitDialog != null) {
11002 app.waitDialog.dismiss();
11003 app.waitDialog = null;
11004 }
11005
11006 app.crashing = false;
11007 app.notResponding = false;
11008
11009 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -070011010 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 app.thread = null;
11012 app.forcingToForeground = null;
11013 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070011014 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070011015 app.hasShownUi = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070011016 app.hasAboveClient = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011018 killServicesLocked(app, allowRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019
11020 boolean restart = false;
11021
11022 int NL = mLaunchingProviders.size();
11023
11024 // Remove published content providers.
11025 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011026 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011028 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 cpr.provider = null;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070011030 cpr.proc = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031
11032 // See if someone is waiting for this provider... in which
11033 // case we don't remove it, but just let it restart.
11034 int i = 0;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011035 if (!app.bad && allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 for (; i<NL; i++) {
11037 if (mLaunchingProviders.get(i) == cpr) {
11038 restart = true;
11039 break;
11040 }
11041 }
11042 } else {
11043 i = NL;
11044 }
11045
11046 if (i >= NL) {
11047 removeDyingProviderLocked(app, cpr);
11048 NL = mLaunchingProviders.size();
11049 }
11050 }
11051 app.pubProviders.clear();
11052 }
11053
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011054 // Take care of any launching providers waiting for this process.
11055 if (checkAppInLaunchingProvidersLocked(app, false)) {
11056 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 // Unregister from connected content providers.
11060 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070011061 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 while (it.hasNext()) {
11063 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
11064 cpr.clients.remove(app);
11065 }
11066 app.conProviders.clear();
11067 }
11068
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011069 // At this point there may be remaining entries in mLaunchingProviders
11070 // where we were the only one waiting, so they are no longer of use.
11071 // Look for these and clean up if found.
11072 // XXX Commented out for now. Trying to figure out a way to reproduce
11073 // the actual situation to identify what is actually going on.
11074 if (false) {
11075 for (int i=0; i<NL; i++) {
11076 ContentProviderRecord cpr = (ContentProviderRecord)
11077 mLaunchingProviders.get(i);
11078 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
11079 synchronized (cpr) {
11080 cpr.launchingApp = null;
11081 cpr.notifyAll();
11082 }
11083 }
11084 }
11085 }
11086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 skipCurrentReceiverLocked(app);
11088
11089 // Unregister any receivers.
11090 if (app.receivers.size() > 0) {
11091 Iterator<ReceiverList> it = app.receivers.iterator();
11092 while (it.hasNext()) {
11093 removeReceiverLocked(it.next());
11094 }
11095 app.receivers.clear();
11096 }
11097
Christopher Tate181fafa2009-05-14 11:12:14 -070011098 // If the app is undergoing backup, tell the backup manager about it
11099 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011100 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070011101 try {
11102 IBackupManager bm = IBackupManager.Stub.asInterface(
11103 ServiceManager.getService(Context.BACKUP_SERVICE));
11104 bm.agentDisconnected(app.info.packageName);
11105 } catch (RemoteException e) {
11106 // can't happen; backup manager is local
11107 }
11108 }
11109
Jeff Sharkey287bd832011-05-28 19:36:26 -070011110 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070011111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 // If the caller is restarting this app, then leave it in its
11113 // current lists and let the caller take care of it.
11114 if (restarting) {
11115 return;
11116 }
11117
11118 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011119 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 "Removing non-persistent process during cleanup: " + app);
11121 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070011122 if (mHeavyWeightProcess == app) {
11123 mHeavyWeightProcess = null;
11124 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
11125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011126 } else if (!app.removed) {
11127 // This app is persistent, so we need to keep its record around.
11128 // If it is not already on the pending app list, add it there
11129 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 if (mPersistentStartingProcesses.indexOf(app) < 0) {
11131 mPersistentStartingProcesses.add(app);
11132 restart = true;
11133 }
11134 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011135 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
11136 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 mProcessesOnHold.remove(app);
11138
The Android Open Source Project4df24232009-03-05 14:34:35 -080011139 if (app == mHomeProcess) {
11140 mHomeProcess = null;
11141 }
Dianne Hackbornf35fe232011-11-01 19:25:20 -070011142 if (app == mPreviousProcess) {
11143 mPreviousProcess = null;
11144 }
11145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 if (restart) {
11147 // We have components that still need to be running in the
11148 // process, so re-launch it.
11149 mProcessNames.put(app.processName, app.info.uid, app);
11150 startProcessLocked(app, "restart", app.processName);
11151 } else if (app.pid > 0 && app.pid != MY_PID) {
11152 // Goodbye!
11153 synchronized (mPidsSelfLocked) {
11154 mPidsSelfLocked.remove(app.pid);
11155 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
11156 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070011157 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 }
11159 }
11160
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011161 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
11162 // Look through the content providers we are waiting to have launched,
11163 // and if any run in this process then either schedule a restart of
11164 // the process or kill the client waiting for it if this process has
11165 // gone bad.
11166 int NL = mLaunchingProviders.size();
11167 boolean restart = false;
11168 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011169 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011170 if (cpr.launchingApp == app) {
11171 if (!alwaysBad && !app.bad) {
11172 restart = true;
11173 } else {
11174 removeDyingProviderLocked(app, cpr);
11175 NL = mLaunchingProviders.size();
11176 }
11177 }
11178 }
11179 return restart;
11180 }
11181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 // =========================================================
11183 // SERVICES
11184 // =========================================================
11185
11186 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11187 ActivityManager.RunningServiceInfo info =
11188 new ActivityManager.RunningServiceInfo();
11189 info.service = r.name;
11190 if (r.app != null) {
11191 info.pid = r.app.pid;
11192 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011193 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 info.process = r.processName;
11195 info.foreground = r.isForeground;
11196 info.activeSince = r.createTime;
11197 info.started = r.startRequested;
11198 info.clientCount = r.connections.size();
11199 info.crashCount = r.crashCount;
11200 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011201 if (r.isForeground) {
11202 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11203 }
11204 if (r.startRequested) {
11205 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11206 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011207 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011208 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11209 }
11210 if (r.app != null && r.app.persistent) {
11211 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11212 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011213
11214 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
11215 for (int i=0; i<connl.size(); i++) {
11216 ConnectionRecord conn = connl.get(i);
11217 if (conn.clientLabel != 0) {
11218 info.clientPackage = conn.binding.client.info.packageName;
11219 info.clientLabel = conn.clientLabel;
11220 return info;
11221 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011222 }
11223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011224 return info;
11225 }
11226
11227 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11228 int flags) {
11229 synchronized (this) {
11230 ArrayList<ActivityManager.RunningServiceInfo> res
11231 = new ArrayList<ActivityManager.RunningServiceInfo>();
11232
Amith Yamasani742a6712011-05-04 14:49:28 -070011233 int userId = UserId.getUserId(Binder.getCallingUid());
11234 if (mServiceMap.getAllServices(userId).size() > 0) {
11235 Iterator<ServiceRecord> it
11236 = mServiceMap.getAllServices(userId).iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 while (it.hasNext() && res.size() < maxNum) {
11238 res.add(makeRunningServiceInfoLocked(it.next()));
11239 }
11240 }
11241
11242 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11243 ServiceRecord r = mRestartingServices.get(i);
11244 ActivityManager.RunningServiceInfo info =
11245 makeRunningServiceInfoLocked(r);
11246 info.restarting = r.nextRestartTime;
11247 res.add(info);
11248 }
11249
11250 return res;
11251 }
11252 }
11253
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011254 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11255 synchronized (this) {
Amith Yamasani742a6712011-05-04 14:49:28 -070011256 int userId = UserId.getUserId(Binder.getCallingUid());
11257 ServiceRecord r = mServiceMap.getServiceByName(name, userId);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011258 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011259 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
11260 for (int i=0; i<conn.size(); i++) {
11261 if (conn.get(i).clientIntent != null) {
11262 return conn.get(i).clientIntent;
11263 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011264 }
11265 }
11266 }
11267 }
11268 return null;
11269 }
11270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 private final ServiceRecord findServiceLocked(ComponentName name,
11272 IBinder token) {
Amith Yamasani742a6712011-05-04 14:49:28 -070011273 ServiceRecord r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 return r == token ? r : null;
11275 }
11276
11277 private final class ServiceLookupResult {
11278 final ServiceRecord record;
11279 final String permission;
11280
11281 ServiceLookupResult(ServiceRecord _record, String _permission) {
11282 record = _record;
11283 permission = _permission;
11284 }
11285 };
11286
11287 private ServiceLookupResult findServiceLocked(Intent service,
11288 String resolvedType) {
11289 ServiceRecord r = null;
11290 if (service.getComponent() != null) {
Amith Yamasani742a6712011-05-04 14:49:28 -070011291 r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 }
11293 if (r == null) {
11294 Intent.FilterComparison filter = new Intent.FilterComparison(service);
Amith Yamasani742a6712011-05-04 14:49:28 -070011295 r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 }
11297
11298 if (r == null) {
11299 try {
11300 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011301 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 service, resolvedType, 0);
11303 ServiceInfo sInfo =
11304 rInfo != null ? rInfo.serviceInfo : null;
11305 if (sInfo == null) {
11306 return null;
11307 }
11308
11309 ComponentName name = new ComponentName(
11310 sInfo.applicationInfo.packageName, sInfo.name);
Amith Yamasani742a6712011-05-04 14:49:28 -070011311 r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 } catch (RemoteException ex) {
11313 // pm is in same process, this will never happen.
11314 }
11315 }
11316 if (r != null) {
11317 int callingPid = Binder.getCallingPid();
11318 int callingUid = Binder.getCallingUid();
11319 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011320 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011322 if (!r.exported) {
11323 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
11324 + " from pid=" + callingPid
11325 + ", uid=" + callingUid
11326 + " that is not exported from uid " + r.appInfo.uid);
11327 return new ServiceLookupResult(null, "not exported from uid "
11328 + r.appInfo.uid);
11329 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011330 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 + " from pid=" + callingPid
11332 + ", uid=" + callingUid
11333 + " requires " + r.permission);
11334 return new ServiceLookupResult(null, r.permission);
11335 }
11336 return new ServiceLookupResult(r, null);
11337 }
11338 return null;
11339 }
11340
11341 private class ServiceRestarter implements Runnable {
11342 private ServiceRecord mService;
11343
11344 void setService(ServiceRecord service) {
11345 mService = service;
11346 }
11347
11348 public void run() {
11349 synchronized(ActivityManagerService.this) {
11350 performServiceRestartLocked(mService);
11351 }
11352 }
11353 }
11354
11355 private ServiceLookupResult retrieveServiceLocked(Intent service,
11356 String resolvedType, int callingPid, int callingUid) {
11357 ServiceRecord r = null;
Amith Yamasani742a6712011-05-04 14:49:28 -070011358 if (DEBUG_SERVICE)
11359 Slog.v(TAG, "retrieveServiceLocked: " + service + " type=" + resolvedType
11360 + " origCallingUid=" + callingUid);
11361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 if (service.getComponent() != null) {
Amith Yamasani742a6712011-05-04 14:49:28 -070011363 r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 }
Amith Yamasani742a6712011-05-04 14:49:28 -070011365 if (r == null) {
11366 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11367 r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
11368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 if (r == null) {
11370 try {
11371 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011372 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011373 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 ServiceInfo sInfo =
11375 rInfo != null ? rInfo.serviceInfo : null;
11376 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011377 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 ": not found");
11379 return null;
11380 }
Amith Yamasani742a6712011-05-04 14:49:28 -070011381 if (Binder.getOrigCallingUser() > 0) {
11382 sInfo.applicationInfo = getAppInfoForUser(sInfo.applicationInfo,
11383 Binder.getOrigCallingUser());
11384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 ComponentName name = new ComponentName(
11386 sInfo.applicationInfo.packageName, sInfo.name);
Amith Yamasani742a6712011-05-04 14:49:28 -070011387 r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 if (r == null) {
Amith Yamasani742a6712011-05-04 14:49:28 -070011389 Intent.FilterComparison filter = new Intent.FilterComparison(
11390 service.cloneFilter());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 ServiceRestarter res = new ServiceRestarter();
11392 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11393 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11394 synchronized (stats) {
11395 ss = stats.getServiceStatsLocked(
11396 sInfo.applicationInfo.uid, sInfo.packageName,
11397 sInfo.name);
11398 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011399 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 res.setService(r);
Amith Yamasani742a6712011-05-04 14:49:28 -070011401 mServiceMap.putServiceByName(name, UserId.getUserId(r.appInfo.uid), r);
11402 mServiceMap.putServiceByIntent(filter, UserId.getUserId(r.appInfo.uid), r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403
11404 // Make sure this component isn't in the pending list.
11405 int N = mPendingServices.size();
11406 for (int i=0; i<N; i++) {
11407 ServiceRecord pr = mPendingServices.get(i);
11408 if (pr.name.equals(name)) {
11409 mPendingServices.remove(i);
11410 i--;
11411 N--;
11412 }
11413 }
11414 }
11415 } catch (RemoteException ex) {
11416 // pm is in same process, this will never happen.
11417 }
11418 }
11419 if (r != null) {
11420 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011421 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011423 if (!r.exported) {
11424 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
11425 + " from pid=" + callingPid
11426 + ", uid=" + callingUid
11427 + " that is not exported from uid " + r.appInfo.uid);
11428 return new ServiceLookupResult(null, "not exported from uid "
11429 + r.appInfo.uid);
11430 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011431 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011432 + " from pid=" + callingPid
11433 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 + " requires " + r.permission);
11435 return new ServiceLookupResult(null, r.permission);
11436 }
11437 return new ServiceLookupResult(r, null);
11438 }
11439 return null;
11440 }
11441
Dianne Hackborn287952c2010-09-22 22:34:31 -070011442 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
11443 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
11444 + why + " of " + r + " in app " + r.app);
11445 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
11446 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011447 long now = SystemClock.uptimeMillis();
11448 if (r.executeNesting == 0 && r.app != null) {
11449 if (r.app.executingServices.size() == 0) {
11450 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11451 msg.obj = r.app;
11452 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11453 }
11454 r.app.executingServices.add(r);
11455 }
11456 r.executeNesting++;
11457 r.executingStart = now;
11458 }
11459
11460 private final void sendServiceArgsLocked(ServiceRecord r,
11461 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011462 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 if (N == 0) {
11464 return;
11465 }
11466
Dianne Hackborn39792d22010-08-19 18:01:52 -070011467 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -070011469 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011470 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
11471 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -080011472 if (si.intent == null && N > 1) {
11473 // If somehow we got a dummy null intent in the middle,
11474 // then skip it. DO NOT skip a null intent when it is
11475 // the only one in the list -- this is to support the
11476 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011477 continue;
11478 }
Dianne Hackborn39792d22010-08-19 18:01:52 -070011479 si.deliveredTime = SystemClock.uptimeMillis();
11480 r.deliveredStarts.add(si);
11481 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -080011482 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070011483 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -070011484 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -070011485 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011486 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 if (!oomAdjusted) {
11488 oomAdjusted = true;
11489 updateOomAdjLocked(r.app);
11490 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011491 int flags = 0;
11492 if (si.deliveryCount > 0) {
11493 flags |= Service.START_FLAG_RETRY;
11494 }
11495 if (si.doneExecutingCount > 0) {
11496 flags |= Service.START_FLAG_REDELIVERY;
11497 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011498 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011499 } catch (RemoteException e) {
11500 // Remote process gone... we'll let the normal cleanup take
11501 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011502 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011503 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011505 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 break;
11507 }
11508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 }
11510
11511 private final boolean requestServiceBindingLocked(ServiceRecord r,
11512 IntentBindRecord i, boolean rebind) {
11513 if (r.app == null || r.app.thread == null) {
11514 // If service is not currently running, can't yet bind.
11515 return false;
11516 }
11517 if ((!i.requested || rebind) && i.apps.size() > 0) {
11518 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011519 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11521 if (!rebind) {
11522 i.requested = true;
11523 }
11524 i.hasBound = true;
11525 i.doRebind = false;
11526 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011527 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011528 return false;
11529 }
11530 }
11531 return true;
11532 }
11533
11534 private final void requestServiceBindingsLocked(ServiceRecord r) {
11535 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11536 while (bindings.hasNext()) {
11537 IntentBindRecord i = bindings.next();
11538 if (!requestServiceBindingLocked(r, i, false)) {
11539 break;
11540 }
11541 }
11542 }
11543
11544 private final void realStartServiceLocked(ServiceRecord r,
11545 ProcessRecord app) throws RemoteException {
11546 if (app.thread == null) {
11547 throw new RemoteException();
11548 }
Amith Yamasani742a6712011-05-04 14:49:28 -070011549 if (DEBUG_MU)
11550 Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
11551 + ", ProcessRecord.uid = " + app.info.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011553 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011554
11555 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011556 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011557 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011558
11559 boolean created = false;
11560 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011561 mStringBuilder.setLength(0);
Dianne Hackborn90c52de2011-09-23 12:57:44 -070011562 r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011563 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011565 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 synchronized (r.stats.getBatteryStats()) {
11567 r.stats.startLaunchedLocked();
11568 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011569 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011570 app.thread.scheduleCreateService(r, r.serviceInfo,
11571 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011572 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 created = true;
11574 } finally {
11575 if (!created) {
11576 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011577 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 }
11579 }
11580
11581 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011582
11583 // If the service is in the started state, and there are no
11584 // pending arguments, then fake up one so its onStartCommand() will
11585 // be called.
11586 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011587 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
11588 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011589 }
11590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011591 sendServiceArgsLocked(r, true);
11592 }
11593
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011594 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11595 boolean allowCancel) {
11596 boolean canceled = false;
11597
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011598 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011599 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011600 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011601
Dianne Hackborn070783f2010-12-29 16:46:28 -080011602 if ((r.serviceInfo.applicationInfo.flags
11603 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
11604 minDuration /= 4;
11605 }
11606
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011607 // Any delivered but not yet finished starts should be put back
11608 // on the pending list.
11609 final int N = r.deliveredStarts.size();
11610 if (N > 0) {
11611 for (int i=N-1; i>=0; i--) {
11612 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -070011613 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011614 if (si.intent == null) {
11615 // We'll generate this again if needed.
11616 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11617 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11618 r.pendingStarts.add(0, si);
11619 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11620 dur *= 2;
11621 if (minDuration < dur) minDuration = dur;
11622 if (resetTime < dur) resetTime = dur;
11623 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011624 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011625 + r.name);
11626 canceled = true;
11627 }
11628 }
11629 r.deliveredStarts.clear();
11630 }
11631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 r.totalRestartCount++;
11633 if (r.restartDelay == 0) {
11634 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011635 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 } else {
11637 // If it has been a "reasonably long time" since the service
11638 // was started, then reset our restart duration back to
11639 // the beginning, so we don't infinitely increase the duration
11640 // on a service that just occasionally gets killed (which is
11641 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011642 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011644 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -080011646 if ((r.serviceInfo.applicationInfo.flags
11647 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
11648 // Services in peristent processes will restart much more
11649 // quickly, since they are pretty important. (Think SystemUI).
11650 r.restartDelay += minDuration/2;
11651 } else {
11652 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
11653 if (r.restartDelay < minDuration) {
11654 r.restartDelay = minDuration;
11655 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 }
11658 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011659
11660 r.nextRestartTime = now + r.restartDelay;
11661
11662 // Make sure that we don't end up restarting a bunch of services
11663 // all at the same time.
11664 boolean repeat;
11665 do {
11666 repeat = false;
11667 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11668 ServiceRecord r2 = mRestartingServices.get(i);
11669 if (r2 != r && r.nextRestartTime
11670 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11671 && r.nextRestartTime
11672 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11673 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11674 r.restartDelay = r.nextRestartTime - now;
11675 repeat = true;
11676 break;
11677 }
11678 }
11679 } while (repeat);
11680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011681 if (!mRestartingServices.contains(r)) {
11682 mRestartingServices.add(r);
11683 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011684
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011685 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011688 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011690 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011692 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011693 r.shortName, r.restartDelay);
11694
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011695 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 }
11697
11698 final void performServiceRestartLocked(ServiceRecord r) {
11699 if (!mRestartingServices.contains(r)) {
11700 return;
11701 }
11702 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11703 }
11704
11705 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11706 if (r.restartDelay == 0) {
11707 return false;
11708 }
11709 r.resetRestartCounter();
11710 mRestartingServices.remove(r);
11711 mHandler.removeCallbacks(r.restarter);
11712 return true;
11713 }
11714
11715 private final boolean bringUpServiceLocked(ServiceRecord r,
11716 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011717 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 //r.dump(" ");
11719
Dianne Hackborn36124872009-10-08 16:22:03 -070011720 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 sendServiceArgsLocked(r, false);
11722 return true;
11723 }
11724
11725 if (!whileRestarting && r.restartDelay > 0) {
11726 // If waiting for a restart, then do nothing.
11727 return true;
11728 }
11729
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011730 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011732 // We are now bringing the service up, so no longer in the
11733 // restarting state.
11734 mRestartingServices.remove(r);
11735
Dianne Hackborne7f97212011-02-24 14:40:20 -080011736 // Service is now being launched, its package can't be stopped.
11737 try {
11738 AppGlobals.getPackageManager().setPackageStoppedState(
11739 r.packageName, false);
11740 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011741 } catch (IllegalArgumentException e) {
11742 Slog.w(TAG, "Failed trying to unstop package "
11743 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011744 }
11745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 final String appName = r.processName;
11747 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
Amith Yamasani742a6712011-05-04 14:49:28 -070011748 if (DEBUG_MU)
11749 Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 if (app != null && app.thread != null) {
11751 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011752 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 realStartServiceLocked(r, app);
11754 return true;
11755 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011756 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 }
11758
11759 // If a dead object exception was thrown -- fall through to
11760 // restart the application.
11761 }
11762
Dianne Hackborn36124872009-10-08 16:22:03 -070011763 // Not running -- get it started, and enqueue this service record
11764 // to be executed when the app comes up.
11765 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11766 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011767 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011768 + r.appInfo.packageName + "/"
11769 + r.appInfo.uid + " for service "
11770 + r.intent.getIntent() + ": process is bad");
11771 bringDownServiceLocked(r, true);
11772 return false;
11773 }
11774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 mPendingServices.add(r);
11777 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 return true;
11780 }
11781
11782 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011783 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 //r.dump(" ");
11785
11786 // Does it still need to run?
11787 if (!force && r.startRequested) {
11788 return;
11789 }
11790 if (r.connections.size() > 0) {
11791 if (!force) {
11792 // XXX should probably keep a count of the number of auto-create
11793 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011794 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011795 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011796 ArrayList<ConnectionRecord> cr = it.next();
11797 for (int i=0; i<cr.size(); i++) {
11798 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
11799 return;
11800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 }
11802 }
11803 }
11804
11805 // Report to all of the connections that the service is no longer
11806 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011807 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011809 ArrayList<ConnectionRecord> c = it.next();
11810 for (int i=0; i<c.size(); i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011811 ConnectionRecord cr = c.get(i);
11812 // There is still a connection to the service that is
11813 // being brought down. Mark it as dead.
11814 cr.serviceDead = true;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011815 try {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011816 cr.conn.connected(r.name, null);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011817 } catch (Exception e) {
11818 Slog.w(TAG, "Failure disconnecting service " + r.name +
11819 " to connection " + c.get(i).conn.asBinder() +
11820 " (in " + c.get(i).binding.client.processName + ")", e);
11821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 }
11823 }
11824 }
11825
11826 // Tell the service that it has been unbound.
11827 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11828 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11829 while (it.hasNext()) {
11830 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011831 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011832 + ": hasBound=" + ibr.hasBound);
11833 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11834 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011835 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 updateOomAdjLocked(r.app);
11837 ibr.hasBound = false;
11838 r.app.thread.scheduleUnbindService(r,
11839 ibr.intent.getIntent());
11840 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011841 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 + r.shortName, e);
11843 serviceDoneExecutingLocked(r, true);
11844 }
11845 }
11846 }
11847 }
11848
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011849 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011850 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011851 System.identityHashCode(r), r.shortName,
11852 (r.app != null) ? r.app.pid : -1);
11853
Amith Yamasani742a6712011-05-04 14:49:28 -070011854 mServiceMap.removeServiceByName(r.name, r.userId);
11855 mServiceMap.removeServiceByIntent(r.intent, r.userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 r.totalRestartCount = 0;
11857 unscheduleServiceRestartLocked(r);
11858
11859 // Also make sure it is not on the pending list.
11860 int N = mPendingServices.size();
11861 for (int i=0; i<N; i++) {
11862 if (mPendingServices.get(i) == r) {
11863 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011864 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 i--;
11866 N--;
11867 }
11868 }
11869
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011870 r.cancelNotification();
11871 r.isForeground = false;
11872 r.foregroundId = 0;
11873 r.foregroundNoti = null;
11874
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011875 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070011876 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011877 r.pendingStarts.clear();
11878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879 if (r.app != null) {
11880 synchronized (r.stats.getBatteryStats()) {
11881 r.stats.stopLaunchedLocked();
11882 }
11883 r.app.services.remove(r);
11884 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011886 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 mStoppingServices.add(r);
11888 updateOomAdjLocked(r.app);
11889 r.app.thread.scheduleStopService(r);
11890 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011891 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 + r.shortName, e);
11893 serviceDoneExecutingLocked(r, true);
11894 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011895 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011897 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011898 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 }
11900 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011901 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011902 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080011904
11905 if (r.bindings.size() > 0) {
11906 r.bindings.clear();
11907 }
11908
11909 if (r.restarter instanceof ServiceRestarter) {
11910 ((ServiceRestarter)r.restarter).setService(null);
11911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011912 }
11913
11914 ComponentName startServiceLocked(IApplicationThread caller,
11915 Intent service, String resolvedType,
11916 int callingPid, int callingUid) {
11917 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011918 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 + " type=" + resolvedType + " args=" + service.getExtras());
11920
11921 if (caller != null) {
11922 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11923 if (callerApp == null) {
11924 throw new SecurityException(
11925 "Unable to find app for caller " + caller
11926 + " (pid=" + Binder.getCallingPid()
11927 + ") when starting service " + service);
11928 }
11929 }
11930
11931 ServiceLookupResult res =
11932 retrieveServiceLocked(service, resolvedType,
11933 callingPid, callingUid);
11934 if (res == null) {
11935 return null;
11936 }
11937 if (res.record == null) {
11938 return new ComponentName("!", res.permission != null
11939 ? res.permission : "private to package");
11940 }
11941 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070011942 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
11943 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011944 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011945 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 }
11947 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011948 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011949 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070011950 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011951 r.lastActivity = SystemClock.uptimeMillis();
11952 synchronized (r.stats.getBatteryStats()) {
11953 r.stats.startRunningLocked();
11954 }
11955 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11956 return new ComponentName("!", "Service process is bad");
11957 }
11958 return r.name;
11959 }
11960 }
11961
11962 public ComponentName startService(IApplicationThread caller, Intent service,
11963 String resolvedType) {
11964 // Refuse possible leaked file descriptors
11965 if (service != null && service.hasFileDescriptors() == true) {
11966 throw new IllegalArgumentException("File descriptors passed in Intent");
11967 }
11968
Amith Yamasani742a6712011-05-04 14:49:28 -070011969 if (DEBUG_SERVICE)
11970 Slog.v(TAG, "startService: " + service + " type=" + resolvedType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971 synchronized(this) {
11972 final int callingPid = Binder.getCallingPid();
11973 final int callingUid = Binder.getCallingUid();
11974 final long origId = Binder.clearCallingIdentity();
11975 ComponentName res = startServiceLocked(caller, service,
11976 resolvedType, callingPid, callingUid);
11977 Binder.restoreCallingIdentity(origId);
11978 return res;
11979 }
11980 }
11981
11982 ComponentName startServiceInPackage(int uid,
11983 Intent service, String resolvedType) {
11984 synchronized(this) {
Amith Yamasani742a6712011-05-04 14:49:28 -070011985 if (DEBUG_SERVICE)
11986 Slog.v(TAG, "startServiceInPackage: " + service + " type=" + resolvedType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011987 final long origId = Binder.clearCallingIdentity();
11988 ComponentName res = startServiceLocked(null, service,
11989 resolvedType, -1, uid);
11990 Binder.restoreCallingIdentity(origId);
11991 return res;
11992 }
11993 }
11994
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011995 private void stopServiceLocked(ServiceRecord service) {
11996 synchronized (service.stats.getBatteryStats()) {
11997 service.stats.stopRunningLocked();
11998 }
11999 service.startRequested = false;
12000 service.callStart = false;
12001 bringDownServiceLocked(service, false);
12002 }
12003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 public int stopService(IApplicationThread caller, Intent service,
12005 String resolvedType) {
12006 // Refuse possible leaked file descriptors
12007 if (service != null && service.hasFileDescriptors() == true) {
12008 throw new IllegalArgumentException("File descriptors passed in Intent");
12009 }
12010
12011 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012012 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013 + " type=" + resolvedType);
12014
12015 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12016 if (caller != null && callerApp == null) {
12017 throw new SecurityException(
12018 "Unable to find app for caller " + caller
12019 + " (pid=" + Binder.getCallingPid()
12020 + ") when stopping service " + service);
12021 }
12022
12023 // If this service is active, make sure it is stopped.
12024 ServiceLookupResult r = findServiceLocked(service, resolvedType);
12025 if (r != null) {
12026 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012028 try {
12029 stopServiceLocked(r.record);
12030 } finally {
12031 Binder.restoreCallingIdentity(origId);
12032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 return 1;
12034 }
12035 return -1;
12036 }
12037 }
12038
12039 return 0;
12040 }
12041
12042 public IBinder peekService(Intent service, String resolvedType) {
12043 // Refuse possible leaked file descriptors
12044 if (service != null && service.hasFileDescriptors() == true) {
12045 throw new IllegalArgumentException("File descriptors passed in Intent");
12046 }
12047
12048 IBinder ret = null;
12049
12050 synchronized(this) {
12051 ServiceLookupResult r = findServiceLocked(service, resolvedType);
12052
12053 if (r != null) {
12054 // r.record is null if findServiceLocked() failed the caller permission check
12055 if (r.record == null) {
12056 throw new SecurityException(
12057 "Permission Denial: Accessing service " + r.record.name
12058 + " from pid=" + Binder.getCallingPid()
12059 + ", uid=" + Binder.getCallingUid()
12060 + " requires " + r.permission);
12061 }
12062 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
12063 if (ib != null) {
12064 ret = ib.binder;
12065 }
12066 }
12067 }
12068
12069 return ret;
12070 }
12071
12072 public boolean stopServiceToken(ComponentName className, IBinder token,
12073 int startId) {
12074 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012075 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 + " " + token + " startId=" + startId);
12077 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012078 if (r != null) {
12079 if (startId >= 0) {
12080 // Asked to only stop if done with all work. Note that
12081 // to avoid leaks, we will take this as dropping all
12082 // start items up to and including this one.
12083 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12084 if (si != null) {
12085 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070012086 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
12087 cur.removeUriPermissionsLocked();
12088 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012089 break;
12090 }
12091 }
12092 }
12093
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012094 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012095 return false;
12096 }
12097
12098 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012099 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012100 + " is last, but have " + r.deliveredStarts.size()
12101 + " remaining args");
12102 }
12103 }
12104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 synchronized (r.stats.getBatteryStats()) {
12106 r.stats.stopRunningLocked();
12107 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012108 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012109 }
12110 final long origId = Binder.clearCallingIdentity();
12111 bringDownServiceLocked(r, false);
12112 Binder.restoreCallingIdentity(origId);
12113 return true;
12114 }
12115 }
12116 return false;
12117 }
12118
12119 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012120 int id, Notification notification, boolean removeNotification) {
12121 final long origId = Binder.clearCallingIdentity();
12122 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012123 synchronized(this) {
12124 ServiceRecord r = findServiceLocked(className, token);
12125 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012126 if (id != 0) {
12127 if (notification == null) {
12128 throw new IllegalArgumentException("null notification");
12129 }
12130 if (r.foregroundId != id) {
12131 r.cancelNotification();
12132 r.foregroundId = id;
12133 }
12134 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
12135 r.foregroundNoti = notification;
12136 r.isForeground = true;
12137 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012138 if (r.app != null) {
12139 updateServiceForegroundLocked(r.app, true);
12140 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012141 } else {
12142 if (r.isForeground) {
12143 r.isForeground = false;
12144 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070012145 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012146 updateServiceForegroundLocked(r.app, true);
12147 }
12148 }
12149 if (removeNotification) {
12150 r.cancelNotification();
12151 r.foregroundId = 0;
12152 r.foregroundNoti = null;
12153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012154 }
12155 }
12156 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012157 } finally {
12158 Binder.restoreCallingIdentity(origId);
12159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012160 }
12161
12162 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
12163 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070012164 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012165 if (sr.isForeground) {
12166 anyForeground = true;
12167 break;
12168 }
12169 }
12170 if (anyForeground != proc.foregroundServices) {
12171 proc.foregroundServices = anyForeground;
12172 if (oomAdj) {
12173 updateOomAdjLocked();
12174 }
12175 }
12176 }
12177
12178 public int bindService(IApplicationThread caller, IBinder token,
12179 Intent service, String resolvedType,
12180 IServiceConnection connection, int flags) {
12181 // Refuse possible leaked file descriptors
12182 if (service != null && service.hasFileDescriptors() == true) {
12183 throw new IllegalArgumentException("File descriptors passed in Intent");
12184 }
12185
12186 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012187 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012188 + " type=" + resolvedType + " conn=" + connection.asBinder()
12189 + " flags=0x" + Integer.toHexString(flags));
Amith Yamasani742a6712011-05-04 14:49:28 -070012190 if (DEBUG_MU)
12191 Slog.i(TAG_MU, "bindService uid=" + Binder.getCallingUid() + " origUid="
12192 + Binder.getOrigCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012193 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12194 if (callerApp == null) {
12195 throw new SecurityException(
12196 "Unable to find app for caller " + caller
12197 + " (pid=" + Binder.getCallingPid()
12198 + ") when binding service " + service);
12199 }
12200
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012201 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012202 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070012203 activity = mMainStack.isInStackLocked(token);
12204 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012205 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 return 0;
12207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012208 }
12209
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012210 int clientLabel = 0;
12211 PendingIntent clientIntent = null;
12212
12213 if (callerApp.info.uid == Process.SYSTEM_UID) {
12214 // Hacky kind of thing -- allow system stuff to tell us
12215 // what they are, so we can report this elsewhere for
12216 // others to know why certain services are running.
12217 try {
12218 clientIntent = (PendingIntent)service.getParcelableExtra(
12219 Intent.EXTRA_CLIENT_INTENT);
12220 } catch (RuntimeException e) {
12221 }
12222 if (clientIntent != null) {
12223 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
12224 if (clientLabel != 0) {
12225 // There are no useful extras in the intent, trash them.
12226 // System code calling with this stuff just needs to know
12227 // this will happen.
12228 service = service.cloneFilter();
12229 }
12230 }
12231 }
12232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 ServiceLookupResult res =
12234 retrieveServiceLocked(service, resolvedType,
Amith Yamasani742a6712011-05-04 14:49:28 -070012235 Binder.getCallingPid(), Binder.getOrigCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012236 if (res == null) {
12237 return 0;
12238 }
12239 if (res.record == null) {
12240 return -1;
12241 }
12242 ServiceRecord s = res.record;
12243
12244 final long origId = Binder.clearCallingIdentity();
12245
12246 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012247 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012248 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012249 }
12250
12251 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12252 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012253 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254
12255 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012256 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
12257 if (clist == null) {
12258 clist = new ArrayList<ConnectionRecord>();
12259 s.connections.put(binder, clist);
12260 }
12261 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 b.connections.add(c);
12263 if (activity != null) {
12264 if (activity.connections == null) {
12265 activity.connections = new HashSet<ConnectionRecord>();
12266 }
12267 activity.connections.add(c);
12268 }
12269 b.client.connections.add(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012270 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
12271 b.client.hasAboveClient = true;
12272 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012273 clist = mServiceConnections.get(binder);
12274 if (clist == null) {
12275 clist = new ArrayList<ConnectionRecord>();
12276 mServiceConnections.put(binder, clist);
12277 }
12278 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012279
12280 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12281 s.lastActivity = SystemClock.uptimeMillis();
12282 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12283 return 0;
12284 }
12285 }
12286
12287 if (s.app != null) {
12288 // This could have made the service more important.
12289 updateOomAdjLocked(s.app);
12290 }
12291
Joe Onorato8a9b2202010-02-26 18:56:32 -080012292 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012293 + ": received=" + b.intent.received
12294 + " apps=" + b.intent.apps.size()
12295 + " doRebind=" + b.intent.doRebind);
12296
12297 if (s.app != null && b.intent.received) {
12298 // Service is already running, so we can immediately
12299 // publish the connection.
12300 try {
12301 c.conn.connected(s.name, b.intent.binder);
12302 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012303 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012304 + " to connection " + c.conn.asBinder()
12305 + " (in " + c.binding.client.processName + ")", e);
12306 }
12307
12308 // If this is the first app connected back to this binding,
12309 // and the service had previously asked to be told when
12310 // rebound, then do so.
12311 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12312 requestServiceBindingLocked(s, b.intent, true);
12313 }
12314 } else if (!b.intent.requested) {
12315 requestServiceBindingLocked(s, b.intent, false);
12316 }
12317
12318 Binder.restoreCallingIdentity(origId);
12319 }
12320
12321 return 1;
12322 }
12323
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012324 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012325 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012326 IBinder binder = c.conn.asBinder();
12327 AppBindRecord b = c.binding;
12328 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012329 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
12330 if (clist != null) {
12331 clist.remove(c);
12332 if (clist.size() == 0) {
12333 s.connections.remove(binder);
12334 }
12335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 b.connections.remove(c);
12337 if (c.activity != null && c.activity != skipAct) {
12338 if (c.activity.connections != null) {
12339 c.activity.connections.remove(c);
12340 }
12341 }
12342 if (b.client != skipApp) {
12343 b.client.connections.remove(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012344 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
12345 b.client.updateHasAboveClientLocked();
12346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012348 clist = mServiceConnections.get(binder);
12349 if (clist != null) {
12350 clist.remove(c);
12351 if (clist.size() == 0) {
12352 mServiceConnections.remove(binder);
12353 }
12354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012355
12356 if (b.connections.size() == 0) {
12357 b.intent.apps.remove(b.client);
12358 }
12359
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012360 if (!c.serviceDead) {
12361 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
12362 + ": shouldUnbind=" + b.intent.hasBound);
12363 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12364 && b.intent.hasBound) {
12365 try {
12366 bumpServiceExecutingLocked(s, "unbind");
12367 updateOomAdjLocked(s.app);
12368 b.intent.hasBound = false;
12369 // Assume the client doesn't want to know about a rebind;
12370 // we will deal with that later if it asks for one.
12371 b.intent.doRebind = false;
12372 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12373 } catch (Exception e) {
12374 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
12375 serviceDoneExecutingLocked(s, true);
12376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012377 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012378
12379 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12380 bringDownServiceLocked(s, false);
12381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382 }
12383 }
12384
12385 public boolean unbindService(IServiceConnection connection) {
12386 synchronized (this) {
12387 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012388 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012389 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
12390 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012391 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 + connection.asBinder());
12393 return false;
12394 }
12395
12396 final long origId = Binder.clearCallingIdentity();
12397
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012398 while (clist.size() > 0) {
12399 ConnectionRecord r = clist.get(0);
12400 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012402 if (r.binding.service.app != null) {
12403 // This could have made the service less important.
12404 updateOomAdjLocked(r.binding.service.app);
12405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012406 }
12407
12408 Binder.restoreCallingIdentity(origId);
12409 }
12410
12411 return true;
12412 }
12413
12414 public void publishService(IBinder token, Intent intent, IBinder service) {
12415 // Refuse possible leaked file descriptors
12416 if (intent != null && intent.hasFileDescriptors() == true) {
12417 throw new IllegalArgumentException("File descriptors passed in Intent");
12418 }
12419
12420 synchronized(this) {
12421 if (!(token instanceof ServiceRecord)) {
12422 throw new IllegalArgumentException("Invalid service token");
12423 }
12424 ServiceRecord r = (ServiceRecord)token;
12425
12426 final long origId = Binder.clearCallingIdentity();
12427
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012428 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429 + " " + intent + ": " + service);
12430 if (r != null) {
12431 Intent.FilterComparison filter
12432 = new Intent.FilterComparison(intent);
12433 IntentBindRecord b = r.bindings.get(filter);
12434 if (b != null && !b.received) {
12435 b.binder = service;
12436 b.requested = true;
12437 b.received = true;
12438 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012439 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 = r.connections.values().iterator();
12441 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012442 ArrayList<ConnectionRecord> clist = it.next();
12443 for (int i=0; i<clist.size(); i++) {
12444 ConnectionRecord c = clist.get(i);
12445 if (!filter.equals(c.binding.intent.intent)) {
12446 if (DEBUG_SERVICE) Slog.v(
12447 TAG, "Not publishing to: " + c);
12448 if (DEBUG_SERVICE) Slog.v(
12449 TAG, "Bound intent: " + c.binding.intent.intent);
12450 if (DEBUG_SERVICE) Slog.v(
12451 TAG, "Published intent: " + intent);
12452 continue;
12453 }
12454 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
12455 try {
12456 c.conn.connected(r.name, service);
12457 } catch (Exception e) {
12458 Slog.w(TAG, "Failure sending service " + r.name +
12459 " to connection " + c.conn.asBinder() +
12460 " (in " + c.binding.client.processName + ")", e);
12461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012462 }
12463 }
12464 }
12465 }
12466
12467 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12468
12469 Binder.restoreCallingIdentity(origId);
12470 }
12471 }
12472 }
12473
12474 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12475 // Refuse possible leaked file descriptors
12476 if (intent != null && intent.hasFileDescriptors() == true) {
12477 throw new IllegalArgumentException("File descriptors passed in Intent");
12478 }
12479
12480 synchronized(this) {
12481 if (!(token instanceof ServiceRecord)) {
12482 throw new IllegalArgumentException("Invalid service token");
12483 }
12484 ServiceRecord r = (ServiceRecord)token;
12485
12486 final long origId = Binder.clearCallingIdentity();
12487
12488 if (r != null) {
12489 Intent.FilterComparison filter
12490 = new Intent.FilterComparison(intent);
12491 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012492 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493 + " at " + b + ": apps="
12494 + (b != null ? b.apps.size() : 0));
Per Edelberg78f9fff2010-08-30 20:01:35 +020012495
12496 boolean inStopping = mStoppingServices.contains(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012497 if (b != null) {
Per Edelberg78f9fff2010-08-30 20:01:35 +020012498 if (b.apps.size() > 0 && !inStopping) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012499 // Applications have already bound since the last
12500 // unbind, so just rebind right here.
12501 requestServiceBindingLocked(r, b, true);
12502 } else {
12503 // Note to tell the service the next time there is
12504 // a new client.
12505 b.doRebind = true;
12506 }
12507 }
12508
Per Edelberg78f9fff2010-08-30 20:01:35 +020012509 serviceDoneExecutingLocked(r, inStopping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012510
12511 Binder.restoreCallingIdentity(origId);
12512 }
12513 }
12514 }
12515
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012516 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012517 synchronized(this) {
12518 if (!(token instanceof ServiceRecord)) {
12519 throw new IllegalArgumentException("Invalid service token");
12520 }
12521 ServiceRecord r = (ServiceRecord)token;
12522 boolean inStopping = mStoppingServices.contains(token);
12523 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012524 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012525 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012526 + " with incorrect token: given " + token
12527 + ", expected " + r);
12528 return;
12529 }
12530
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012531 if (type == 1) {
12532 // This is a call from a service start... take care of
12533 // book-keeping.
12534 r.callStart = true;
12535 switch (res) {
12536 case Service.START_STICKY_COMPATIBILITY:
12537 case Service.START_STICKY: {
12538 // We are done with the associated start arguments.
12539 r.findDeliveredStart(startId, true);
12540 // Don't stop if killed.
12541 r.stopIfKilled = false;
12542 break;
12543 }
12544 case Service.START_NOT_STICKY: {
12545 // We are done with the associated start arguments.
12546 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012547 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012548 // There is no more work, and this service
12549 // doesn't want to hang around if killed.
12550 r.stopIfKilled = true;
12551 }
12552 break;
12553 }
12554 case Service.START_REDELIVER_INTENT: {
12555 // We'll keep this item until they explicitly
12556 // call stop for it, but keep track of the fact
12557 // that it was delivered.
12558 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12559 if (si != null) {
12560 si.deliveryCount = 0;
12561 si.doneExecutingCount++;
12562 // Don't stop if killed.
12563 r.stopIfKilled = true;
12564 }
12565 break;
12566 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012567 case Service.START_TASK_REMOVED_COMPLETE: {
12568 // Special processing for onTaskRemoved(). Don't
12569 // impact normal onStartCommand() processing.
12570 r.findDeliveredStart(startId, true);
12571 break;
12572 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012573 default:
12574 throw new IllegalArgumentException(
12575 "Unknown service start result: " + res);
12576 }
12577 if (res == Service.START_STICKY_COMPATIBILITY) {
12578 r.callStart = false;
12579 }
12580 }
Amith Yamasani742a6712011-05-04 14:49:28 -070012581 if (DEBUG_MU)
12582 Slog.v(TAG_MU, "before serviceDontExecutingLocked, uid="
12583 + Binder.getOrigCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012584 final long origId = Binder.clearCallingIdentity();
12585 serviceDoneExecutingLocked(r, inStopping);
12586 Binder.restoreCallingIdentity(origId);
12587 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012588 Slog.w(TAG, "Done executing unknown service from pid "
12589 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012590 }
12591 }
12592 }
12593
12594 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012595 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
12596 + ": nesting=" + r.executeNesting
12597 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012598 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 r.executeNesting--;
12600 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012601 if (DEBUG_SERVICE) Slog.v(TAG,
12602 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 r.app.executingServices.remove(r);
12604 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012605 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
12606 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012607 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12608 }
12609 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012610 if (DEBUG_SERVICE) Slog.v(TAG,
12611 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012612 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020012613 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012614 }
12615 updateOomAdjLocked(r.app);
12616 }
12617 }
12618
12619 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012620 String anrMessage = null;
12621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012622 synchronized(this) {
12623 if (proc.executingServices.size() == 0 || proc.thread == null) {
12624 return;
12625 }
12626 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12627 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12628 ServiceRecord timeout = null;
12629 long nextTime = 0;
12630 while (it.hasNext()) {
12631 ServiceRecord sr = it.next();
12632 if (sr.executingStart < maxTime) {
12633 timeout = sr;
12634 break;
12635 }
12636 if (sr.executingStart > nextTime) {
12637 nextTime = sr.executingStart;
12638 }
12639 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012640 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012641 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012642 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643 } else {
12644 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12645 msg.obj = proc;
12646 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12647 }
12648 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012649
12650 if (anrMessage != null) {
12651 appNotResponding(proc, null, null, anrMessage);
12652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012653 }
12654
12655 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012656 // BACKUP AND RESTORE
12657 // =========================================================
12658
12659 // Cause the target app to be launched if necessary and its backup agent
12660 // instantiated. The backup agent will invoke backupAgentCreated() on the
12661 // activity manager to announce its creation.
12662 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012663 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012664 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12665
12666 synchronized(this) {
12667 // !!! TODO: currently no check here that we're already bound
12668 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12669 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12670 synchronized (stats) {
12671 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12672 }
12673
Dianne Hackborne7f97212011-02-24 14:40:20 -080012674 // Backup agent is now in use, its package can't be stopped.
12675 try {
12676 AppGlobals.getPackageManager().setPackageStoppedState(
12677 app.packageName, false);
12678 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012679 } catch (IllegalArgumentException e) {
12680 Slog.w(TAG, "Failed trying to unstop package "
12681 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012682 }
12683
Christopher Tate181fafa2009-05-14 11:12:14 -070012684 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070012685 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
12686 ? new ComponentName(app.packageName, app.backupAgentName)
12687 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070012688 // startProcessLocked() returns existing proc's record if it's already running
12689 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012690 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012691 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012692 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012693 return false;
12694 }
12695
12696 r.app = proc;
12697 mBackupTarget = r;
12698 mBackupAppName = app.packageName;
12699
Christopher Tate6fa95972009-06-05 18:43:55 -070012700 // Try not to kill the process during backup
12701 updateOomAdjLocked(proc);
12702
Christopher Tate181fafa2009-05-14 11:12:14 -070012703 // If the process is already attached, schedule the creation of the backup agent now.
12704 // If it is not yet live, this will be done when it attaches to the framework.
12705 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012706 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012707 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012708 proc.thread.scheduleCreateBackupAgent(app,
12709 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012710 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012711 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012712 }
12713 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012714 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012715 }
12716 // Invariants: at this point, the target app process exists and the application
12717 // is either already running or in the process of coming up. mBackupTarget and
12718 // mBackupAppName describe the app, so that when it binds back to the AM we
12719 // know that it's scheduled for a backup-agent operation.
12720 }
12721
12722 return true;
12723 }
12724
12725 // A backup agent has just come up
12726 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012727 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012728 + " = " + agent);
12729
12730 synchronized(this) {
12731 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012732 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012733 return;
12734 }
Dianne Hackborn06740692010-09-22 22:46:21 -070012735 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012736
Dianne Hackborn06740692010-09-22 22:46:21 -070012737 long oldIdent = Binder.clearCallingIdentity();
12738 try {
12739 IBackupManager bm = IBackupManager.Stub.asInterface(
12740 ServiceManager.getService(Context.BACKUP_SERVICE));
12741 bm.agentConnected(agentPackageName, agent);
12742 } catch (RemoteException e) {
12743 // can't happen; the backup manager service is local
12744 } catch (Exception e) {
12745 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
12746 e.printStackTrace();
12747 } finally {
12748 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012749 }
12750 }
12751
12752 // done with this agent
12753 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012754 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012755 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012756 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012757 return;
12758 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012759
12760 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012761 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012762 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012763 return;
12764 }
12765
Christopher Tate181fafa2009-05-14 11:12:14 -070012766 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012767 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012768 return;
12769 }
12770
Christopher Tate6fa95972009-06-05 18:43:55 -070012771 ProcessRecord proc = mBackupTarget.app;
12772 mBackupTarget = null;
12773 mBackupAppName = null;
12774
12775 // Not backing this app up any more; reset its OOM adjustment
12776 updateOomAdjLocked(proc);
12777
Christopher Tatec7b31e32009-06-10 15:49:30 -070012778 // If the app crashed during backup, 'thread' will be null here
12779 if (proc.thread != null) {
12780 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012781 proc.thread.scheduleDestroyBackupAgent(appInfo,
12782 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070012783 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012784 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012785 e.printStackTrace();
12786 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012787 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012788 }
12789 }
12790 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012791 // BROADCASTS
12792 // =========================================================
12793
Josh Bartel7f208742010-02-25 11:01:44 -060012794 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012795 List cur) {
12796 final ContentResolver resolver = mContext.getContentResolver();
12797 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12798 if (list == null) {
12799 return cur;
12800 }
12801 int N = list.size();
12802 for (int i=0; i<N; i++) {
12803 Intent intent = list.get(i);
12804 if (filter.match(resolver, intent, true, TAG) >= 0) {
12805 if (cur == null) {
12806 cur = new ArrayList<Intent>();
12807 }
12808 cur.add(intent);
12809 }
12810 }
12811 return cur;
12812 }
12813
Christopher Tatef46723b2012-01-26 14:19:24 -080012814 boolean isPendingBroadcastProcessLocked(int pid) {
12815 return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
12816 || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid);
12817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818
Christopher Tatef46723b2012-01-26 14:19:24 -080012819 void skipPendingBroadcastLocked(int pid) {
12820 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
12821 for (BroadcastQueue queue : mBroadcastQueues) {
12822 queue.skipPendingBroadcastLocked(pid);
12823 }
12824 }
12825
12826 // The app just attached; send any pending broadcasts that it should receive
12827 boolean sendPendingBroadcastsLocked(ProcessRecord app) {
12828 boolean didSomething = false;
12829 for (BroadcastQueue queue : mBroadcastQueues) {
12830 didSomething |= queue.sendPendingBroadcastsLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012831 }
Christopher Tatef46723b2012-01-26 14:19:24 -080012832 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012833 }
12834
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012835 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 IIntentReceiver receiver, IntentFilter filter, String permission) {
12837 synchronized(this) {
12838 ProcessRecord callerApp = null;
12839 if (caller != null) {
12840 callerApp = getRecordForAppLocked(caller);
12841 if (callerApp == null) {
12842 throw new SecurityException(
12843 "Unable to find app for caller " + caller
12844 + " (pid=" + Binder.getCallingPid()
12845 + ") when registering receiver " + receiver);
12846 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012847 if (callerApp.info.uid != Process.SYSTEM_UID &&
12848 !callerApp.pkgList.contains(callerPackage)) {
12849 throw new SecurityException("Given caller package " + callerPackage
12850 + " is not running in process " + callerApp);
12851 }
12852 } else {
12853 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854 }
12855
12856 List allSticky = null;
12857
12858 // Look for any matching sticky broadcasts...
12859 Iterator actions = filter.actionsIterator();
12860 if (actions != null) {
12861 while (actions.hasNext()) {
12862 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012863 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 }
12865 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012866 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012867 }
12868
12869 // The first sticky in the list is returned directly back to
12870 // the client.
12871 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12872
Joe Onorato8a9b2202010-02-26 18:56:32 -080012873 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012874 + ": " + sticky);
12875
12876 if (receiver == null) {
12877 return sticky;
12878 }
12879
12880 ReceiverList rl
12881 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12882 if (rl == null) {
12883 rl = new ReceiverList(this, callerApp,
12884 Binder.getCallingPid(),
12885 Binder.getCallingUid(), receiver);
12886 if (rl.app != null) {
12887 rl.app.receivers.add(rl);
12888 } else {
12889 try {
12890 receiver.asBinder().linkToDeath(rl, 0);
12891 } catch (RemoteException e) {
12892 return sticky;
12893 }
12894 rl.linkedToDeath = true;
12895 }
12896 mRegisteredReceivers.put(receiver.asBinder(), rl);
12897 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012898 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012899 rl.add(bf);
12900 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012901 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 }
12903 mReceiverResolver.addFilter(bf);
12904
12905 // Enqueue broadcasts for all existing stickies that match
12906 // this filter.
12907 if (allSticky != null) {
12908 ArrayList receivers = new ArrayList();
12909 receivers.add(bf);
12910
12911 int N = allSticky.size();
12912 for (int i=0; i<N; i++) {
12913 Intent intent = (Intent)allSticky.get(i);
Christopher Tatef46723b2012-01-26 14:19:24 -080012914 BroadcastQueue queue = broadcastQueueForIntent(intent);
12915 BroadcastRecord r = new BroadcastRecord(queue, intent, null,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012916 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012917 false, true, true);
Christopher Tatef46723b2012-01-26 14:19:24 -080012918 queue.enqueueParallelBroadcastLocked(r);
12919 queue.scheduleBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012920 }
12921 }
12922
12923 return sticky;
12924 }
12925 }
12926
12927 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012928 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012929
Christopher Tatef46723b2012-01-26 14:19:24 -080012930 final long origId = Binder.clearCallingIdentity();
12931 try {
12932 boolean doTrim = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012933
Christopher Tatef46723b2012-01-26 14:19:24 -080012934 synchronized(this) {
12935 ReceiverList rl
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012936 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
Christopher Tatef46723b2012-01-26 14:19:24 -080012937 if (rl != null) {
12938 if (rl.curBroadcast != null) {
12939 BroadcastRecord r = rl.curBroadcast;
12940 final boolean doNext = finishReceiverLocked(
12941 receiver.asBinder(), r.resultCode, r.resultData,
12942 r.resultExtras, r.resultAbort, true);
12943 if (doNext) {
12944 doTrim = true;
12945 r.queue.processNextBroadcast(false);
12946 }
12947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012948
Christopher Tatef46723b2012-01-26 14:19:24 -080012949 if (rl.app != null) {
12950 rl.app.receivers.remove(rl);
12951 }
12952 removeReceiverLocked(rl);
12953 if (rl.linkedToDeath) {
12954 rl.linkedToDeath = false;
12955 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 }
12958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012959
Christopher Tatef46723b2012-01-26 14:19:24 -080012960 // If we actually concluded any broadcasts, we might now be able
12961 // to trim the recipients' apps from our working set
12962 if (doTrim) {
12963 trimApplications();
12964 return;
12965 }
12966
12967 } finally {
12968 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012970 }
12971
12972 void removeReceiverLocked(ReceiverList rl) {
12973 mRegisteredReceivers.remove(rl.receiver.asBinder());
12974 int N = rl.size();
12975 for (int i=0; i<N; i++) {
12976 mReceiverResolver.removeFilter(rl.get(i));
12977 }
12978 }
12979
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012980 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12981 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12982 ProcessRecord r = mLruProcesses.get(i);
12983 if (r.thread != null) {
12984 try {
12985 r.thread.dispatchPackageBroadcast(cmd, packages);
12986 } catch (RemoteException ex) {
12987 }
12988 }
12989 }
12990 }
12991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992 private final int broadcastIntentLocked(ProcessRecord callerApp,
12993 String callerPackage, Intent intent, String resolvedType,
12994 IIntentReceiver resultTo, int resultCode, String resultData,
12995 Bundle map, String requiredPermission,
Amith Yamasani742a6712011-05-04 14:49:28 -070012996 boolean ordered, boolean sticky, int callingPid, int callingUid,
12997 int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012998 intent = new Intent(intent);
12999
Dianne Hackborne7f97212011-02-24 14:40:20 -080013000 // By default broadcasts do not go to stopped apps.
13001 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
13002
Joe Onorato8a9b2202010-02-26 18:56:32 -080013003 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013004 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
13005 + " ordered=" + ordered);
13006 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013007 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013008 }
13009
13010 // Handle special intents: if this broadcast is from the package
13011 // manager about a package being removed, we need to remove all of
13012 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013013 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013014 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013015 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
13016 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080013017 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013018 || uidRemoved) {
13019 if (checkComponentPermission(
13020 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013021 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013022 == PackageManager.PERMISSION_GRANTED) {
13023 if (uidRemoved) {
13024 final Bundle intentExtras = intent.getExtras();
13025 final int uid = intentExtras != null
13026 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
13027 if (uid >= 0) {
13028 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
13029 synchronized (bs) {
13030 bs.removeUidStatsLocked(uid);
13031 }
13032 }
13033 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013034 // If resources are unvailble just force stop all
13035 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080013036 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013037 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
13038 if (list != null && (list.length > 0)) {
13039 for (String pkg : list) {
Christopher Tate3dacd842011-08-19 14:56:15 -070013040 forceStopPackageLocked(pkg, -1, false, true, true, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013041 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070013042 sendPackageBroadcastLocked(
13043 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013044 }
13045 } else {
13046 Uri data = intent.getData();
13047 String ssp;
13048 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
13049 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
13050 forceStopPackageLocked(ssp,
Christopher Tate3dacd842011-08-19 14:56:15 -070013051 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070013052 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013053 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070013054 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
13055 new String[] {ssp});
13056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013057 }
13058 }
13059 }
13060 } else {
13061 String msg = "Permission Denial: " + intent.getAction()
13062 + " broadcast from " + callerPackage + " (pid=" + callingPid
13063 + ", uid=" + callingUid + ")"
13064 + " requires "
13065 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013066 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013067 throw new SecurityException(msg);
13068 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013069
13070 // Special case for adding a package: by default turn on compatibility
13071 // mode.
13072 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070013073 Uri data = intent.getData();
13074 String ssp;
13075 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
13076 mCompatModePackages.handlePackageAddedLocked(ssp,
13077 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013079 }
13080
13081 /*
13082 * If this is the time zone changed action, queue up a message that will reset the timezone
13083 * of all currently running processes. This message will get queued up before the broadcast
13084 * happens.
13085 */
13086 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
13087 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
13088 }
13089
Robert Greenwalt03595d02010-11-02 14:08:23 -070013090 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
13091 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
13092 }
13093
Robert Greenwalt434203a2010-10-11 16:00:27 -070013094 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
13095 ProxyProperties proxy = intent.getParcelableExtra("proxy");
13096 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
13097 }
13098
Dianne Hackborn854060af2009-07-09 18:14:31 -070013099 /*
13100 * Prevent non-system code (defined here to be non-persistent
13101 * processes) from sending protected broadcasts.
13102 */
13103 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
13104 || callingUid == Process.SHELL_UID || callingUid == 0) {
13105 // Always okay.
13106 } else if (callerApp == null || !callerApp.persistent) {
13107 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013108 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070013109 intent.getAction())) {
13110 String msg = "Permission Denial: not allowed to send broadcast "
13111 + intent.getAction() + " from pid="
13112 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013113 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070013114 throw new SecurityException(msg);
13115 }
13116 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013117 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070013118 return BROADCAST_SUCCESS;
13119 }
13120 }
13121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013122 // Add to the sticky list if requested.
13123 if (sticky) {
13124 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
13125 callingPid, callingUid)
13126 != PackageManager.PERMISSION_GRANTED) {
13127 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
13128 + callingPid + ", uid=" + callingUid
13129 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013130 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013131 throw new SecurityException(msg);
13132 }
13133 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013134 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013135 + " and enforce permission " + requiredPermission);
13136 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
13137 }
13138 if (intent.getComponent() != null) {
13139 throw new SecurityException(
13140 "Sticky broadcasts can't target a specific component");
13141 }
13142 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13143 if (list == null) {
13144 list = new ArrayList<Intent>();
13145 mStickyBroadcasts.put(intent.getAction(), list);
13146 }
13147 int N = list.size();
13148 int i;
13149 for (i=0; i<N; i++) {
13150 if (intent.filterEquals(list.get(i))) {
13151 // This sticky already exists, replace it.
13152 list.set(i, new Intent(intent));
13153 break;
13154 }
13155 }
13156 if (i >= N) {
13157 list.add(new Intent(intent));
13158 }
13159 }
13160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 // Figure out who all will receive this broadcast.
13162 List receivers = null;
13163 List<BroadcastFilter> registeredReceivers = null;
13164 try {
13165 if (intent.getComponent() != null) {
13166 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013167 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070013168 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013169 if (ai != null) {
13170 receivers = new ArrayList();
13171 ResolveInfo ri = new ResolveInfo();
Amith Yamasani742a6712011-05-04 14:49:28 -070013172 ri.activityInfo = getActivityInfoForUser(ai, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013173 receivers.add(ri);
13174 }
13175 } else {
Amith Yamasani742a6712011-05-04 14:49:28 -070013176 // TODO: Apply userId
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013177 // Need to resolve the intent to interested receivers...
13178 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
13179 == 0) {
13180 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013181 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013182 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 }
Mihai Preda074edef2009-05-18 17:13:31 +020013184 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013185 }
13186 } catch (RemoteException ex) {
13187 // pm is in same process, this will never happen.
13188 }
13189
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013190 final boolean replacePending =
13191 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
13192
Joe Onorato8a9b2202010-02-26 18:56:32 -080013193 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013194 + " replacePending=" + replacePending);
13195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013196 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
13197 if (!ordered && NR > 0) {
13198 // If we are not serializing this broadcast, then send the
13199 // registered receivers separately so they don't wait for the
13200 // components to be launched.
Christopher Tatef46723b2012-01-26 14:19:24 -080013201 final BroadcastQueue queue = broadcastQueueForIntent(intent);
13202 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 callerPackage, callingPid, callingUid, requiredPermission,
13204 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013205 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013206 if (DEBUG_BROADCAST) Slog.v(
Christopher Tatef46723b2012-01-26 14:19:24 -080013207 TAG, "Enqueueing parallel broadcast " + r);
13208 final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013209 if (!replaced) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013210 queue.enqueueParallelBroadcastLocked(r);
13211 queue.scheduleBroadcastsLocked();
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013213 registeredReceivers = null;
13214 NR = 0;
13215 }
13216
13217 // Merge into one list.
13218 int ir = 0;
13219 if (receivers != null) {
13220 // A special case for PACKAGE_ADDED: do not allow the package
13221 // being added to see this broadcast. This prevents them from
13222 // using this as a back door to get run as soon as they are
13223 // installed. Maybe in the future we want to have a special install
13224 // broadcast or such for apps, but we'd like to deliberately make
13225 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013226 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013227 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
13228 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
13229 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013230 Uri data = intent.getData();
13231 if (data != null) {
13232 String pkgName = data.getSchemeSpecificPart();
13233 if (pkgName != null) {
13234 skipPackages = new String[] { pkgName };
13235 }
13236 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013237 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013238 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070013239 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013240 if (skipPackages != null && (skipPackages.length > 0)) {
13241 for (String skipPackage : skipPackages) {
13242 if (skipPackage != null) {
13243 int NT = receivers.size();
13244 for (int it=0; it<NT; it++) {
13245 ResolveInfo curt = (ResolveInfo)receivers.get(it);
13246 if (curt.activityInfo.packageName.equals(skipPackage)) {
13247 receivers.remove(it);
13248 it--;
13249 NT--;
13250 }
13251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013252 }
13253 }
13254 }
13255
13256 int NT = receivers != null ? receivers.size() : 0;
13257 int it = 0;
13258 ResolveInfo curt = null;
13259 BroadcastFilter curr = null;
13260 while (it < NT && ir < NR) {
13261 if (curt == null) {
13262 curt = (ResolveInfo)receivers.get(it);
13263 }
13264 if (curr == null) {
13265 curr = registeredReceivers.get(ir);
13266 }
13267 if (curr.getPriority() >= curt.priority) {
13268 // Insert this broadcast record into the final list.
13269 receivers.add(it, curr);
13270 ir++;
13271 curr = null;
13272 it++;
13273 NT++;
13274 } else {
13275 // Skip to the next ResolveInfo in the final list.
13276 it++;
13277 curt = null;
13278 }
13279 }
13280 }
13281 while (ir < NR) {
13282 if (receivers == null) {
13283 receivers = new ArrayList();
13284 }
13285 receivers.add(registeredReceivers.get(ir));
13286 ir++;
13287 }
13288
13289 if ((receivers != null && receivers.size() > 0)
13290 || resultTo != null) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013291 BroadcastQueue queue = broadcastQueueForIntent(intent);
13292 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013293 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013294 receivers, resultTo, resultCode, resultData, map, ordered,
13295 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013296 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297 TAG, "Enqueueing ordered broadcast " + r
Christopher Tatef46723b2012-01-26 14:19:24 -080013298 + ": prev had " + queue.mOrderedBroadcasts.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 if (DEBUG_BROADCAST) {
13300 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013301 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302 }
Christopher Tatef46723b2012-01-26 14:19:24 -080013303 boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013304 if (!replaced) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013305 queue.enqueueOrderedBroadcastLocked(r);
13306 queue.scheduleBroadcastsLocked();
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013308 }
13309
13310 return BROADCAST_SUCCESS;
13311 }
13312
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013313 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013314 // Refuse possible leaked file descriptors
13315 if (intent != null && intent.hasFileDescriptors() == true) {
13316 throw new IllegalArgumentException("File descriptors passed in Intent");
13317 }
13318
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013319 int flags = intent.getFlags();
13320
13321 if (!mProcessesReady) {
13322 // if the caller really truly claims to know what they're doing, go
13323 // ahead and allow the broadcast without launching any receivers
13324 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
13325 intent = new Intent(intent);
13326 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
13327 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
13328 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
13329 + " before boot completion");
13330 throw new IllegalStateException("Cannot broadcast before boot completed");
13331 }
13332 }
13333
13334 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
13335 throw new IllegalArgumentException(
13336 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13337 }
13338
13339 return intent;
13340 }
13341
13342 public final int broadcastIntent(IApplicationThread caller,
13343 Intent intent, String resolvedType, IIntentReceiver resultTo,
13344 int resultCode, String resultData, Bundle map,
Amith Yamasani742a6712011-05-04 14:49:28 -070013345 String requiredPermission, boolean serialized, boolean sticky, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013346 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013347 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013349 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13350 final int callingPid = Binder.getCallingPid();
13351 final int callingUid = Binder.getCallingUid();
13352 final long origId = Binder.clearCallingIdentity();
13353 int res = broadcastIntentLocked(callerApp,
13354 callerApp != null ? callerApp.info.packageName : null,
13355 intent, resolvedType, resultTo,
Amith Yamasani742a6712011-05-04 14:49:28 -070013356 resultCode, resultData, map, requiredPermission, serialized, sticky,
13357 callingPid, callingUid, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 Binder.restoreCallingIdentity(origId);
13359 return res;
13360 }
13361 }
13362
13363 int broadcastIntentInPackage(String packageName, int uid,
13364 Intent intent, String resolvedType, IIntentReceiver resultTo,
13365 int resultCode, String resultData, Bundle map,
Amith Yamasani742a6712011-05-04 14:49:28 -070013366 String requiredPermission, boolean serialized, boolean sticky, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013367 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013368 intent = verifyBroadcastLocked(intent);
13369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370 final long origId = Binder.clearCallingIdentity();
13371 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13372 resultTo, resultCode, resultData, map, requiredPermission,
Amith Yamasani742a6712011-05-04 14:49:28 -070013373 serialized, sticky, -1, uid, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013374 Binder.restoreCallingIdentity(origId);
13375 return res;
13376 }
13377 }
13378
Amith Yamasani742a6712011-05-04 14:49:28 -070013379 // TODO: Use the userId; maybe mStickyBroadcasts need to be tied to the user.
13380 public final void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 // Refuse possible leaked file descriptors
13382 if (intent != null && intent.hasFileDescriptors() == true) {
13383 throw new IllegalArgumentException("File descriptors passed in Intent");
13384 }
13385
13386 synchronized(this) {
13387 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13388 != PackageManager.PERMISSION_GRANTED) {
13389 String msg = "Permission Denial: unbroadcastIntent() from pid="
13390 + Binder.getCallingPid()
13391 + ", uid=" + Binder.getCallingUid()
13392 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013393 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013394 throw new SecurityException(msg);
13395 }
13396 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13397 if (list != null) {
13398 int N = list.size();
13399 int i;
13400 for (i=0; i<N; i++) {
13401 if (intent.filterEquals(list.get(i))) {
13402 list.remove(i);
13403 break;
13404 }
13405 }
13406 }
13407 }
13408 }
13409
13410 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13411 String resultData, Bundle resultExtras, boolean resultAbort,
13412 boolean explicit) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013413 final BroadcastRecord r = broadcastRecordForReceiverLocked(receiver);
13414 if (r == null) {
13415 Slog.w(TAG, "finishReceiver called but not found on queue");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013416 return false;
13417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418
Christopher Tatef46723b2012-01-26 14:19:24 -080013419 return r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort,
13420 explicit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 }
13422
13423 public void finishReceiver(IBinder who, int resultCode, String resultData,
13424 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013425 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013426
13427 // Refuse possible leaked file descriptors
13428 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13429 throw new IllegalArgumentException("File descriptors passed in Bundle");
13430 }
13431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013432 final long origId = Binder.clearCallingIdentity();
Christopher Tatef46723b2012-01-26 14:19:24 -080013433 try {
13434 boolean doNext = false;
13435 BroadcastRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436
Christopher Tatef46723b2012-01-26 14:19:24 -080013437 synchronized(this) {
13438 r = broadcastRecordForReceiverLocked(who);
13439 if (r != null) {
13440 doNext = r.queue.finishReceiverLocked(r, resultCode,
13441 resultData, resultExtras, resultAbort, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013443 }
Jeff Brown4d94a762010-09-23 11:33:28 -070013444
Christopher Tatef46723b2012-01-26 14:19:24 -080013445 if (doNext) {
13446 r.queue.processNextBroadcast(false);
13447 }
13448 trimApplications();
13449 } finally {
13450 Binder.restoreCallingIdentity(origId);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013452 }
13453
13454 private final void processCurBroadcastLocked(BroadcastRecord r,
13455 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013456 if (DEBUG_BROADCAST) Slog.v(TAG,
13457 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013458 if (app.thread == null) {
13459 throw new RemoteException();
13460 }
13461 r.receiver = app.thread.asBinder();
13462 r.curApp = app;
13463 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013464 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013465
13466 // Tell the application to launch this receiver.
13467 r.intent.setComponent(r.curComponent);
13468
13469 boolean started = false;
13470 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013471 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013472 "Delivering to component " + r.curComponent
13473 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013474 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013475 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040013476 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013477 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013478 if (DEBUG_BROADCAST) Slog.v(TAG,
13479 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013480 started = true;
13481 } finally {
13482 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013483 if (DEBUG_BROADCAST) Slog.v(TAG,
13484 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013485 r.receiver = null;
13486 r.curApp = null;
13487 app.curReceiver = null;
13488 }
13489 }
13490
13491 }
13492
Jeff Brown4d94a762010-09-23 11:33:28 -070013493 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013494 Intent intent, int resultCode, String data, Bundle extras,
13495 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070013496 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013497 if (app != null && app.thread != null) {
13498 // If we have an app thread, do the call through that so it is
13499 // correctly ordered with other one-way calls.
13500 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013501 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013502 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013503 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013504 }
13505 }
13506
Jeff Brown4d94a762010-09-23 11:33:28 -070013507 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013508 BroadcastFilter filter, boolean ordered) {
13509 boolean skip = false;
13510 if (filter.requiredPermission != null) {
13511 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013512 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013513 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013514 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 + r.intent.toString()
13516 + " from " + r.callerPackage + " (pid="
13517 + r.callingPid + ", uid=" + r.callingUid + ")"
13518 + " requires " + filter.requiredPermission
13519 + " due to registered receiver " + filter);
13520 skip = true;
13521 }
13522 }
13523 if (r.requiredPermission != null) {
13524 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013525 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013527 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013528 + r.intent.toString()
13529 + " to " + filter.receiverList.app
13530 + " (pid=" + filter.receiverList.pid
13531 + ", uid=" + filter.receiverList.uid + ")"
13532 + " requires " + r.requiredPermission
13533 + " due to sender " + r.callerPackage
13534 + " (uid " + r.callingUid + ")");
13535 skip = true;
13536 }
13537 }
13538
13539 if (!skip) {
13540 // If this is not being sent as an ordered broadcast, then we
13541 // don't want to touch the fields that keep track of the current
13542 // state of ordered broadcasts.
13543 if (ordered) {
13544 r.receiver = filter.receiverList.receiver.asBinder();
13545 r.curFilter = filter;
13546 filter.receiverList.curBroadcast = r;
13547 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013548 if (filter.receiverList.app != null) {
13549 // Bump hosting application to no longer be in background
13550 // scheduling class. Note that we can't do that if there
13551 // isn't an app... but we can only be in that case for
13552 // things that directly call the IActivityManager API, which
13553 // are already core system stuff so don't matter for this.
13554 r.curApp = filter.receiverList.app;
13555 filter.receiverList.app.curReceiver = r;
13556 updateOomAdjLocked();
13557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013558 }
13559 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013560 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013561 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013562 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013563 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564 }
Jeff Brown4d94a762010-09-23 11:33:28 -070013565 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013566 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013567 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 if (ordered) {
13569 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13570 }
13571 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013572 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013573 if (ordered) {
13574 r.receiver = null;
13575 r.curFilter = null;
13576 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013577 if (filter.receiverList.app != null) {
13578 filter.receiverList.app.curReceiver = null;
13579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013580 }
13581 }
13582 }
13583 }
13584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013585 // =========================================================
13586 // INSTRUMENTATION
13587 // =========================================================
13588
13589 public boolean startInstrumentation(ComponentName className,
13590 String profileFile, int flags, Bundle arguments,
13591 IInstrumentationWatcher watcher) {
13592 // Refuse possible leaked file descriptors
13593 if (arguments != null && arguments.hasFileDescriptors()) {
13594 throw new IllegalArgumentException("File descriptors passed in Bundle");
13595 }
13596
13597 synchronized(this) {
13598 InstrumentationInfo ii = null;
13599 ApplicationInfo ai = null;
13600 try {
13601 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013602 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013603 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013604 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 } catch (PackageManager.NameNotFoundException e) {
13606 }
13607 if (ii == null) {
13608 reportStartInstrumentationFailure(watcher, className,
13609 "Unable to find instrumentation info for: " + className);
13610 return false;
13611 }
13612 if (ai == null) {
13613 reportStartInstrumentationFailure(watcher, className,
13614 "Unable to find instrumentation target package: " + ii.targetPackage);
13615 return false;
13616 }
13617
13618 int match = mContext.getPackageManager().checkSignatures(
13619 ii.targetPackage, ii.packageName);
13620 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13621 String msg = "Permission Denial: starting instrumentation "
13622 + className + " from pid="
13623 + Binder.getCallingPid()
13624 + ", uid=" + Binder.getCallingPid()
13625 + " not allowed because package " + ii.packageName
13626 + " does not have a signature matching the target "
13627 + ii.targetPackage;
13628 reportStartInstrumentationFailure(watcher, className, msg);
13629 throw new SecurityException(msg);
13630 }
13631
13632 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -070013633 // Instrumentation can kill and relaunch even persistent processes
13634 forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013635 ProcessRecord app = addAppLocked(ai);
13636 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013637 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013638 app.instrumentationProfileFile = profileFile;
13639 app.instrumentationArguments = arguments;
13640 app.instrumentationWatcher = watcher;
13641 app.instrumentationResultClass = className;
13642 Binder.restoreCallingIdentity(origId);
13643 }
13644
13645 return true;
13646 }
13647
13648 /**
13649 * Report errors that occur while attempting to start Instrumentation. Always writes the
13650 * error to the logs, but if somebody is watching, send the report there too. This enables
13651 * the "am" command to report errors with more information.
13652 *
13653 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13654 * @param cn The component name of the instrumentation.
13655 * @param report The error report.
13656 */
13657 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13658 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013659 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013660 try {
13661 if (watcher != null) {
13662 Bundle results = new Bundle();
13663 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13664 results.putString("Error", report);
13665 watcher.instrumentationStatus(cn, -1, results);
13666 }
13667 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013668 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013669 }
13670 }
13671
13672 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13673 if (app.instrumentationWatcher != null) {
13674 try {
13675 // NOTE: IInstrumentationWatcher *must* be oneway here
13676 app.instrumentationWatcher.instrumentationFinished(
13677 app.instrumentationClass,
13678 resultCode,
13679 results);
13680 } catch (RemoteException e) {
13681 }
13682 }
13683 app.instrumentationWatcher = null;
13684 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013685 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013686 app.instrumentationProfileFile = null;
13687 app.instrumentationArguments = null;
13688
Christopher Tate3dacd842011-08-19 14:56:15 -070013689 forceStopPackageLocked(app.processName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013690 }
13691
13692 public void finishInstrumentation(IApplicationThread target,
13693 int resultCode, Bundle results) {
13694 // Refuse possible leaked file descriptors
13695 if (results != null && results.hasFileDescriptors()) {
13696 throw new IllegalArgumentException("File descriptors passed in Intent");
13697 }
13698
13699 synchronized(this) {
13700 ProcessRecord app = getRecordForAppLocked(target);
13701 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013702 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013703 return;
13704 }
13705 final long origId = Binder.clearCallingIdentity();
13706 finishInstrumentationLocked(app, resultCode, results);
13707 Binder.restoreCallingIdentity(origId);
13708 }
13709 }
13710
13711 // =========================================================
13712 // CONFIGURATION
13713 // =========================================================
13714
13715 public ConfigurationInfo getDeviceConfigurationInfo() {
13716 ConfigurationInfo config = new ConfigurationInfo();
13717 synchronized (this) {
13718 config.reqTouchScreen = mConfiguration.touchscreen;
13719 config.reqKeyboardType = mConfiguration.keyboard;
13720 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013721 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13722 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013723 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13724 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013725 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13726 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013727 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13728 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013729 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013730 }
13731 return config;
13732 }
13733
13734 public Configuration getConfiguration() {
13735 Configuration ci;
13736 synchronized(this) {
13737 ci = new Configuration(mConfiguration);
13738 }
13739 return ci;
13740 }
13741
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013742 public void updatePersistentConfiguration(Configuration values) {
13743 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13744 "updateConfiguration()");
13745 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
13746 "updateConfiguration()");
13747 if (values == null) {
13748 throw new NullPointerException("Configuration must not be null");
13749 }
13750
13751 synchronized(this) {
13752 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn813075a62011-11-14 17:45:19 -080013753 updateConfigurationLocked(values, null, true, false);
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013754 Binder.restoreCallingIdentity(origId);
13755 }
13756 }
13757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013758 public void updateConfiguration(Configuration values) {
13759 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13760 "updateConfiguration()");
13761
13762 synchronized(this) {
13763 if (values == null && mWindowManager != null) {
13764 // sentinel: fetch the current configuration from the window manager
13765 values = mWindowManager.computeNewConfiguration();
13766 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013767
13768 if (mWindowManager != null) {
13769 mProcessList.applyDisplaySize(mWindowManager);
13770 }
13771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013772 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013773 if (values != null) {
13774 Settings.System.clearConfiguration(values);
13775 }
Dianne Hackborn813075a62011-11-14 17:45:19 -080013776 updateConfigurationLocked(values, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013777 Binder.restoreCallingIdentity(origId);
13778 }
13779 }
13780
13781 /**
13782 * Do either or both things: (1) change the current configuration, and (2)
13783 * make sure the given activity is running with the (now) current
13784 * configuration. Returns true if the activity has been left running, or
13785 * false if <var>starting</var> is being destroyed to match the new
13786 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013787 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013788 */
13789 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn813075a62011-11-14 17:45:19 -080013790 ActivityRecord starting, boolean persistent, boolean initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013791 int changes = 0;
13792
13793 boolean kept = true;
13794
13795 if (values != null) {
13796 Configuration newConfig = new Configuration(mConfiguration);
13797 changes = newConfig.updateFrom(values);
13798 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013799 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013800 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013801 }
13802
Doug Zongker2bec3d42009-12-04 12:52:44 -080013803 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013804
Dianne Hackborn813075a62011-11-14 17:45:19 -080013805 if (values.locale != null && !initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013806 saveLocaleLocked(values.locale,
13807 !values.locale.equals(mConfiguration.locale),
13808 values.userSetLocale);
13809 }
13810
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013811 mConfigurationSeq++;
13812 if (mConfigurationSeq <= 0) {
13813 mConfigurationSeq = 1;
13814 }
13815 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013816 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013817 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013818
13819 final Configuration configCopy = new Configuration(mConfiguration);
13820
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013821 AttributeCache ac = AttributeCache.instance();
13822 if (ac != null) {
Dianne Hackborn813075a62011-11-14 17:45:19 -080013823 ac.updateConfiguration(configCopy);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013825
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013826 // Make sure all resources in our process are updated
13827 // right now, so that anyone who is going to retrieve
13828 // resource values after we return will be sure to get
13829 // the new ones. This is especially important during
13830 // boot, where the first config change needs to guarantee
13831 // all resources have that config before following boot
13832 // code is executed.
Dianne Hackborn813075a62011-11-14 17:45:19 -080013833 mSystemThread.applyConfigurationToResources(configCopy);
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013834
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013835 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013836 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013837 msg.obj = new Configuration(configCopy);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013838 mHandler.sendMessage(msg);
13839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013840
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013841 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13842 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013843 try {
13844 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013845 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013846 + app.processName + " new config " + mConfiguration);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013847 app.thread.scheduleConfigurationChanged(configCopy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013848 }
13849 } catch (Exception e) {
13850 }
13851 }
13852 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013853 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13854 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013855 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
Amith Yamasani742a6712011-05-04 14:49:28 -070013856 null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013857 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13858 broadcastIntentLocked(null, null,
13859 new Intent(Intent.ACTION_LOCALE_CHANGED),
13860 null, null, 0, null, null,
Amith Yamasani742a6712011-05-04 14:49:28 -070013861 null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013863 }
13864 }
13865
13866 if (changes != 0 && starting == null) {
13867 // If the configuration changed, and the caller is not already
13868 // in the process of starting an activity, then find the top
13869 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013870 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013871 }
13872
13873 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013874 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080013875 // And we need to make sure at this point that all other activities
13876 // are made visible with the correct configuration.
13877 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013878 }
13879
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013880 if (values != null && mWindowManager != null) {
13881 mWindowManager.setNewConfiguration(mConfiguration);
13882 }
13883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013884 return kept;
13885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013886
13887 /**
13888 * Save the locale. You must be inside a synchronized (this) block.
13889 */
13890 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13891 if(isDiff) {
13892 SystemProperties.set("user.language", l.getLanguage());
13893 SystemProperties.set("user.region", l.getCountry());
13894 }
13895
13896 if(isPersist) {
13897 SystemProperties.set("persist.sys.language", l.getLanguage());
13898 SystemProperties.set("persist.sys.country", l.getCountry());
13899 SystemProperties.set("persist.sys.localevar", l.getVariant());
13900 }
13901 }
13902
13903 // =========================================================
13904 // LIFETIME MANAGEMENT
13905 // =========================================================
13906
Christopher Tatef46723b2012-01-26 14:19:24 -080013907 // Returns which broadcast queue the app is the current [or imminent] receiver
13908 // on, or 'null' if the app is not an active broadcast recipient.
13909 private BroadcastQueue isReceivingBroadcast(ProcessRecord app) {
13910 BroadcastRecord r = app.curReceiver;
13911 if (r != null) {
13912 return r.queue;
13913 }
13914
13915 // It's not the current receiver, but it might be starting up to become one
13916 synchronized (this) {
13917 for (BroadcastQueue queue : mBroadcastQueues) {
13918 r = queue.mPendingBroadcast;
13919 if (r != null && r.curApp == app) {
13920 // found it; report which queue it's in
13921 return queue;
13922 }
13923 }
13924 }
13925
13926 return null;
13927 }
13928
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013929 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013930 ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013931 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013932 // This adjustment has already been computed. If we are calling
13933 // from the top, we may have already computed our adjustment with
13934 // an earlier hidden adjustment that isn't really for us... if
13935 // so, use the new hidden adjustment.
13936 if (!recursed && app.hidden) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013937 app.curAdj = app.curRawAdj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013938 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013939 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013940 }
13941
13942 if (app.thread == null) {
13943 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013944 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013945 return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013946 }
13947
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013948 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
13949 app.adjSource = null;
13950 app.adjTarget = null;
13951 app.empty = false;
13952 app.hidden = false;
13953
13954 final int activitiesSize = app.activities.size();
13955
Dianne Hackborn7d608422011-08-07 16:24:18 -070013956 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013957 // The max adjustment doesn't allow this app to be anything
13958 // below foreground, so it is not worth doing work for it.
13959 app.adjType = "fixed";
13960 app.adjSeq = mAdjSeq;
13961 app.curRawAdj = app.maxAdj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013962 app.foregroundActivities = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013963 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013964 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013965 // System process can do UI, and when they do we want to have
13966 // them trim their memory after the user leaves the UI. To
13967 // facilitate this, here we need to determine whether or not it
13968 // is currently showing UI.
13969 app.systemNoUi = true;
13970 if (app == TOP_APP) {
13971 app.systemNoUi = false;
13972 } else if (activitiesSize > 0) {
13973 for (int j = 0; j < activitiesSize; j++) {
13974 final ActivityRecord r = app.activities.get(j);
13975 if (r.visible) {
13976 app.systemNoUi = false;
13977 break;
13978 }
13979 }
13980 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013981 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013982 }
13983
13984 final boolean hadForegroundActivities = app.foregroundActivities;
13985
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013986 app.foregroundActivities = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013987 app.keeping = false;
13988 app.systemNoUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013989
The Android Open Source Project4df24232009-03-05 14:34:35 -080013990 // Determine the importance of the process, starting with most
13991 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013993 int schedGroup;
Christopher Tatef46723b2012-01-26 14:19:24 -080013994 BroadcastQueue queue;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013995 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 // The last app on the list is the foreground app.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013997 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013998 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013999 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014000 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014001 } else if (app.instrumentationClass != null) {
14002 // Don't want to kill running instrumentation.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014003 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014004 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014005 app.adjType = "instrumentation";
Christopher Tatef46723b2012-01-26 14:19:24 -080014006 } else if ((queue = isReceivingBroadcast(app)) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014007 // An app that is currently receiving a broadcast also
Christopher Tatef46723b2012-01-26 14:19:24 -080014008 // counts as being in the foreground for OOM killer purposes.
14009 // It's placed in a sched group based on the nature of the
14010 // broadcast as reflected by which queue it's active in.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014011 adj = ProcessList.FOREGROUND_APP_ADJ;
Christopher Tatef46723b2012-01-26 14:19:24 -080014012 schedGroup = (queue == mFgBroadcastQueue)
14013 ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014014 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014015 } else if (app.executingServices.size() > 0) {
14016 // An app that is currently executing a service callback also
14017 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014018 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014019 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014020 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014021 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014022 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014023 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014024 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014025 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014026 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014027 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014028 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014029 // A very not-needed process. If this is lower in the lru list,
14030 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014031 adj = hiddenAdj;
14032 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014033 app.hidden = true;
14034 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014035 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014036 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014037
14038 // Examine all activities if not already foreground.
14039 if (!app.foregroundActivities && activitiesSize > 0) {
14040 for (int j = 0; j < activitiesSize; j++) {
14041 final ActivityRecord r = app.activities.get(j);
14042 if (r.visible) {
14043 // App has a visible activity; only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014044 if (adj > ProcessList.VISIBLE_APP_ADJ) {
14045 adj = ProcessList.VISIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014046 app.adjType = "visible";
14047 }
14048 schedGroup = Process.THREAD_GROUP_DEFAULT;
14049 app.hidden = false;
14050 app.foregroundActivities = true;
14051 break;
14052 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
14053 || r.state == ActivityState.STOPPING) {
14054 // Only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014055 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
14056 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014057 app.adjType = "stopping";
14058 }
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -080014059 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014060 app.foregroundActivities = true;
14061 }
14062 }
14063 }
14064
Dianne Hackborn7d608422011-08-07 16:24:18 -070014065 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014066 if (app.foregroundServices) {
14067 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014068 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014069 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014070 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014071 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014072 } else if (app.forcingToForeground != null) {
14073 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014074 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014075 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014076 app.adjType = "force-foreground";
14077 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014078 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014079 }
14080 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014081
Dianne Hackborn7d608422011-08-07 16:24:18 -070014082 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014083 // We don't want to kill the current heavy-weight process.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014084 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014085 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014086 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014087 app.adjType = "heavy";
14088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014089
Dianne Hackborn7d608422011-08-07 16:24:18 -070014090 if (adj > ProcessList.HOME_APP_ADJ && app == mHomeProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014091 // This process is hosting what we currently consider to be the
14092 // home app, so we don't want to let it go into the background.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014093 adj = ProcessList.HOME_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014094 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014095 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014096 app.adjType = "home";
14097 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014098
Dianne Hackbornf35fe232011-11-01 19:25:20 -070014099 if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
14100 && app.activities.size() > 0) {
14101 // This was the previous process that showed UI to the user.
14102 // We want to try to keep it around more aggressively, to give
14103 // a good experience around switching between two apps.
14104 adj = ProcessList.PREVIOUS_APP_ADJ;
14105 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
14106 app.hidden = false;
14107 app.adjType = "previous";
14108 }
14109
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014110 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
14111 + " reason=" + app.adjType);
14112
The Android Open Source Project4df24232009-03-05 14:34:35 -080014113 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014114 // there are applications dependent on our services or providers, but
14115 // this gives us a baseline and makes sure we don't get into an
14116 // infinite recursion.
14117 app.adjSeq = mAdjSeq;
14118 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119
Christopher Tate6fa95972009-06-05 18:43:55 -070014120 if (mBackupTarget != null && app == mBackupTarget.app) {
14121 // If possible we want to avoid killing apps while they're being backed up
Dianne Hackborn7d608422011-08-07 16:24:18 -070014122 if (adj > ProcessList.BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014123 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014124 adj = ProcessList.BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014125 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014126 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014127 }
14128 }
14129
Dianne Hackborn7d608422011-08-07 16:24:18 -070014130 if (app.services.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014131 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014132 final long now = SystemClock.uptimeMillis();
14133 // This process is more important if the top activity is
14134 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014135 Iterator<ServiceRecord> jt = app.services.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014136 while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014137 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014138 if (s.startRequested) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014139 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014140 // If this process has shown some UI, let it immediately
14141 // go to the LRU list because it may be pretty heavy with
14142 // UI stuff. We'll tag it with a label just to help
14143 // debug and understand what is going on.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014144 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014145 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014146 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014147 } else {
14148 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14149 // This service has seen some activity within
14150 // recent memory, so we will keep its process ahead
14151 // of the background processes.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014152 if (adj > ProcessList.SERVICE_ADJ) {
14153 adj = ProcessList.SERVICE_ADJ;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014154 app.adjType = "started-services";
14155 app.hidden = false;
14156 }
14157 }
14158 // If we have let the service slide into the background
14159 // state, still have some text describing what it is doing
14160 // even though the service no longer has an impact.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014161 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014162 app.adjType = "started-bg-services";
14163 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014164 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014165 // Don't kill this process because it is doing work; it
14166 // has said it is doing work.
14167 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014168 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014169 if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014170 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014171 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014172 = s.connections.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014173 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014174 ArrayList<ConnectionRecord> clist = kt.next();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014175 for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014176 // XXX should compute this based on the max of
14177 // all connected clients.
14178 ConnectionRecord cr = clist.get(i);
14179 if (cr.binding.client == app) {
14180 // Binding to ourself is not interesting.
14181 continue;
14182 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014183 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014184 ProcessRecord client = cr.binding.client;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014185 int clientAdj = adj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014186 int myHiddenAdj = hiddenAdj;
14187 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014188 if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014189 myHiddenAdj = client.hiddenAdj;
14190 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014191 myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014192 }
14193 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014194 clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014195 client, myHiddenAdj, TOP_APP, true, doingAll);
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014196 String adjType = null;
14197 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
14198 // Not doing bind OOM management, so treat
14199 // this guy more like a started service.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014200 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014201 // If this process has shown some UI, let it immediately
14202 // go to the LRU list because it may be pretty heavy with
14203 // UI stuff. We'll tag it with a label just to help
14204 // debug and understand what is going on.
14205 if (adj > clientAdj) {
14206 adjType = "bound-bg-ui-services";
14207 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014208 app.hidden = false;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014209 clientAdj = adj;
14210 } else {
14211 if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14212 // This service has not seen activity within
14213 // recent memory, so allow it to drop to the
14214 // LRU list if there is no other reason to keep
14215 // it around. We'll also tag it with a label just
14216 // to help debug and undertand what is going on.
14217 if (adj > clientAdj) {
14218 adjType = "bound-bg-services";
14219 }
14220 clientAdj = adj;
14221 }
14222 }
14223 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014224 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014225 // If this process has recently shown UI, and
14226 // the process that is binding to it is less
14227 // important than being visible, then we don't
14228 // care about the binding as much as we care
14229 // about letting this process get into the LRU
14230 // list to be killed and restarted if needed for
14231 // memory.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014232 if (app.hasShownUi && app != mHomeProcess
14233 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014234 adjType = "bound-bg-ui-services";
14235 } else {
14236 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
14237 |Context.BIND_IMPORTANT)) != 0) {
14238 adj = clientAdj;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070014239 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
14240 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
14241 && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
14242 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
14243 } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014244 adj = clientAdj;
14245 } else {
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070014246 app.pendingUiClean = true;
14247 if (adj > ProcessList.VISIBLE_APP_ADJ) {
14248 adj = ProcessList.VISIBLE_APP_ADJ;
14249 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014250 }
14251 if (!client.hidden) {
14252 app.hidden = false;
14253 }
14254 if (client.keeping) {
14255 app.keeping = true;
14256 }
14257 adjType = "service";
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014258 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014259 }
14260 if (adjType != null) {
14261 app.adjType = adjType;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014262 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14263 .REASON_SERVICE_IN_USE;
14264 app.adjSource = cr.binding.client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014265 app.adjSourceOom = clientAdj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014266 app.adjTarget = s.name;
14267 }
14268 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14269 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14270 schedGroup = Process.THREAD_GROUP_DEFAULT;
14271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014272 }
14273 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014274 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
14275 ActivityRecord a = cr.activity;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014276 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014277 (a.visible || a.state == ActivityState.RESUMED
14278 || a.state == ActivityState.PAUSING)) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014279 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014280 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14281 schedGroup = Process.THREAD_GROUP_DEFAULT;
14282 }
14283 app.hidden = false;
14284 app.adjType = "service";
14285 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14286 .REASON_SERVICE_IN_USE;
14287 app.adjSource = a;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014288 app.adjSourceOom = adj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014289 app.adjTarget = s.name;
14290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014292 }
14293 }
14294 }
14295 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014296
Dianne Hackborn287952c2010-09-22 22:34:31 -070014297 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014298 // would like to avoid killing it unless it would prevent the current
14299 // application from running. By default we put the process in
14300 // with the rest of the background processes; as we scan through
14301 // its services we may bump it up from there.
14302 if (adj > hiddenAdj) {
14303 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014304 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014305 app.adjType = "bg-services";
14306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014307 }
14308
Dianne Hackborn7d608422011-08-07 16:24:18 -070014309 if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014310 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014311 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014312 while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014313 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014314 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014315 if (cpr.clients.size() != 0) {
14316 Iterator<ProcessRecord> kt = cpr.clients.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014317 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014318 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014319 if (client == app) {
14320 // Being our own client is not interesting.
14321 continue;
14322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014323 int myHiddenAdj = hiddenAdj;
14324 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014325 if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014326 myHiddenAdj = client.hiddenAdj;
14327 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014328 myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014329 }
14330 }
14331 int clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014332 client, myHiddenAdj, TOP_APP, true, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014333 if (adj > clientAdj) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014334 if (app.hasShownUi && app != mHomeProcess
14335 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014336 app.adjType = "bg-ui-provider";
14337 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014338 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
14339 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014340 app.adjType = "provider";
14341 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014342 if (!client.hidden) {
14343 app.hidden = false;
14344 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014345 if (client.keeping) {
14346 app.keeping = true;
14347 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014348 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14349 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014350 app.adjSource = client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014351 app.adjSourceOom = clientAdj;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014352 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014353 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014354 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14355 schedGroup = Process.THREAD_GROUP_DEFAULT;
14356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014357 }
14358 }
14359 // If the provider has external (non-framework) process
14360 // dependencies, ensure that its adjustment is at least
14361 // FOREGROUND_APP_ADJ.
14362 if (cpr.externals != 0) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014363 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
14364 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014365 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014366 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014367 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014368 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014369 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014370 }
14371 }
14372 }
14373 }
14374
14375 app.curRawAdj = adj;
14376
Joe Onorato8a9b2202010-02-26 18:56:32 -080014377 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014378 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14379 if (adj > app.maxAdj) {
14380 adj = app.maxAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014381 if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014382 schedGroup = Process.THREAD_GROUP_DEFAULT;
14383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014384 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014385 if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014386 app.keeping = true;
14387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014388
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014389 if (app.hasAboveClient) {
14390 // If this process has bound to any services with BIND_ABOVE_CLIENT,
14391 // then we need to drop its adjustment to be lower than the service's
14392 // in order to honor the request. We want to drop it by one adjustment
14393 // level... but there is special meaning applied to various levels so
14394 // we will skip some of them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014395 if (adj < ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014396 // System process will not get dropped, ever
Dianne Hackborn7d608422011-08-07 16:24:18 -070014397 } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
14398 adj = ProcessList.VISIBLE_APP_ADJ;
14399 } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
14400 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
14401 } else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14402 adj = ProcessList.HIDDEN_APP_MIN_ADJ;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014403 } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014404 adj++;
14405 }
14406 }
14407
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014408 if (adj == ProcessList.SERVICE_ADJ) {
14409 if (doingAll) {
14410 app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
14411 mNewNumServiceProcs++;
14412 }
14413 if (app.serviceb) {
14414 adj = ProcessList.SERVICE_B_ADJ;
14415 }
14416 } else {
14417 app.serviceb = false;
14418 }
14419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014420 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014421 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014422
14423 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070014424 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
14425 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014426 }
14427
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014428 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014429 }
14430
14431 /**
14432 * Ask a given process to GC right now.
14433 */
14434 final void performAppGcLocked(ProcessRecord app) {
14435 try {
14436 app.lastRequestedGc = SystemClock.uptimeMillis();
14437 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014438 if (app.reportLowMemory) {
14439 app.reportLowMemory = false;
14440 app.thread.scheduleLowMemory();
14441 } else {
14442 app.thread.processInBackground();
14443 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014444 }
14445 } catch (Exception e) {
14446 // whatever.
14447 }
14448 }
14449
14450 /**
14451 * Returns true if things are idle enough to perform GCs.
14452 */
Josh Bartel7f208742010-02-25 11:01:44 -060014453 private final boolean canGcNowLocked() {
Christopher Tatef46723b2012-01-26 14:19:24 -080014454 boolean processingBroadcasts = false;
14455 for (BroadcastQueue q : mBroadcastQueues) {
14456 if (q.mParallelBroadcasts.size() != 0 || q.mOrderedBroadcasts.size() != 0) {
14457 processingBroadcasts = true;
14458 }
14459 }
14460 return !processingBroadcasts
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014461 && (mSleeping || (mMainStack.mResumedActivity != null &&
14462 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014463 }
14464
14465 /**
14466 * Perform GCs on all processes that are waiting for it, but only
14467 * if things are idle.
14468 */
14469 final void performAppGcsLocked() {
14470 final int N = mProcessesToGc.size();
14471 if (N <= 0) {
14472 return;
14473 }
Josh Bartel7f208742010-02-25 11:01:44 -060014474 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014475 while (mProcessesToGc.size() > 0) {
14476 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014477 if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014478 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14479 <= SystemClock.uptimeMillis()) {
14480 // To avoid spamming the system, we will GC processes one
14481 // at a time, waiting a few seconds between each.
14482 performAppGcLocked(proc);
14483 scheduleAppGcsLocked();
14484 return;
14485 } else {
14486 // It hasn't been long enough since we last GCed this
14487 // process... put it in the list to wait for its time.
14488 addProcessToGcListLocked(proc);
14489 break;
14490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014491 }
14492 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014493
14494 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014495 }
14496 }
14497
14498 /**
14499 * If all looks good, perform GCs on all processes waiting for them.
14500 */
14501 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014502 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014503 performAppGcsLocked();
14504 return;
14505 }
14506 // Still not idle, wait some more.
14507 scheduleAppGcsLocked();
14508 }
14509
14510 /**
14511 * Schedule the execution of all pending app GCs.
14512 */
14513 final void scheduleAppGcsLocked() {
14514 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014515
14516 if (mProcessesToGc.size() > 0) {
14517 // Schedule a GC for the time to the next process.
14518 ProcessRecord proc = mProcessesToGc.get(0);
14519 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14520
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014521 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014522 long now = SystemClock.uptimeMillis();
14523 if (when < (now+GC_TIMEOUT)) {
14524 when = now + GC_TIMEOUT;
14525 }
14526 mHandler.sendMessageAtTime(msg, when);
14527 }
14528 }
14529
14530 /**
14531 * Add a process to the array of processes waiting to be GCed. Keeps the
14532 * list in sorted order by the last GC time. The process can't already be
14533 * on the list.
14534 */
14535 final void addProcessToGcListLocked(ProcessRecord proc) {
14536 boolean added = false;
14537 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14538 if (mProcessesToGc.get(i).lastRequestedGc <
14539 proc.lastRequestedGc) {
14540 added = true;
14541 mProcessesToGc.add(i+1, proc);
14542 break;
14543 }
14544 }
14545 if (!added) {
14546 mProcessesToGc.add(0, proc);
14547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014548 }
14549
14550 /**
14551 * Set up to ask a process to GC itself. This will either do it
14552 * immediately, or put it on the list of processes to gc the next
14553 * time things are idle.
14554 */
14555 final void scheduleAppGcLocked(ProcessRecord app) {
14556 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014557 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014558 return;
14559 }
14560 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014561 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014562 scheduleAppGcsLocked();
14563 }
14564 }
14565
Dianne Hackborn287952c2010-09-22 22:34:31 -070014566 final void checkExcessivePowerUsageLocked(boolean doKills) {
14567 updateCpuStatsNow();
14568
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014569 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014570 boolean doWakeKills = doKills;
14571 boolean doCpuKills = doKills;
14572 if (mLastPowerCheckRealtime == 0) {
14573 doWakeKills = false;
14574 }
14575 if (mLastPowerCheckUptime == 0) {
14576 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014577 }
14578 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014579 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014580 }
14581 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014582 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
14583 final long curUptime = SystemClock.uptimeMillis();
14584 final long uptimeSince = curUptime - mLastPowerCheckUptime;
14585 mLastPowerCheckRealtime = curRealtime;
14586 mLastPowerCheckUptime = curUptime;
14587 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
14588 doWakeKills = false;
14589 }
14590 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
14591 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014592 }
14593 int i = mLruProcesses.size();
14594 while (i > 0) {
14595 i--;
14596 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014597 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014598 long wtime;
14599 synchronized (stats) {
14600 wtime = stats.getProcessWakeTime(app.info.uid,
14601 app.pid, curRealtime);
14602 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014603 long wtimeUsed = wtime - app.lastWakeTime;
14604 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
14605 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014606 StringBuilder sb = new StringBuilder(128);
14607 sb.append("Wake for ");
14608 app.toShortString(sb);
14609 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014610 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014611 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014612 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014613 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014614 sb.append((wtimeUsed*100)/realtimeSince);
14615 sb.append("%)");
14616 Slog.i(TAG, sb.toString());
14617 sb.setLength(0);
14618 sb.append("CPU for ");
14619 app.toShortString(sb);
14620 sb.append(": over ");
14621 TimeUtils.formatDuration(uptimeSince, sb);
14622 sb.append(" used ");
14623 TimeUtils.formatDuration(cputimeUsed, sb);
14624 sb.append(" (");
14625 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014626 sb.append("%)");
14627 Slog.i(TAG, sb.toString());
14628 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014629 // If a process has held a wake lock for more
14630 // than 50% of the time during this period,
14631 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070014632 if (doWakeKills && realtimeSince > 0
14633 && ((wtimeUsed*100)/realtimeSince) >= 50) {
14634 synchronized (stats) {
14635 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
14636 realtimeSince, wtimeUsed);
14637 }
14638 Slog.w(TAG, "Excessive wake lock in " + app.processName
14639 + " (pid " + app.pid + "): held " + wtimeUsed
14640 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014641 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14642 app.processName, app.setAdj, "excessive wake lock");
14643 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014644 } else if (doCpuKills && uptimeSince > 0
14645 && ((cputimeUsed*100)/uptimeSince) >= 50) {
14646 synchronized (stats) {
14647 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
14648 uptimeSince, cputimeUsed);
14649 }
14650 Slog.w(TAG, "Excessive CPU in " + app.processName
14651 + " (pid " + app.pid + "): used " + cputimeUsed
14652 + " during " + uptimeSince);
14653 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14654 app.processName, app.setAdj, "excessive cpu");
14655 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014656 } else {
14657 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014658 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014659 }
14660 }
14661 }
14662 }
14663
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014664 private final boolean updateOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014665 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014666 app.hiddenAdj = hiddenAdj;
14667
14668 if (app.thread == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014669 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014670 }
14671
Dianne Hackborn287952c2010-09-22 22:34:31 -070014672 final boolean wasKeeping = app.keeping;
14673
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014674 boolean success = true;
14675
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014676 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014677
Jeff Brown10e89712011-07-08 18:52:57 -070014678 if (app.curRawAdj != app.setRawAdj) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070014679 if (false) {
14680 // Removing for now. Forcing GCs is not so useful anymore
14681 // with Dalvik, and the new memory level hint facility is
14682 // better for what we need to do these days.
14683 if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
14684 && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
14685 // If this app is transitioning from foreground to
14686 // non-foreground, have it do a gc.
14687 scheduleAppGcLocked(app);
14688 } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14689 && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14690 // Likewise do a gc when an app is moving in to the
14691 // background (such as a service stopping).
14692 scheduleAppGcLocked(app);
14693 }
Jeff Brown10e89712011-07-08 18:52:57 -070014694 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014695
Jeff Brown10e89712011-07-08 18:52:57 -070014696 if (wasKeeping && !app.keeping) {
14697 // This app is no longer something we want to keep. Note
14698 // its current wake lock time to later know to kill it if
14699 // it is not behaving well.
14700 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
14701 synchronized (stats) {
14702 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
14703 app.pid, SystemClock.elapsedRealtime());
14704 }
14705 app.lastCpuTime = app.curCpuTime;
14706 }
14707
14708 app.setRawAdj = app.curRawAdj;
14709 }
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014710
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014711 if (app.curAdj != app.setAdj) {
14712 if (Process.setOomAdj(app.pid, app.curAdj)) {
Dianne Hackbornbbb09ac2011-11-30 11:31:29 -080014713 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014714 TAG, "Set " + app.pid + " " + app.processName +
14715 " adj " + app.curAdj + ": " + app.adjType);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014716 app.setAdj = app.curAdj;
Jeff Brown10e89712011-07-08 18:52:57 -070014717 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014718 success = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014719 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
Jeff Brown10e89712011-07-08 18:52:57 -070014720 }
14721 }
14722 if (app.setSchedGroup != app.curSchedGroup) {
14723 app.setSchedGroup = app.curSchedGroup;
14724 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
14725 "Setting process group of " + app.processName
14726 + " to " + app.curSchedGroup);
14727 if (app.waitingToKill != null &&
14728 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
14729 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
14730 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14731 app.processName, app.setAdj, app.waitingToKill);
14732 Process.killProcessQuiet(app.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014733 success = false;
Jeff Brown10e89712011-07-08 18:52:57 -070014734 } else {
14735 if (true) {
14736 long oldId = Binder.clearCallingIdentity();
14737 try {
14738 Process.setProcessGroup(app.pid, app.curSchedGroup);
14739 } catch (Exception e) {
14740 Slog.w(TAG, "Failed setting process group of " + app.pid
14741 + " to " + app.curSchedGroup);
14742 e.printStackTrace();
14743 } finally {
14744 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014745 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014746 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070014747 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014748 try {
Jeff Brown10e89712011-07-08 18:52:57 -070014749 app.thread.setSchedulingGroup(app.curSchedGroup);
14750 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014751 }
14752 }
14753 }
14754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014755 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014756 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014757 }
14758
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014759 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014760 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014761 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014762 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014763 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014764 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014765 }
14766 }
14767 return resumedActivity;
14768 }
14769
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014770 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014771 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014772 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14773 int curAdj = app.curAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014774 final boolean wasHidden = curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14775 && curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014776
14777 mAdjSeq++;
14778
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014779 boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014780 final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14781 && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014782 if (nowHidden != wasHidden) {
14783 // Changed to/from hidden state, so apps after it in the LRU
14784 // list may also be changed.
14785 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014786 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014787 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014788 }
14789
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014790 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014791 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014792 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14793
14794 if (false) {
14795 RuntimeException e = new RuntimeException();
14796 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014797 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014798 }
14799
14800 mAdjSeq++;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014801 mNewNumServiceProcs = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014802
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014803 // Let's determine how many processes we have running vs.
14804 // how many slots we have for background processes; we may want
14805 // to put multiple processes in a slot of there are enough of
14806 // them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014807 int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014808 int factor = (mLruProcesses.size()-4)/numSlots;
14809 if (factor < 1) factor = 1;
14810 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014811 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014812
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014813 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014814 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014815 int i = mLruProcesses.size();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014816 int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014817 while (i > 0) {
14818 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014819 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014820 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014821 updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
14822 if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014823 && app.curAdj == curHiddenAdj) {
14824 step++;
14825 if (step >= factor) {
14826 step = 0;
14827 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014828 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014829 }
14830 if (!app.killedBackground) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014831 if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014832 numHidden++;
14833 if (numHidden > mProcessLimit) {
14834 Slog.i(TAG, "No longer want " + app.processName
14835 + " (pid " + app.pid + "): hidden #" + numHidden);
14836 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14837 app.processName, app.setAdj, "too many background");
14838 app.killedBackground = true;
14839 Process.killProcessQuiet(app.pid);
Dianne Hackborn8633e682010-04-22 16:03:41 -070014840 }
14841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014842 }
14843 }
14844
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014845 mNumServiceProcs = mNewNumServiceProcs;
14846
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014847 // Now determine the memory trimming level of background processes.
14848 // Unfortunately we need to start at the back of the list to do this
14849 // properly. We only do this if the number of background apps we
14850 // are managing to keep around is less than half the maximum we desire;
14851 // if we are keeping a good number around, we'll let them use whatever
14852 // memory they want.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014853 if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014854 final int N = mLruProcesses.size();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014855 factor = numHidden/3;
14856 int minFactor = 2;
14857 if (mHomeProcess != null) minFactor++;
14858 if (mPreviousProcess != null) minFactor++;
14859 if (factor < minFactor) factor = minFactor;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014860 step = 0;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014861 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014862 for (i=0; i<N; i++) {
14863 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014864 if (app.curAdj >= ProcessList.HOME_APP_ADJ
14865 && app.curAdj != ProcessList.SERVICE_B_ADJ
14866 && !app.killedBackground) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014867 if (app.trimMemoryLevel < curLevel && app.thread != null) {
14868 try {
14869 app.thread.scheduleTrimMemory(curLevel);
14870 } catch (RemoteException e) {
14871 }
Dianne Hackborn77eaaf02011-12-05 18:05:31 -080014872 if (false) {
14873 // For now we won't do this; our memory trimming seems
14874 // to be good enough at this point that destroying
14875 // activities causes more harm than good.
14876 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
14877 && app != mHomeProcess && app != mPreviousProcess) {
14878 // For these apps we will also finish their activities
14879 // to help them free memory.
14880 mMainStack.destroyActivitiesLocked(app, false, "trim");
14881 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014882 }
14883 }
14884 app.trimMemoryLevel = curLevel;
14885 step++;
14886 if (step >= factor) {
14887 switch (curLevel) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014888 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
14889 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014890 break;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014891 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
14892 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014893 break;
14894 }
14895 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014896 } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014897 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014898 && app.thread != null) {
14899 try {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014900 app.thread.scheduleTrimMemory(
14901 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014902 } catch (RemoteException e) {
14903 }
14904 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014905 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014906 } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014907 && app.pendingUiClean) {
14908 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14909 && app.thread != null) {
14910 try {
14911 app.thread.scheduleTrimMemory(
14912 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14913 } catch (RemoteException e) {
14914 }
14915 }
14916 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14917 app.pendingUiClean = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014918 } else {
14919 app.trimMemoryLevel = 0;
14920 }
14921 }
14922 } else {
14923 final int N = mLruProcesses.size();
14924 for (i=0; i<N; i++) {
14925 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014926 if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014927 && app.pendingUiClean) {
14928 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14929 && app.thread != null) {
14930 try {
14931 app.thread.scheduleTrimMemory(
14932 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14933 } catch (RemoteException e) {
14934 }
14935 }
14936 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14937 app.pendingUiClean = false;
14938 } else {
14939 app.trimMemoryLevel = 0;
14940 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014941 }
14942 }
14943
14944 if (mAlwaysFinishActivities) {
Dianne Hackborn28695e02011-11-02 21:59:51 -070014945 mMainStack.destroyActivitiesLocked(null, false, "always-finish");
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014947 }
14948
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014949 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014950 synchronized (this) {
14951 int i;
14952
14953 // First remove any unused application processes whose package
14954 // has been removed.
14955 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14956 final ProcessRecord app = mRemovedProcesses.get(i);
14957 if (app.activities.size() == 0
14958 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014959 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014960 TAG, "Exiting empty application process "
14961 + app.processName + " ("
14962 + (app.thread != null ? app.thread.asBinder() : null)
14963 + ")\n");
14964 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070014965 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14966 app.processName, app.setAdj, "empty");
14967 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014968 } else {
14969 try {
14970 app.thread.scheduleExit();
14971 } catch (Exception e) {
14972 // Ignore exceptions.
14973 }
14974 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014975 cleanUpApplicationRecordLocked(app, false, true, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014976 mRemovedProcesses.remove(i);
14977
14978 if (app.persistent) {
14979 if (app.persistent) {
14980 addAppLocked(app.info);
14981 }
14982 }
14983 }
14984 }
14985
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014986 // Now update the oom adj for all processes.
14987 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014988 }
14989 }
14990
14991 /** This method sends the specified signal to each of the persistent apps */
14992 public void signalPersistentProcesses(int sig) throws RemoteException {
14993 if (sig != Process.SIGNAL_USR1) {
14994 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14995 }
14996
14997 synchronized (this) {
14998 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14999 != PackageManager.PERMISSION_GRANTED) {
15000 throw new SecurityException("Requires permission "
15001 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
15002 }
15003
Dianne Hackborndd71fc82009-12-16 19:24:32 -080015004 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
15005 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015006 if (r.thread != null && r.persistent) {
15007 Process.sendSignal(r.pid, sig);
15008 }
15009 }
15010 }
15011 }
15012
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015013 private void stopProfilerLocked(ProcessRecord proc, String path, int profileType) {
15014 if (proc == null || proc == mProfileProc) {
15015 proc = mProfileProc;
15016 path = mProfileFile;
15017 profileType = mProfileType;
15018 clearProfilerLocked();
15019 }
15020 if (proc == null) {
15021 return;
15022 }
15023 try {
15024 proc.thread.profilerControl(false, path, null, profileType);
15025 } catch (RemoteException e) {
15026 throw new IllegalStateException("Process disappeared");
15027 }
15028 }
15029
15030 private void clearProfilerLocked() {
15031 if (mProfileFd != null) {
15032 try {
15033 mProfileFd.close();
15034 } catch (IOException e) {
15035 }
15036 }
15037 mProfileApp = null;
15038 mProfileProc = null;
15039 mProfileFile = null;
15040 mProfileType = 0;
15041 mAutoStopProfiler = false;
15042 }
15043
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015044 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070015045 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015046
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015047 try {
15048 synchronized (this) {
15049 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
15050 // its own permission.
15051 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
15052 != PackageManager.PERMISSION_GRANTED) {
15053 throw new SecurityException("Requires permission "
15054 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015055 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015056
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015057 if (start && fd == null) {
15058 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015059 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015060
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015061 ProcessRecord proc = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015062 if (process != null) {
15063 try {
15064 int pid = Integer.parseInt(process);
15065 synchronized (mPidsSelfLocked) {
15066 proc = mPidsSelfLocked.get(pid);
15067 }
15068 } catch (NumberFormatException e) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015069 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015070
15071 if (proc == null) {
15072 HashMap<String, SparseArray<ProcessRecord>> all
15073 = mProcessNames.getMap();
15074 SparseArray<ProcessRecord> procs = all.get(process);
15075 if (procs != null && procs.size() > 0) {
15076 proc = procs.valueAt(0);
15077 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015078 }
15079 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015080
15081 if (start && (proc == null || proc.thread == null)) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015082 throw new IllegalArgumentException("Unknown process: " + process);
15083 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015084
15085 if (start) {
15086 stopProfilerLocked(null, null, 0);
15087 setProfileApp(proc.info, proc.processName, path, fd, false);
15088 mProfileProc = proc;
15089 mProfileType = profileType;
15090 try {
15091 fd = fd.dup();
15092 } catch (IOException e) {
15093 fd = null;
15094 }
15095 proc.thread.profilerControl(start, path, fd, profileType);
15096 fd = null;
15097 mProfileFd = null;
15098 } else {
15099 stopProfilerLocked(proc, path, profileType);
15100 if (fd != null) {
15101 try {
15102 fd.close();
15103 } catch (IOException e) {
15104 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015105 }
15106 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015107
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015108 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015109 }
15110 } catch (RemoteException e) {
15111 throw new IllegalStateException("Process disappeared");
15112 } finally {
15113 if (fd != null) {
15114 try {
15115 fd.close();
15116 } catch (IOException e) {
15117 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015118 }
15119 }
15120 }
Andy McFadden824c5102010-07-09 16:26:57 -070015121
15122 public boolean dumpHeap(String process, boolean managed,
15123 String path, ParcelFileDescriptor fd) throws RemoteException {
15124
15125 try {
15126 synchronized (this) {
15127 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
15128 // its own permission (same as profileControl).
15129 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
15130 != PackageManager.PERMISSION_GRANTED) {
15131 throw new SecurityException("Requires permission "
15132 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
15133 }
15134
15135 if (fd == null) {
15136 throw new IllegalArgumentException("null fd");
15137 }
15138
15139 ProcessRecord proc = null;
15140 try {
15141 int pid = Integer.parseInt(process);
15142 synchronized (mPidsSelfLocked) {
15143 proc = mPidsSelfLocked.get(pid);
15144 }
15145 } catch (NumberFormatException e) {
15146 }
15147
15148 if (proc == null) {
15149 HashMap<String, SparseArray<ProcessRecord>> all
15150 = mProcessNames.getMap();
15151 SparseArray<ProcessRecord> procs = all.get(process);
15152 if (procs != null && procs.size() > 0) {
15153 proc = procs.valueAt(0);
15154 }
15155 }
15156
15157 if (proc == null || proc.thread == null) {
15158 throw new IllegalArgumentException("Unknown process: " + process);
15159 }
15160
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080015161 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
15162 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070015163 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
15164 throw new SecurityException("Process not debuggable: " + proc);
15165 }
15166 }
15167
15168 proc.thread.dumpHeap(managed, path, fd);
15169 fd = null;
15170 return true;
15171 }
15172 } catch (RemoteException e) {
15173 throw new IllegalStateException("Process disappeared");
15174 } finally {
15175 if (fd != null) {
15176 try {
15177 fd.close();
15178 } catch (IOException e) {
15179 }
15180 }
15181 }
15182 }
15183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015184 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
15185 public void monitor() {
15186 synchronized (this) { }
15187 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080015188
15189 public void onCoreSettingsChange(Bundle settings) {
15190 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
15191 ProcessRecord processRecord = mLruProcesses.get(i);
15192 try {
15193 if (processRecord.thread != null) {
15194 processRecord.thread.setCoreSettings(settings);
15195 }
15196 } catch (RemoteException re) {
15197 /* ignore */
15198 }
15199 }
15200 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070015201
15202 // Multi-user methods
15203
Amith Yamasani742a6712011-05-04 14:49:28 -070015204 private int mCurrentUserId;
15205 private SparseIntArray mLoggedInUsers = new SparseIntArray(5);
15206
15207 public boolean switchUser(int userId) {
15208 final int callingUid = Binder.getCallingUid();
15209 if (callingUid != 0 && callingUid != Process.myUid()) {
15210 Slog.e(TAG, "Trying to switch user from unauthorized app");
15211 return false;
15212 }
15213 if (mCurrentUserId == userId)
15214 return true;
15215
15216 synchronized (this) {
15217 // Check if user is already logged in, otherwise check if user exists first before
15218 // adding to the list of logged in users.
15219 if (mLoggedInUsers.indexOfKey(userId) < 0) {
15220 if (!userExists(userId)) {
15221 return false;
15222 }
15223 mLoggedInUsers.append(userId, userId);
15224 }
15225
15226 mCurrentUserId = userId;
15227 boolean haveActivities = mMainStack.switchUser(userId);
15228 if (!haveActivities) {
15229 startHomeActivityLocked(userId);
15230 }
15231 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070015232 return true;
15233 }
Amith Yamasani742a6712011-05-04 14:49:28 -070015234
15235 private boolean userExists(int userId) {
15236 try {
15237 List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
15238 for (UserInfo user : users) {
15239 if (user.id == userId) {
15240 return true;
15241 }
15242 }
15243 } catch (RemoteException re) {
15244 // Won't happen, in same process
15245 }
15246
15247 return false;
15248 }
15249
15250
15251 private int applyUserId(int uid, int userId) {
15252 return UserId.getUid(userId, uid);
15253 }
15254
15255 private ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
15256 ApplicationInfo newInfo = new ApplicationInfo(info);
15257 newInfo.uid = applyUserId(info.uid, userId);
15258 if (newInfo.uid >= Process.FIRST_APPLICATION_UID) {
15259 newInfo.dataDir = USER_DATA_DIR + userId + "/"
15260 + info.packageName;
15261 }
15262 return newInfo;
15263 }
15264
15265 ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) {
15266 if (aInfo.applicationInfo.uid < Process.FIRST_APPLICATION_UID
15267 || userId < 1) {
15268 return aInfo;
15269 }
15270
15271 ActivityInfo info = new ActivityInfo(aInfo);
15272 info.applicationInfo = getAppInfoForUser(info.applicationInfo, userId);
15273 return info;
15274 }
15275
15276 static class ServiceMap {
15277
15278 private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
15279 = new SparseArray<HashMap<ComponentName, ServiceRecord>>();
15280 private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
15281 mServicesByIntentPerUser = new SparseArray<
15282 HashMap<Intent.FilterComparison, ServiceRecord>>();
15283
15284 ServiceRecord getServiceByName(ComponentName name, int callingUser) {
15285 // TODO: Deal with global services
15286 if (DEBUG_MU)
15287 Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
15288 return getServices(callingUser).get(name);
15289 }
15290
15291 ServiceRecord getServiceByName(ComponentName name) {
15292 return getServiceByName(name, -1);
15293 }
15294
15295 ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
15296 // TODO: Deal with global services
15297 if (DEBUG_MU)
15298 Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
15299 return getServicesByIntent(callingUser).get(filter);
15300 }
15301
15302 ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
15303 return getServiceByIntent(filter, -1);
15304 }
15305
15306 void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
15307 // TODO: Deal with global services
15308 getServices(callingUser).put(name, value);
15309 }
15310
15311 void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
15312 ServiceRecord value) {
15313 // TODO: Deal with global services
15314 getServicesByIntent(callingUser).put(filter, value);
15315 }
15316
15317 void removeServiceByName(ComponentName name, int callingUser) {
15318 // TODO: Deal with global services
15319 ServiceRecord removed = getServices(callingUser).remove(name);
15320 if (DEBUG_MU)
15321 Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
15322 + " removed=" + removed);
15323 }
15324
15325 void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
15326 // TODO: Deal with global services
15327 ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
15328 if (DEBUG_MU)
15329 Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
15330 + " removed=" + removed);
15331 }
15332
15333 Collection<ServiceRecord> getAllServices(int callingUser) {
15334 // TODO: Deal with global services
15335 return getServices(callingUser).values();
15336 }
15337
15338 private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
15339 HashMap map = mServicesByNamePerUser.get(callingUser);
15340 if (map == null) {
15341 map = new HashMap<ComponentName, ServiceRecord>();
15342 mServicesByNamePerUser.put(callingUser, map);
15343 }
15344 return map;
15345 }
15346
15347 private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
15348 int callingUser) {
15349 HashMap map = mServicesByIntentPerUser.get(callingUser);
15350 if (map == null) {
15351 map = new HashMap<Intent.FilterComparison, ServiceRecord>();
15352 mServicesByIntentPerUser.put(callingUser, map);
15353 }
15354 return map;
15355 }
15356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015357}