blob: 3a6a3de8f2990fd91c8e82dc47c454d48e8fd87f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackborn45ce8642011-07-14 16:10:16 -070021import com.android.internal.os.ProcessStats;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
Jeff Sharkeya4620792011-05-20 15:29:23 -070045import android.app.IProcessObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.IServiceConnection;
47import android.app.IThumbnailReceiver;
48import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070049import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070050import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070056import android.content.ComponentCallbacks2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.ComponentName;
58import android.content.ContentResolver;
59import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020060import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040079import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.content.res.Configuration;
81import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070082import android.net.Proxy;
83import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.net.Uri;
85import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080087import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070088import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080089import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080091import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.FileUtils;
93import android.os.Handler;
94import android.os.IBinder;
95import android.os.IPermissionController;
96import android.os.Looper;
97import android.os.Message;
98import android.os.Parcel;
99import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700101import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.RemoteException;
103import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700104import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.SystemClock;
106import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.util.EventLog;
Dianne Hackborn905577f2011-09-07 18:31:28 -0700109import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800110import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800111import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.util.PrintWriterPrinter;
113import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700114import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import android.view.Gravity;
116import android.view.LayoutInflater;
117import android.view.View;
118import android.view.WindowManager;
119import android.view.WindowManagerPolicy;
120
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700121import java.io.BufferedInputStream;
122import java.io.BufferedOutputStream;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700123import java.io.BufferedReader;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.DataInputStream;
125import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.io.File;
127import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700130import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200131import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800132import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.io.PrintWriter;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700134import java.io.StringWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.lang.IllegalStateException;
136import java.lang.ref.WeakReference;
137import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700138import java.util.Collections;
139import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140import java.util.HashMap;
141import java.util.HashSet;
142import java.util.Iterator;
143import java.util.List;
144import java.util.Locale;
145import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700146import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700147import java.util.concurrent.atomic.AtomicBoolean;
148import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700150public final class ActivityManagerService extends ActivityManagerNative
151 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final String TAG = "ActivityManager";
153 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400154 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_SWITCH = localLOGV || false;
156 static final boolean DEBUG_TASKS = localLOGV || false;
157 static final boolean DEBUG_PAUSE = localLOGV || false;
158 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
159 static final boolean DEBUG_TRANSITION = localLOGV || false;
160 static final boolean DEBUG_BROADCAST = localLOGV || false;
Christopher Tatef46723b2012-01-26 14:19:24 -0800161 static final boolean DEBUG_BACKGROUND_BROADCAST = DEBUG_BROADCAST || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700162 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700164 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 static final boolean DEBUG_VISBILITY = localLOGV || false;
166 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700167 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800168 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700170 static final boolean DEBUG_RESULTS = localLOGV || false;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -0700171 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700172 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700173 static final boolean DEBUG_POWER = localLOGV || false;
174 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 static final boolean VALIDATE_TOKENS = false;
176 static final boolean SHOW_ACTIVITY_START_TIME = true;
177
178 // Control over CPU and battery monitoring.
179 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
180 static final boolean MONITOR_CPU_USAGE = true;
181 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
182 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
183 static final boolean MONITOR_THREAD_CPU_USAGE = false;
184
Dianne Hackborn1655be42009-05-08 14:29:01 -0700185 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700186 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700187
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800188 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // Maximum number of recent tasks that we can remember.
191 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700192
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700193 // Amount of time after a call to stopAppSwitches() during which we will
194 // prevent further untrusted switches from happening.
195 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196
197 // How long we wait for a launched process to attach to the activity manager
198 // before we decide it's never going to come up for real.
199 static final int PROC_START_TIMEOUT = 10*1000;
200
Jeff Brown3f9dd282011-07-08 20:02:19 -0700201 // How long we wait for a launched process to attach to the activity manager
202 // before we decide it's never going to come up for real, when the process was
203 // started with a wrapper for instrumentation (such as Valgrind) because it
204 // could take much longer than usual.
205 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 // How long to wait after going idle before forcing apps to GC.
208 static final int GC_TIMEOUT = 5*1000;
209
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700210 // The minimum amount of time between successive GC requests for a process.
211 static final int GC_MIN_INTERVAL = 60*1000;
212
Dianne Hackborn287952c2010-09-22 22:34:31 -0700213 // The rate at which we check for apps using excessive power -- 15 mins.
214 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
215
216 // The minimum sample duration we will allow before deciding we have
217 // enough data on wake locks to start killing things.
218 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
219
220 // The minimum sample duration we will allow before deciding we have
221 // enough data on CPU usage to start killing things.
222 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 // How long we allow a receiver to run before giving up on it.
Christopher Tatef46723b2012-01-26 14:19:24 -0800225 static final int BROADCAST_FG_TIMEOUT = 10*1000;
226 static final int BROADCAST_BG_TIMEOUT = 60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227
228 // How long we wait for a service to finish executing.
229 static final int SERVICE_TIMEOUT = 20*1000;
230
231 // How long a service needs to be running until restarting its process
232 // is no longer considered to be a relaunch of the service.
233 static final int SERVICE_RESTART_DURATION = 5*1000;
234
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700235 // How long a service needs to be running until it will start back at
236 // SERVICE_RESTART_DURATION after being killed.
237 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
238
239 // Multiplying factor to increase restart duration time by, for each time
240 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
241 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
242
243 // The minimum amount of time between restarting services that we allow.
244 // That is, when multiple services are restarting, we won't allow each
245 // to restart less than this amount of time from the last one.
246 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 // Maximum amount of time for there to be no activity on a service before
249 // we consider it non-essential and allow its process to go on the
250 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700251 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // How long we wait until we timeout on key dispatching.
254 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 // How long we wait until we timeout on key dispatching during instrumentation.
257 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
258
Dan Egnor42471dd2010-01-07 17:25:22 -0800259 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
261 static final String[] EMPTY_STRING_ARRAY = new String[0];
262
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700263 public ActivityStack mMainStack;
264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700266 * Description of a request to start a new activity, which has been held
267 * due to app switches being disabled.
268 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700269 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700270 ActivityRecord r;
271 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700272 Uri[] grantedUriPermissions;
273 int grantedMode;
274 boolean onlyIfNeeded;
275 }
276
277 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
278 = new ArrayList<PendingActivityLaunch>();
279
280 /**
Christopher Tatef46723b2012-01-26 14:19:24 -0800281 * BROADCASTS
282 *
283 * We keep two broadcast queues and associated bookkeeping, one for those at
284 * foreground priority, and one for normal (background-priority) broadcasts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 */
Christopher Tatef46723b2012-01-26 14:19:24 -0800286 public class BroadcastQueue {
287 static final String TAG = "BroadcastQueue";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
Christopher Tatef46723b2012-01-26 14:19:24 -0800289 static final int MAX_BROADCAST_HISTORY = 25;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
Christopher Tatef46723b2012-01-26 14:19:24 -0800291 /**
292 * Recognizable moniker for this queue
293 */
294 String mQueueName;
Dianne Hackborn12527f92009-11-11 17:39:50 -0800295
Christopher Tatef46723b2012-01-26 14:19:24 -0800296 /**
297 * Timeout period for this queue's broadcasts
298 */
299 long mTimeoutPeriod;
300
301 /**
302 * Lists of all active broadcasts that are to be executed immediately
303 * (without waiting for another broadcast to finish). Currently this only
304 * contains broadcasts to registered receivers, to avoid spinning up
305 * a bunch of processes to execute IntentReceiver components. Background-
306 * and foreground-priority broadcasts are queued separately.
307 */
308 final ArrayList<BroadcastRecord> mParallelBroadcasts
309 = new ArrayList<BroadcastRecord>();
310 /**
311 * List of all active broadcasts that are to be executed one at a time.
312 * The object at the top of the list is the currently activity broadcasts;
313 * those after it are waiting for the top to finish. As with parallel
314 * broadcasts, separate background- and foreground-priority queues are
315 * maintained.
316 */
317 final ArrayList<BroadcastRecord> mOrderedBroadcasts
318 = new ArrayList<BroadcastRecord>();
319
320 /**
321 * Historical data of past broadcasts, for debugging.
322 */
323 final BroadcastRecord[] mBroadcastHistory
324 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
325
326 /**
327 * Set when we current have a BROADCAST_INTENT_MSG in flight.
328 */
329 boolean mBroadcastsScheduled = false;
330
331 /**
332 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
333 */
334 boolean mPendingBroadcastTimeoutMessage;
335
336 /**
337 * Intent broadcasts that we have tried to start, but are
338 * waiting for the application's process to be created. We only
339 * need one per scheduling class (instead of a list) because we always
340 * process broadcasts one at a time, so no others can be started while
341 * waiting for this one.
342 */
343 BroadcastRecord mPendingBroadcast = null;
344
345 /**
346 * The receiver index that is pending, to restart the broadcast if needed.
347 */
348 int mPendingBroadcastRecvIndex;
349
350 BroadcastQueue(String name, long timeoutPeriod) {
351 mQueueName = name;
352 mTimeoutPeriod = timeoutPeriod;
353 }
354
355 public boolean isPendingBroadcastProcessLocked(int pid) {
356 return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
357 }
358
359 public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
360 mParallelBroadcasts.add(r);
361 }
362
363 public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
364 mOrderedBroadcasts.add(r);
365 }
366
367 public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
368 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
369 if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
370 if (DEBUG_BROADCAST) Slog.v(TAG,
371 "***** DROPPING PARALLEL ["
372 + mQueueName + "]: " + r.intent);
373 mParallelBroadcasts.set(i, r);
374 return true;
375 }
376 }
377 return false;
378 }
379
380 public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
381 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
382 if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
383 if (DEBUG_BROADCAST) Slog.v(TAG,
384 "***** DROPPING ORDERED ["
385 + mQueueName + "]: " + r.intent);
386 mOrderedBroadcasts.set(i, r);
387 return true;
388 }
389 }
390 return false;
391 }
392
393 public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
394 boolean didSomething = false;
395 final BroadcastRecord br = mPendingBroadcast;
396 if (br != null && br.curApp.pid == app.pid) {
397 try {
398 mPendingBroadcast = null;
399 processCurBroadcastLocked(br, app);
400 didSomething = true;
401 } catch (Exception e) {
402 Slog.w(TAG, "Exception in new application when starting receiver "
403 + br.curComponent.flattenToShortString(), e);
404 logBroadcastReceiverDiscardLocked(br);
405 finishReceiverLocked(br, br.resultCode, br.resultData,
406 br.resultExtras, br.resultAbort, true);
407 scheduleBroadcastsLocked();
408 // We need to reset the state if we fails to start the receiver.
409 br.state = BroadcastRecord.IDLE;
410 throw new RuntimeException(e.getMessage());
411 }
412 }
413 return didSomething;
414 }
415
416 public void skipPendingBroadcastLocked(int pid) {
417 final BroadcastRecord br = mPendingBroadcast;
418 if (br != null && br.curApp.pid == pid) {
419 br.state = BroadcastRecord.IDLE;
420 br.nextReceiver = mPendingBroadcastRecvIndex;
421 mPendingBroadcast = null;
422 scheduleBroadcastsLocked();
423 }
424 }
425
426 public void skipCurrentReceiverLocked(ProcessRecord app) {
427 boolean reschedule = false;
428 BroadcastRecord r = app.curReceiver;
429 if (r != null) {
430 // The current broadcast is waiting for this app's receiver
431 // to be finished. Looks like that's not going to happen, so
432 // let the broadcast continue.
433 logBroadcastReceiverDiscardLocked(r);
434 finishReceiverLocked(r, r.resultCode, r.resultData,
435 r.resultExtras, r.resultAbort, true);
436 reschedule = true;
437 }
438
439 r = mPendingBroadcast;
440 if (r != null && r.curApp == app) {
441 if (DEBUG_BROADCAST) Slog.v(TAG,
442 "[" + mQueueName + "] skip & discard pending app " + r);
443 logBroadcastReceiverDiscardLocked(r);
444 finishReceiverLocked(r, r.resultCode, r.resultData,
445 r.resultExtras, r.resultAbort, true);
446 reschedule = true;
447 }
448 if (reschedule) {
449 scheduleBroadcastsLocked();
450 }
451 }
452
453 public void scheduleBroadcastsLocked() {
454 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
455 + mQueueName + "]: current="
456 + mBroadcastsScheduled);
457
458 if (mBroadcastsScheduled) {
459 return;
460 }
461 mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
462 mBroadcastsScheduled = true;
463 }
464
465 public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
466 if (mOrderedBroadcasts.size() > 0) {
467 final BroadcastRecord r = mOrderedBroadcasts.get(0);
468 if (r != null && r.receiver == receiver) {
469 return r;
470 }
471 }
472 return null;
473 }
474
475 public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
476 String resultData, Bundle resultExtras, boolean resultAbort,
477 boolean explicit) {
478 int state = r.state;
479 r.state = BroadcastRecord.IDLE;
480 if (state == BroadcastRecord.IDLE) {
481 if (explicit) {
482 Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
483 }
484 }
485 r.receiver = null;
486 r.intent.setComponent(null);
487 if (r.curApp != null) {
488 r.curApp.curReceiver = null;
489 }
490 if (r.curFilter != null) {
491 r.curFilter.receiverList.curBroadcast = null;
492 }
493 r.curFilter = null;
494 r.curApp = null;
495 r.curComponent = null;
496 r.curReceiver = null;
497 mPendingBroadcast = null;
498
499 r.resultCode = resultCode;
500 r.resultData = resultData;
501 r.resultExtras = resultExtras;
502 r.resultAbort = resultAbort;
503
504 // We will process the next receiver right now if this is finishing
505 // an app receiver (which is always asynchronous) or after we have
506 // come back from calling a receiver.
507 return state == BroadcastRecord.APP_RECEIVE
508 || state == BroadcastRecord.CALL_DONE_RECEIVE;
509 }
510
511 private final void processNextBroadcast(boolean fromMsg) {
512 synchronized(ActivityManagerService.this) {
513 BroadcastRecord r;
514
515 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
516 + mQueueName + "]: "
517 + mParallelBroadcasts.size() + " broadcasts, "
518 + mOrderedBroadcasts.size() + " ordered broadcasts");
519
520 updateCpuStats();
521
522 if (fromMsg) {
523 mBroadcastsScheduled = false;
524 }
525
526 // First, deliver any non-serialized broadcasts right away.
527 while (mParallelBroadcasts.size() > 0) {
528 r = mParallelBroadcasts.remove(0);
529 r.dispatchTime = SystemClock.uptimeMillis();
530 r.dispatchClockTime = System.currentTimeMillis();
531 final int N = r.receivers.size();
532 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["
533 + mQueueName + "] " + r);
534 for (int i=0; i<N; i++) {
535 Object target = r.receivers.get(i);
536 if (DEBUG_BROADCAST) Slog.v(TAG,
537 "Delivering non-ordered on [" + mQueueName + "] to registered "
538 + target + ": " + r);
539 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
540 }
541 addBroadcastToHistoryLocked(r);
542 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
543 + mQueueName + "] " + r);
544 }
545
546 // Now take care of the next serialized one...
547
548 // If we are waiting for a process to come up to handle the next
549 // broadcast, then do nothing at this point. Just in case, we
550 // check that the process we're waiting for still exists.
551 if (mPendingBroadcast != null) {
552 if (DEBUG_BROADCAST_LIGHT) {
553 Slog.v(TAG, "processNextBroadcast ["
554 + mQueueName + "]: waiting for "
555 + mPendingBroadcast.curApp);
556 }
557
558 boolean isDead;
559 synchronized (mPidsSelfLocked) {
560 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
561 }
562 if (!isDead) {
563 // It's still alive, so keep waiting
564 return;
565 } else {
566 Slog.w(TAG, "pending app ["
567 + mQueueName + "]" + mPendingBroadcast.curApp
568 + " died before responding to broadcast");
569 mPendingBroadcast.state = BroadcastRecord.IDLE;
570 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
571 mPendingBroadcast = null;
572 }
573 }
574
575 boolean looped = false;
576
577 do {
578 if (mOrderedBroadcasts.size() == 0) {
579 // No more broadcasts pending, so all done!
580 scheduleAppGcsLocked();
581 if (looped) {
582 // If we had finished the last ordered broadcast, then
583 // make sure all processes have correct oom and sched
584 // adjustments.
585 updateOomAdjLocked();
586 }
587 return;
588 }
589 r = mOrderedBroadcasts.get(0);
590 boolean forceReceive = false;
591
592 // Ensure that even if something goes awry with the timeout
593 // detection, we catch "hung" broadcasts here, discard them,
594 // and continue to make progress.
595 //
596 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
597 // receivers don't get executed with timeouts. They're intended for
598 // one time heavy lifting after system upgrades and can take
599 // significant amounts of time.
600 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
601 if (mProcessesReady && r.dispatchTime > 0) {
602 long now = SystemClock.uptimeMillis();
603 if ((numReceivers > 0) &&
604 (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
605 Slog.w(TAG, "Hung broadcast ["
606 + mQueueName + "] discarded after timeout failure:"
607 + " now=" + now
608 + " dispatchTime=" + r.dispatchTime
609 + " startTime=" + r.receiverTime
610 + " intent=" + r.intent
611 + " numReceivers=" + numReceivers
612 + " nextReceiver=" + r.nextReceiver
613 + " state=" + r.state);
614 broadcastTimeoutLocked(false); // forcibly finish this broadcast
615 forceReceive = true;
616 r.state = BroadcastRecord.IDLE;
617 }
618 }
619
620 if (r.state != BroadcastRecord.IDLE) {
621 if (DEBUG_BROADCAST) Slog.d(TAG,
622 "processNextBroadcast("
623 + mQueueName + ") called when not idle (state="
624 + r.state + ")");
625 return;
626 }
627
628 if (r.receivers == null || r.nextReceiver >= numReceivers
629 || r.resultAbort || forceReceive) {
630 // No more receivers for this broadcast! Send the final
631 // result if requested...
632 if (r.resultTo != null) {
633 try {
634 if (DEBUG_BROADCAST) {
635 int seq = r.intent.getIntExtra("seq", -1);
636 Slog.i(TAG, "Finishing broadcast ["
637 + mQueueName + "] " + r.intent.getAction()
638 + " seq=" + seq + " app=" + r.callerApp);
639 }
640 performReceiveLocked(r.callerApp, r.resultTo,
641 new Intent(r.intent), r.resultCode,
642 r.resultData, r.resultExtras, false, false);
643 // Set this to null so that the reference
644 // (local and remote) isnt kept in the mBroadcastHistory.
645 r.resultTo = null;
646 } catch (RemoteException e) {
647 Slog.w(TAG, "Failure ["
648 + mQueueName + "] sending broadcast result of "
649 + r.intent, e);
650 }
651 }
652
653 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
654 cancelBroadcastTimeoutLocked();
655
656 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
657 + r);
658
659 // ... and on to the next...
660 addBroadcastToHistoryLocked(r);
661 mOrderedBroadcasts.remove(0);
662 r = null;
663 looped = true;
664 continue;
665 }
666 } while (r == null);
667
668 // Get the next receiver...
669 int recIdx = r.nextReceiver++;
670
671 // Keep track of when this receiver started, and make sure there
672 // is a timeout message pending to kill it if need be.
673 r.receiverTime = SystemClock.uptimeMillis();
674 if (recIdx == 0) {
675 r.dispatchTime = r.receiverTime;
676 r.dispatchClockTime = System.currentTimeMillis();
677 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["
678 + mQueueName + "] " + r);
679 }
680 if (! mPendingBroadcastTimeoutMessage) {
681 long timeoutTime = r.receiverTime + mTimeoutPeriod;
682 if (DEBUG_BROADCAST) Slog.v(TAG,
683 "Submitting BROADCAST_TIMEOUT_MSG ["
684 + mQueueName + "] for " + r + " at " + timeoutTime);
685 setBroadcastTimeoutLocked(timeoutTime);
686 }
687
688 Object nextReceiver = r.receivers.get(recIdx);
689 if (nextReceiver instanceof BroadcastFilter) {
690 // Simple case: this is a registered receiver who gets
691 // a direct call.
692 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
693 if (DEBUG_BROADCAST) Slog.v(TAG,
694 "Delivering ordered ["
695 + mQueueName + "] to registered "
696 + filter + ": " + r);
697 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
698 if (r.receiver == null || !r.ordered) {
699 // The receiver has already finished, so schedule to
700 // process the next one.
701 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["
702 + mQueueName + "]: ordered="
703 + r.ordered + " receiver=" + r.receiver);
704 r.state = BroadcastRecord.IDLE;
705 scheduleBroadcastsLocked();
706 }
707 return;
708 }
709
710 // Hard case: need to instantiate the receiver, possibly
711 // starting its application process to host it.
712
713 ResolveInfo info =
714 (ResolveInfo)nextReceiver;
715
716 boolean skip = false;
717 int perm = checkComponentPermission(info.activityInfo.permission,
718 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
719 info.activityInfo.exported);
720 if (perm != PackageManager.PERMISSION_GRANTED) {
721 if (!info.activityInfo.exported) {
722 Slog.w(TAG, "Permission Denial: broadcasting "
723 + r.intent.toString()
724 + " from " + r.callerPackage + " (pid=" + r.callingPid
725 + ", uid=" + r.callingUid + ")"
726 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
727 + " due to receiver " + info.activityInfo.packageName
728 + "/" + info.activityInfo.name);
729 } else {
730 Slog.w(TAG, "Permission Denial: broadcasting "
731 + r.intent.toString()
732 + " from " + r.callerPackage + " (pid=" + r.callingPid
733 + ", uid=" + r.callingUid + ")"
734 + " requires " + info.activityInfo.permission
735 + " due to receiver " + info.activityInfo.packageName
736 + "/" + info.activityInfo.name);
737 }
738 skip = true;
739 }
740 if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
741 r.requiredPermission != null) {
742 try {
743 perm = AppGlobals.getPackageManager().
744 checkPermission(r.requiredPermission,
745 info.activityInfo.applicationInfo.packageName);
746 } catch (RemoteException e) {
747 perm = PackageManager.PERMISSION_DENIED;
748 }
749 if (perm != PackageManager.PERMISSION_GRANTED) {
750 Slog.w(TAG, "Permission Denial: receiving "
751 + r.intent + " to "
752 + info.activityInfo.applicationInfo.packageName
753 + " requires " + r.requiredPermission
754 + " due to sender " + r.callerPackage
755 + " (uid " + r.callingUid + ")");
756 skip = true;
757 }
758 }
759 if (r.curApp != null && r.curApp.crashing) {
760 // If the target process is crashing, just skip it.
761 if (DEBUG_BROADCAST) Slog.v(TAG,
762 "Skipping deliver ordered ["
763 + mQueueName + "] " + r + " to " + r.curApp
764 + ": process crashing");
765 skip = true;
766 }
767
768 if (skip) {
769 if (DEBUG_BROADCAST) Slog.v(TAG,
770 "Skipping delivery of ordered ["
771 + mQueueName + "] " + r + " for whatever reason");
772 r.receiver = null;
773 r.curFilter = null;
774 r.state = BroadcastRecord.IDLE;
775 scheduleBroadcastsLocked();
776 return;
777 }
778
779 r.state = BroadcastRecord.APP_RECEIVE;
780 String targetProcess = info.activityInfo.processName;
781 r.curComponent = new ComponentName(
782 info.activityInfo.applicationInfo.packageName,
783 info.activityInfo.name);
784 r.curReceiver = info.activityInfo;
785
786 // Broadcast is being executed, its package can't be stopped.
787 try {
788 AppGlobals.getPackageManager().setPackageStoppedState(
789 r.curComponent.getPackageName(), false);
790 } catch (RemoteException e) {
791 } catch (IllegalArgumentException e) {
792 Slog.w(TAG, "Failed trying to unstop package "
793 + r.curComponent.getPackageName() + ": " + e);
794 }
795
796 // Is this receiver's application already running?
797 ProcessRecord app = getProcessRecordLocked(targetProcess,
798 info.activityInfo.applicationInfo.uid);
799 if (app != null && app.thread != null) {
800 try {
801 app.addPackage(info.activityInfo.packageName);
802 processCurBroadcastLocked(r, app);
803 return;
804 } catch (RemoteException e) {
805 Slog.w(TAG, "Exception when sending broadcast to "
806 + r.curComponent, e);
807 }
808
809 // If a dead object exception was thrown -- fall through to
810 // restart the application.
811 }
812
813 // Not running -- get it started, to be executed when the app comes up.
814 if (DEBUG_BROADCAST) Slog.v(TAG,
815 "Need to start app ["
816 + mQueueName + "] " + targetProcess + " for broadcast " + r);
817 if ((r.curApp=startProcessLocked(targetProcess,
818 info.activityInfo.applicationInfo, true,
819 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
820 "broadcast", r.curComponent,
821 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
822 == null) {
823 // Ah, this recipient is unavailable. Finish it if necessary,
824 // and mark the broadcast record as ready for the next.
825 Slog.w(TAG, "Unable to launch app "
826 + info.activityInfo.applicationInfo.packageName + "/"
827 + info.activityInfo.applicationInfo.uid + " for broadcast "
828 + r.intent + ": process is bad");
829 logBroadcastReceiverDiscardLocked(r);
830 finishReceiverLocked(r, r.resultCode, r.resultData,
831 r.resultExtras, r.resultAbort, true);
832 scheduleBroadcastsLocked();
833 r.state = BroadcastRecord.IDLE;
834 return;
835 }
836
837 mPendingBroadcast = r;
838 mPendingBroadcastRecvIndex = recIdx;
839 }
840 }
841
842 final void setBroadcastTimeoutLocked(long timeoutTime) {
843 if (! mPendingBroadcastTimeoutMessage) {
844 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
845 mHandler.sendMessageAtTime(msg, timeoutTime);
846 mPendingBroadcastTimeoutMessage = true;
847 }
848 }
849
850 final void cancelBroadcastTimeoutLocked() {
851 if (mPendingBroadcastTimeoutMessage) {
852 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
853 mPendingBroadcastTimeoutMessage = false;
854 }
855 }
856
857 final void broadcastTimeoutLocked(boolean fromMsg) {
858 if (fromMsg) {
859 mPendingBroadcastTimeoutMessage = false;
860 }
861
862 if (mOrderedBroadcasts.size() == 0) {
863 return;
864 }
865
866 long now = SystemClock.uptimeMillis();
867 BroadcastRecord r = mOrderedBroadcasts.get(0);
868 if (fromMsg) {
869 if (mDidDexOpt) {
870 // Delay timeouts until dexopt finishes.
871 mDidDexOpt = false;
872 long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
873 setBroadcastTimeoutLocked(timeoutTime);
874 return;
875 }
876 if (! mProcessesReady) {
877 // Only process broadcast timeouts if the system is ready. That way
878 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
879 // to do heavy lifting for system up.
880 return;
881 }
882
883 long timeoutTime = r.receiverTime + mTimeoutPeriod;
884 if (timeoutTime > now) {
885 // We can observe premature timeouts because we do not cancel and reset the
886 // broadcast timeout message after each receiver finishes. Instead, we set up
887 // an initial timeout then kick it down the road a little further as needed
888 // when it expires.
889 if (DEBUG_BROADCAST) Slog.v(TAG,
890 "Premature timeout ["
891 + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
892 + timeoutTime);
893 setBroadcastTimeoutLocked(timeoutTime);
894 return;
895 }
896 }
897
898 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
899 + ", started " + (now - r.receiverTime) + "ms ago");
900 r.receiverTime = now;
901 r.anrCount++;
902
903 // Current receiver has passed its expiration date.
904 if (r.nextReceiver <= 0) {
905 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
906 return;
907 }
908
909 ProcessRecord app = null;
910 String anrMessage = null;
911
912 Object curReceiver = r.receivers.get(r.nextReceiver-1);
913 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
914 logBroadcastReceiverDiscardLocked(r);
915 if (curReceiver instanceof BroadcastFilter) {
916 BroadcastFilter bf = (BroadcastFilter)curReceiver;
917 if (bf.receiverList.pid != 0
918 && bf.receiverList.pid != MY_PID) {
919 synchronized (ActivityManagerService.this.mPidsSelfLocked) {
920 app = ActivityManagerService.this.mPidsSelfLocked.get(
921 bf.receiverList.pid);
922 }
923 }
924 } else {
925 app = r.curApp;
926 }
927
928 if (app != null) {
929 anrMessage = "Broadcast of " + r.intent.toString();
930 }
931
932 if (mPendingBroadcast == r) {
933 mPendingBroadcast = null;
934 }
935
936 // Move on to the next receiver.
937 finishReceiverLocked(r, r.resultCode, r.resultData,
938 r.resultExtras, r.resultAbort, true);
939 scheduleBroadcastsLocked();
940
941 if (anrMessage != null) {
942 // Post the ANR to the handler since we do not want to process ANRs while
943 // potentially holding our lock.
944 mHandler.post(new AppNotResponding(app, anrMessage));
945 }
946 }
947
948 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
949 if (r.callingUid < 0) {
950 // This was from a registerReceiver() call; ignore it.
951 return;
952 }
953 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
954 MAX_BROADCAST_HISTORY-1);
955 r.finishTime = SystemClock.uptimeMillis();
956 mBroadcastHistory[0] = r;
957 }
958
959 final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
960 if (r.nextReceiver > 0) {
961 Object curReceiver = r.receivers.get(r.nextReceiver-1);
962 if (curReceiver instanceof BroadcastFilter) {
963 BroadcastFilter bf = (BroadcastFilter) curReceiver;
964 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
965 System.identityHashCode(r),
966 r.intent.getAction(),
967 r.nextReceiver - 1,
968 System.identityHashCode(bf));
969 } else {
970 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
971 System.identityHashCode(r),
972 r.intent.getAction(),
973 r.nextReceiver - 1,
974 ((ResolveInfo)curReceiver).toString());
975 }
976 } else {
977 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
978 + r);
979 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
980 System.identityHashCode(r),
981 r.intent.getAction(),
982 r.nextReceiver,
983 "NONE");
984 }
985 }
986
987 final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
988 int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
989 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
990 || mPendingBroadcast != null) {
991 boolean printed = false;
992 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
993 BroadcastRecord br = mParallelBroadcasts.get(i);
994 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
995 continue;
996 }
997 if (!printed) {
998 if (needSep) {
999 pw.println();
1000 needSep = false;
1001 }
1002 printed = true;
1003 pw.println(" Active broadcasts [" + mQueueName + "]:");
1004 }
1005 pw.println(" Broadcast #" + i + ":");
1006 br.dump(pw, " ");
1007 }
1008 printed = false;
1009 needSep = true;
1010 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
1011 BroadcastRecord br = mOrderedBroadcasts.get(i);
1012 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
1013 continue;
1014 }
1015 if (!printed) {
1016 if (needSep) {
1017 pw.println();
1018 }
1019 needSep = true;
1020 pw.println(" Active ordered broadcasts [" + mQueueName + "]:");
1021 }
1022 pw.println(" Ordered Broadcast #" + i + ":");
1023 mOrderedBroadcasts.get(i).dump(pw, " ");
1024 }
1025 if (dumpPackage == null || (mPendingBroadcast != null
1026 && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
1027 if (needSep) {
1028 pw.println();
1029 }
1030 pw.println(" Pending broadcast [" + mQueueName + "]:");
1031 if (mPendingBroadcast != null) {
1032 mPendingBroadcast.dump(pw, " ");
1033 } else {
1034 pw.println(" (null)");
1035 }
1036 needSep = true;
1037 }
1038 }
1039
1040 boolean printed = false;
1041 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
1042 BroadcastRecord r = mBroadcastHistory[i];
1043 if (r == null) {
1044 break;
1045 }
1046 if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
1047 continue;
1048 }
1049 if (!printed) {
1050 if (needSep) {
1051 pw.println();
1052 }
1053 needSep = true;
1054 pw.println(" Historical broadcasts [" + mQueueName + "]:");
1055 printed = true;
1056 }
1057 if (dumpAll) {
1058 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
1059 r.dump(pw, " ");
1060 } else {
1061 if (i >= 50) {
1062 pw.println(" ...");
1063 break;
1064 }
1065 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
1066 }
1067 }
1068
1069 return needSep;
1070 }
1071 }
1072
1073 final BroadcastQueue mFgBroadcastQueue = new BroadcastQueue("foreground", BROADCAST_FG_TIMEOUT);
1074 final BroadcastQueue mBgBroadcastQueue = new BroadcastQueue("background", BROADCAST_BG_TIMEOUT);
1075 // Convenient for easy iteration over the queues. Foreground is first
1076 // so that dispatch of foreground broadcasts gets precedence.
1077 final BroadcastQueue[] mBroadcastQueues = { mFgBroadcastQueue, mBgBroadcastQueue };
1078
1079 BroadcastQueue broadcastQueueForIntent(Intent intent) {
1080 final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
1081 if (DEBUG_BACKGROUND_BROADCAST) {
1082 Slog.i(TAG, "Broadcast intent " + intent + " on "
1083 + (isFg ? "foreground" : "background")
1084 + " queue");
1085 }
1086 return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
1087 }
1088
1089 BroadcastRecord broadcastRecordForReceiverLocked(IBinder receiver) {
1090 for (BroadcastQueue queue : mBroadcastQueues) {
1091 BroadcastRecord r = queue.getMatchingOrderedReceiver(receiver);
1092 if (r != null) {
1093 return r;
1094 }
1095 }
1096 return null;
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098
1099 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 * Activity we have told the window manager to have key focus.
1101 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001102 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001103 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 * List of intents that were used to start the most recent tasks.
1105 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001106 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107
1108 /**
Dianne Hackborn7d608422011-08-07 16:24:18 -07001109 * Process management.
1110 */
1111 final ProcessList mProcessList = new ProcessList();
1112
1113 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 * All of the applications we currently have running organized by name.
1115 * The keys are strings of the application package name (as
1116 * returned by the package manager), and the keys are ApplicationRecord
1117 * objects.
1118 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001119 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120
1121 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -07001122 * The currently running heavy-weight process, if any.
1123 */
1124 ProcessRecord mHeavyWeightProcess = null;
1125
1126 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 * The last time that various processes have crashed.
1128 */
1129 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
1130
1131 /**
1132 * Set of applications that we consider to be bad, and will reject
1133 * incoming broadcasts from (which the user has no control over).
1134 * Processes are added to this set when they have crashed twice within
1135 * a minimum amount of time; they are removed from it when they are
1136 * later restarted (hopefully due to some user action). The value is the
1137 * time it was added to the list.
1138 */
1139 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
1140
1141 /**
1142 * All of the processes we currently have running organized by pid.
1143 * The keys are the pid running the application.
1144 *
1145 * <p>NOTE: This object is protected by its own lock, NOT the global
1146 * activity manager lock!
1147 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001148 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149
1150 /**
1151 * All of the processes that have been forced to be foreground. The key
1152 * is the pid of the caller who requested it (we hold a death
1153 * link on it).
1154 */
1155 abstract class ForegroundToken implements IBinder.DeathRecipient {
1156 int pid;
1157 IBinder token;
1158 }
1159 final SparseArray<ForegroundToken> mForegroundProcesses
1160 = new SparseArray<ForegroundToken>();
1161
1162 /**
1163 * List of records for processes that someone had tried to start before the
1164 * system was ready. We don't start them at that point, but ensure they
1165 * are started by the time booting is complete.
1166 */
1167 final ArrayList<ProcessRecord> mProcessesOnHold
1168 = new ArrayList<ProcessRecord>();
1169
1170 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 * List of persistent applications that are in the process
1172 * of being started.
1173 */
1174 final ArrayList<ProcessRecord> mPersistentStartingProcesses
1175 = new ArrayList<ProcessRecord>();
1176
1177 /**
1178 * Processes that are being forcibly torn down.
1179 */
1180 final ArrayList<ProcessRecord> mRemovedProcesses
1181 = new ArrayList<ProcessRecord>();
1182
1183 /**
1184 * List of running applications, sorted by recent usage.
1185 * The first entry in the list is the least recently used.
1186 * It contains ApplicationRecord objects. This list does NOT include
1187 * any persistent application records (since we never want to exit them).
1188 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001189 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 = new ArrayList<ProcessRecord>();
1191
1192 /**
1193 * List of processes that should gc as soon as things are idle.
1194 */
1195 final ArrayList<ProcessRecord> mProcessesToGc
1196 = new ArrayList<ProcessRecord>();
1197
1198 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001199 * This is the process holding what we currently consider to be
1200 * the "home" activity.
1201 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001202 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001203
1204 /**
Dianne Hackbornf35fe232011-11-01 19:25:20 -07001205 * This is the process holding the activity the user last visited that
1206 * is in a different process from the one they are currently in.
1207 */
1208 ProcessRecord mPreviousProcess;
Dianne Hackborn50685602011-12-01 12:23:37 -08001209
1210 /**
1211 * The time at which the previous process was last visible.
1212 */
1213 long mPreviousProcessVisibleTime;
1214
Dianne Hackbornf35fe232011-11-01 19:25:20 -07001215 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001216 * Packages that the user has asked to have run in screen size
1217 * compatibility mode instead of filling the screen.
1218 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001219 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001220
1221 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 * Set of PendingResultRecord objects that are currently active.
1223 */
1224 final HashSet mPendingResultRecords = new HashSet();
1225
1226 /**
1227 * Set of IntentSenderRecord objects that are currently active.
1228 */
1229 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
1230 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
1231
1232 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001233 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07001234 * already logged DropBox entries for. Guarded by itself. If
1235 * something (rogue user app) forces this over
1236 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
1237 */
1238 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
1239 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
1240
1241 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07001242 * Strict Mode background batched logging state.
1243 *
1244 * The string buffer is guarded by itself, and its lock is also
1245 * used to determine if another batched write is already
1246 * in-flight.
1247 */
1248 private final StringBuilder mStrictModeBuffer = new StringBuilder();
1249
1250 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 * Keeps track of all IIntentReceivers that have been registered for
1252 * broadcasts. Hash keys are the receiver IBinder, hash value is
1253 * a ReceiverList.
1254 */
1255 final HashMap mRegisteredReceivers = new HashMap();
1256
1257 /**
1258 * Resolver for broadcast intents to registered receivers.
1259 * Holds BroadcastFilter (subclass of IntentFilter).
1260 */
1261 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
1262 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
1263 @Override
1264 protected boolean allowFilterResult(
1265 BroadcastFilter filter, List<BroadcastFilter> dest) {
1266 IBinder target = filter.receiverList.receiver.asBinder();
1267 for (int i=dest.size()-1; i>=0; i--) {
1268 if (dest.get(i).receiverList.receiver.asBinder() == target) {
1269 return false;
1270 }
1271 }
1272 return true;
1273 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001274
1275 @Override
1276 protected String packageForFilter(BroadcastFilter filter) {
1277 return filter.packageName;
1278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 };
1280
1281 /**
1282 * State of all active sticky broadcasts. Keys are the action of the
1283 * sticky Intent, values are an ArrayList of all broadcasted intents with
1284 * that action (which should usually be one).
1285 */
1286 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
1287 new HashMap<String, ArrayList<Intent>>();
1288
1289 /**
1290 * All currently running services.
1291 */
1292 final HashMap<ComponentName, ServiceRecord> mServices =
1293 new HashMap<ComponentName, ServiceRecord>();
1294
1295 /**
1296 * All currently running services indexed by the Intent used to start them.
1297 */
1298 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
1299 new HashMap<Intent.FilterComparison, ServiceRecord>();
1300
1301 /**
1302 * All currently bound service connections. Keys are the IBinder of
1303 * the client's IServiceConnection.
1304 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07001305 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
1306 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307
1308 /**
1309 * List of services that we have been asked to start,
1310 * but haven't yet been able to. It is used to hold start requests
1311 * while waiting for their corresponding application thread to get
1312 * going.
1313 */
1314 final ArrayList<ServiceRecord> mPendingServices
1315 = new ArrayList<ServiceRecord>();
1316
1317 /**
1318 * List of services that are scheduled to restart following a crash.
1319 */
1320 final ArrayList<ServiceRecord> mRestartingServices
1321 = new ArrayList<ServiceRecord>();
1322
1323 /**
1324 * List of services that are in the process of being stopped.
1325 */
1326 final ArrayList<ServiceRecord> mStoppingServices
1327 = new ArrayList<ServiceRecord>();
1328
1329 /**
Christopher Tate181fafa2009-05-14 11:12:14 -07001330 * Backup/restore process management
1331 */
1332 String mBackupAppName = null;
1333 BackupRecord mBackupTarget = null;
1334
1335 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 * List of PendingThumbnailsRecord objects of clients who are still
1337 * waiting to receive all of the thumbnails for a task.
1338 */
1339 final ArrayList mPendingThumbnails = new ArrayList();
1340
1341 /**
1342 * List of HistoryRecord objects that have been finished and must
1343 * still report back to a pending thumbnail receiver.
1344 */
1345 final ArrayList mCancelledThumbnails = new ArrayList();
1346
1347 /**
1348 * All of the currently running global content providers. Keys are a
1349 * string containing the provider name and values are a
1350 * ContentProviderRecord object containing the data about it. Note
1351 * that a single provider may be published under multiple names, so
1352 * there may be multiple entries here for a single one in mProvidersByClass.
1353 */
Dianne Hackborn860755f2010-06-03 18:47:52 -07001354 final HashMap<String, ContentProviderRecord> mProvidersByName
1355 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356
1357 /**
1358 * All of the currently running global content providers. Keys are a
1359 * string containing the provider's implementation class and values are a
1360 * ContentProviderRecord object containing the data about it.
1361 */
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07001362 final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
1363 = new HashMap<ComponentName, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364
1365 /**
1366 * List of content providers who have clients waiting for them. The
1367 * application is currently being launched and the provider will be
1368 * removed from this list once it is published.
1369 */
Dianne Hackborn860755f2010-06-03 18:47:52 -07001370 final ArrayList<ContentProviderRecord> mLaunchingProviders
1371 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372
1373 /**
1374 * Global set of specific Uri permissions that have been granted.
1375 */
1376 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
1377 = new SparseArray<HashMap<Uri, UriPermission>>();
1378
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08001379 CoreSettingsObserver mCoreSettingsObserver;
1380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 /**
1382 * Thread-local storage used to carry caller permissions over through
1383 * indirect content-provider access.
1384 * @see #ActivityManagerService.openContentUri()
1385 */
1386 private class Identity {
1387 public int pid;
1388 public int uid;
1389
1390 Identity(int _pid, int _uid) {
1391 pid = _pid;
1392 uid = _uid;
1393 }
1394 }
1395 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
1396
1397 /**
1398 * All information we have collected about the runtime performance of
1399 * any user id that can impact battery performance.
1400 */
1401 final BatteryStatsService mBatteryStatsService;
1402
1403 /**
1404 * information about component usage
1405 */
1406 final UsageStatsService mUsageStatsService;
1407
1408 /**
1409 * Current configuration information. HistoryRecord objects are given
1410 * a reference to this object to indicate which configuration they are
1411 * currently running in, so this object must be kept immutable.
1412 */
1413 Configuration mConfiguration = new Configuration();
1414
1415 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001416 * Current sequencing integer of the configuration, for skipping old
1417 * configurations.
1418 */
1419 int mConfigurationSeq = 0;
1420
1421 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -07001422 * Hardware-reported OpenGLES version.
1423 */
1424 final int GL_ES_VERSION;
1425
1426 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 * List of initialization arguments to pass to all processes when binding applications to them.
1428 * For example, references to the commonly used services.
1429 */
1430 HashMap<String, IBinder> mAppBindArgs;
1431
1432 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001433 * Temporary to avoid allocations. Protected by main lock.
1434 */
1435 final StringBuilder mStringBuilder = new StringBuilder(256);
1436
1437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 * Used to control how we initialize the service.
1439 */
1440 boolean mStartRunning = false;
1441 ComponentName mTopComponent;
1442 String mTopAction;
1443 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001444 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 boolean mSystemReady = false;
1446 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001447 boolean mWaitingUpdate = false;
1448 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001449 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001450 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451
1452 Context mContext;
1453
1454 int mFactoryTest;
1455
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001456 boolean mCheckedForSetup;
1457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001459 * The time at which we will allow normal application switches again,
1460 * after a call to {@link #stopAppSwitches()}.
1461 */
1462 long mAppSwitchesAllowedTime;
1463
1464 /**
1465 * This is set to true after the first switch after mAppSwitchesAllowedTime
1466 * is set; any switches after that will clear the time.
1467 */
1468 boolean mDidAppSwitch;
1469
1470 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -07001471 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001472 */
Dianne Hackborn287952c2010-09-22 22:34:31 -07001473 long mLastPowerCheckRealtime;
1474
1475 /**
1476 * Last time (in uptime) at which we checked for power usage.
1477 */
1478 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001479
1480 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 * Set while we are wanting to sleep, to prevent any
1482 * activities from being started/resumed.
1483 */
1484 boolean mSleeping = false;
1485
1486 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -07001487 * Set if we are shutting down the system, similar to sleeping.
1488 */
1489 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490
1491 /**
1492 * Task identifier that activities are currently being started
1493 * in. Incremented each time a new task is created.
1494 * todo: Replace this with a TokenSpace class that generates non-repeating
1495 * integers that won't wrap.
1496 */
1497 int mCurTask = 1;
1498
1499 /**
1500 * Current sequence id for oom_adj computation traversal.
1501 */
1502 int mAdjSeq = 0;
1503
1504 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -07001505 * Current sequence id for process LRU updating.
1506 */
1507 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508
1509 /**
Dianne Hackborne02c88a2011-10-28 13:58:15 -07001510 * Keep track of the number of service processes we last found, to
1511 * determine on the next iteration which should be B services.
1512 */
1513 int mNumServiceProcs = 0;
1514 int mNewNumServiceProcs = 0;
1515
1516 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 * System monitoring: number of processes that died since the last
1518 * N procs were started.
1519 */
1520 int[] mProcDeaths = new int[20];
1521
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001522 /**
1523 * This is set if we had to do a delayed dexopt of an app before launching
1524 * it, to increasing the ANR timeouts in that case.
1525 */
1526 boolean mDidDexOpt;
1527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 String mDebugApp = null;
1529 boolean mWaitForDebugger = false;
1530 boolean mDebugTransient = false;
1531 String mOrigDebugApp = null;
1532 boolean mOrigWaitForDebugger = false;
1533 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001534 IActivityController mController = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07001535 String mProfileApp = null;
1536 ProcessRecord mProfileProc = null;
1537 String mProfileFile;
1538 ParcelFileDescriptor mProfileFd;
1539 int mProfileType = 0;
1540 boolean mAutoStopProfiler = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001542 final RemoteCallbackList<IActivityWatcher> mWatchers
1543 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -07001544
1545 final RemoteCallbackList<IProcessObserver> mProcessObservers
1546 = new RemoteCallbackList<IProcessObserver>();
1547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 /**
1549 * Callback of last caller to {@link #requestPss}.
1550 */
1551 Runnable mRequestPssCallback;
1552
1553 /**
1554 * Remaining processes for which we are waiting results from the last
1555 * call to {@link #requestPss}.
1556 */
1557 final ArrayList<ProcessRecord> mRequestPssList
1558 = new ArrayList<ProcessRecord>();
1559
1560 /**
1561 * Runtime statistics collection thread. This object's lock is used to
1562 * protect all related state.
1563 */
1564 final Thread mProcessStatsThread;
1565
1566 /**
1567 * Used to collect process stats when showing not responding dialog.
1568 * Protected by mProcessStatsThread.
1569 */
1570 final ProcessStats mProcessStats = new ProcessStats(
1571 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001572 final AtomicLong mLastCpuTime = new AtomicLong(0);
1573 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
1574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 long mLastWriteTime = 0;
1576
1577 /**
1578 * Set to true after the system has finished booting.
1579 */
1580 boolean mBooted = false;
1581
Dianne Hackborn7d608422011-08-07 16:24:18 -07001582 int mProcessLimit = ProcessList.MAX_HIDDEN_APPS;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001583 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584
1585 WindowManagerService mWindowManager;
1586
1587 static ActivityManagerService mSelf;
1588 static ActivityThread mSystemThread;
1589
1590 private final class AppDeathRecipient implements IBinder.DeathRecipient {
1591 final ProcessRecord mApp;
1592 final int mPid;
1593 final IApplicationThread mAppThread;
1594
1595 AppDeathRecipient(ProcessRecord app, int pid,
1596 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001597 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 TAG, "New death recipient " + this
1599 + " for thread " + thread.asBinder());
1600 mApp = app;
1601 mPid = pid;
1602 mAppThread = thread;
1603 }
1604
1605 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 TAG, "Death received in " + this
1608 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 synchronized(ActivityManagerService.this) {
1610 appDiedLocked(mApp, mPid, mAppThread);
1611 }
1612 }
1613 }
1614
1615 static final int SHOW_ERROR_MSG = 1;
1616 static final int SHOW_NOT_RESPONDING_MSG = 2;
1617 static final int SHOW_FACTORY_ERROR_MSG = 3;
1618 static final int UPDATE_CONFIGURATION_MSG = 4;
1619 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1620 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1621 static final int BROADCAST_INTENT_MSG = 7;
1622 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 static final int SERVICE_TIMEOUT_MSG = 12;
1624 static final int UPDATE_TIME_ZONE = 13;
1625 static final int SHOW_UID_ERROR_MSG = 14;
1626 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001628 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001629 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001630 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001631 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1632 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001633 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001634 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001635 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001636 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001637 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001638 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
1639 static final int DISPATCH_PROCESS_DIED = 32;
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001640 static final int REPORT_MEM_USAGE = 33;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641
1642 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001643 CompatModeDialog mCompatModeDialog;
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001644 long mLastMemUsageReportTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645
1646 final Handler mHandler = new Handler() {
1647 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001648 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 //}
1650
1651 public void handleMessage(Message msg) {
1652 switch (msg.what) {
1653 case SHOW_ERROR_MSG: {
1654 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 synchronized (ActivityManagerService.this) {
1656 ProcessRecord proc = (ProcessRecord)data.get("app");
1657 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001658 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 return;
1660 }
1661 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001662 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001663 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 d.show();
1665 proc.crashDialog = d;
1666 } else {
1667 // The device is asleep, so just pretend that the user
1668 // saw a crash dialog and hit "force quit".
1669 res.set(0);
1670 }
1671 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001672
1673 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 } break;
1675 case SHOW_NOT_RESPONDING_MSG: {
1676 synchronized (ActivityManagerService.this) {
1677 HashMap data = (HashMap) msg.obj;
1678 ProcessRecord proc = (ProcessRecord)data.get("app");
1679 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001680 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 return;
1682 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001683
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001684 Intent intent = new Intent("android.intent.action.ANR");
1685 if (!mProcessesReady) {
Christopher Tatef46723b2012-01-26 14:19:24 -08001686 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1687 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001688 }
1689 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001690 null, null, 0, null, null, null,
1691 false, false, MY_PID, Process.SYSTEM_UID);
1692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001694 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 d.show();
1696 proc.anrDialog = d;
1697 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001698
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001699 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001701 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1702 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1703 synchronized (ActivityManagerService.this) {
1704 ProcessRecord proc = (ProcessRecord) data.get("app");
1705 if (proc == null) {
1706 Slog.e(TAG, "App not found when showing strict mode dialog.");
1707 break;
1708 }
1709 if (proc.crashDialog != null) {
1710 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1711 return;
1712 }
1713 AppErrorResult res = (AppErrorResult) data.get("result");
1714 if (!mSleeping && !mShuttingDown) {
1715 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1716 d.show();
1717 proc.crashDialog = d;
1718 } else {
1719 // The device is asleep, so just pretend that the user
1720 // saw a crash dialog and hit "force quit".
1721 res.set(0);
1722 }
1723 }
1724 ensureBootCompleted();
1725 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 case SHOW_FACTORY_ERROR_MSG: {
1727 Dialog d = new FactoryErrorDialog(
1728 mContext, msg.getData().getCharSequence("msg"));
1729 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001730 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 } break;
1732 case UPDATE_CONFIGURATION_MSG: {
1733 final ContentResolver resolver = mContext.getContentResolver();
1734 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1735 } break;
1736 case GC_BACKGROUND_PROCESSES_MSG: {
1737 synchronized (ActivityManagerService.this) {
1738 performAppGcsIfAppropriateLocked();
1739 }
1740 } break;
1741 case WAIT_FOR_DEBUGGER_MSG: {
1742 synchronized (ActivityManagerService.this) {
1743 ProcessRecord app = (ProcessRecord)msg.obj;
1744 if (msg.arg1 != 0) {
1745 if (!app.waitedForDebugger) {
1746 Dialog d = new AppWaitingForDebuggerDialog(
1747 ActivityManagerService.this,
1748 mContext, app);
1749 app.waitDialog = d;
1750 app.waitedForDebugger = true;
1751 d.show();
1752 }
1753 } else {
1754 if (app.waitDialog != null) {
1755 app.waitDialog.dismiss();
1756 app.waitDialog = null;
1757 }
1758 }
1759 }
1760 } break;
1761 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001762 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 TAG, "Received BROADCAST_INTENT_MSG");
Christopher Tatef46723b2012-01-26 14:19:24 -08001764 BroadcastQueue queue = (BroadcastQueue) msg.obj;
1765 queue.processNextBroadcast(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 } break;
1767 case BROADCAST_TIMEOUT_MSG: {
Christopher Tatef46723b2012-01-26 14:19:24 -08001768 final BroadcastQueue queue = (BroadcastQueue) msg.obj;
Jeff Brown4d94a762010-09-23 11:33:28 -07001769 synchronized (ActivityManagerService.this) {
Christopher Tatef46723b2012-01-26 14:19:24 -08001770 queue.broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001771 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001774 if (mDidDexOpt) {
1775 mDidDexOpt = false;
1776 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1777 nmsg.obj = msg.obj;
1778 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1779 return;
1780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 serviceTimeout((ProcessRecord)msg.obj);
1782 } break;
1783 case UPDATE_TIME_ZONE: {
1784 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001785 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1786 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 if (r.thread != null) {
1788 try {
1789 r.thread.updateTimeZone();
1790 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001791 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 }
1793 }
1794 }
1795 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001796 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001797 case CLEAR_DNS_CACHE: {
1798 synchronized (ActivityManagerService.this) {
1799 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1800 ProcessRecord r = mLruProcesses.get(i);
1801 if (r.thread != null) {
1802 try {
1803 r.thread.clearDnsCache();
1804 } catch (RemoteException ex) {
1805 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1806 }
1807 }
1808 }
1809 }
1810 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001811 case UPDATE_HTTP_PROXY: {
1812 ProxyProperties proxy = (ProxyProperties)msg.obj;
1813 String host = "";
1814 String port = "";
1815 String exclList = "";
1816 if (proxy != null) {
1817 host = proxy.getHost();
1818 port = Integer.toString(proxy.getPort());
1819 exclList = proxy.getExclusionList();
1820 }
1821 synchronized (ActivityManagerService.this) {
1822 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1823 ProcessRecord r = mLruProcesses.get(i);
1824 if (r.thread != null) {
1825 try {
1826 r.thread.setHttpProxy(host, port, exclList);
1827 } catch (RemoteException ex) {
1828 Slog.w(TAG, "Failed to update http proxy for: " +
1829 r.info.processName);
1830 }
1831 }
1832 }
1833 }
1834 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 case SHOW_UID_ERROR_MSG: {
1836 // XXX This is a temporary dialog, no need to localize.
1837 AlertDialog d = new BaseErrorDialog(mContext);
1838 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1839 d.setCancelable(false);
1840 d.setTitle("System UIDs Inconsistent");
1841 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 +02001842 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1844 mUidAlert = d;
1845 d.show();
1846 } break;
1847 case IM_FEELING_LUCKY_MSG: {
1848 if (mUidAlert != null) {
1849 mUidAlert.dismiss();
1850 mUidAlert = null;
1851 }
1852 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001854 if (mDidDexOpt) {
1855 mDidDexOpt = false;
1856 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1857 nmsg.obj = msg.obj;
1858 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1859 return;
1860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 ProcessRecord app = (ProcessRecord)msg.obj;
1862 synchronized (ActivityManagerService.this) {
1863 processStartTimedOutLocked(app);
1864 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001865 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001866 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1867 synchronized (ActivityManagerService.this) {
1868 doPendingActivityLaunchesLocked(true);
1869 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001870 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001871 case KILL_APPLICATION_MSG: {
1872 synchronized (ActivityManagerService.this) {
1873 int uid = msg.arg1;
1874 boolean restart = (msg.arg2 == 1);
1875 String pkg = (String) msg.obj;
Christopher Tate3dacd842011-08-19 14:56:15 -07001876 forceStopPackageLocked(pkg, uid, restart, false, true, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001877 }
1878 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001879 case FINALIZE_PENDING_INTENT_MSG: {
1880 ((PendingIntentRecord)msg.obj).completeFinalize();
1881 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001882 case POST_HEAVY_NOTIFICATION_MSG: {
1883 INotificationManager inm = NotificationManager.getService();
1884 if (inm == null) {
1885 return;
1886 }
1887
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001888 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001889 ProcessRecord process = root.app;
1890 if (process == null) {
1891 return;
1892 }
1893
1894 try {
1895 Context context = mContext.createPackageContext(process.info.packageName, 0);
1896 String text = mContext.getString(R.string.heavy_weight_notification,
1897 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1898 Notification notification = new Notification();
1899 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1900 notification.when = 0;
1901 notification.flags = Notification.FLAG_ONGOING_EVENT;
1902 notification.tickerText = text;
1903 notification.defaults = 0; // please be quiet
1904 notification.sound = null;
1905 notification.vibrate = null;
1906 notification.setLatestEventInfo(context, text,
1907 mContext.getText(R.string.heavy_weight_notification_detail),
1908 PendingIntent.getActivity(mContext, 0, root.intent,
1909 PendingIntent.FLAG_CANCEL_CURRENT));
1910
1911 try {
1912 int[] outId = new int[1];
1913 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1914 notification, outId);
1915 } catch (RuntimeException e) {
1916 Slog.w(ActivityManagerService.TAG,
1917 "Error showing notification for heavy-weight app", e);
1918 } catch (RemoteException e) {
1919 }
1920 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001921 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001922 }
1923 } break;
1924 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1925 INotificationManager inm = NotificationManager.getService();
1926 if (inm == null) {
1927 return;
1928 }
1929 try {
1930 inm.cancelNotification("android",
1931 R.string.heavy_weight_notification);
1932 } catch (RuntimeException e) {
1933 Slog.w(ActivityManagerService.TAG,
1934 "Error canceling notification for service", e);
1935 } catch (RemoteException e) {
1936 }
1937 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001938 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1939 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001940 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001941 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001942 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1943 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001944 }
1945 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001946 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1947 synchronized (ActivityManagerService.this) {
1948 ActivityRecord ar = (ActivityRecord)msg.obj;
1949 if (mCompatModeDialog != null) {
1950 if (mCompatModeDialog.mAppInfo.packageName.equals(
1951 ar.info.applicationInfo.packageName)) {
1952 return;
1953 }
1954 mCompatModeDialog.dismiss();
1955 mCompatModeDialog = null;
1956 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001957 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001958 if (mCompatModePackages.getPackageAskCompatModeLocked(
1959 ar.packageName)) {
1960 int mode = mCompatModePackages.computeCompatModeLocked(
1961 ar.info.applicationInfo);
1962 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1963 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1964 mCompatModeDialog = new CompatModeDialog(
1965 ActivityManagerService.this, mContext,
1966 ar.info.applicationInfo);
1967 mCompatModeDialog.show();
1968 }
1969 }
1970 }
1971 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001972 break;
1973 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001974 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001975 final int pid = msg.arg1;
1976 final int uid = msg.arg2;
1977 final boolean foregroundActivities = (Boolean) msg.obj;
1978 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001979 break;
1980 }
1981 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001982 final int pid = msg.arg1;
1983 final int uid = msg.arg2;
1984 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001985 break;
1986 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001987 case REPORT_MEM_USAGE: {
1988 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
1989 if (!isDebuggable) {
1990 return;
1991 }
1992 synchronized (ActivityManagerService.this) {
1993 long now = SystemClock.uptimeMillis();
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001994 if (now < (mLastMemUsageReportTime+5*60*1000)) {
1995 // Don't report more than every 5 minutes to somewhat
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001996 // avoid spamming.
1997 return;
1998 }
1999 mLastMemUsageReportTime = now;
2000 }
2001 Thread thread = new Thread() {
2002 @Override public void run() {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002003 StringBuilder dropBuilder = new StringBuilder(1024);
2004 StringBuilder logBuilder = new StringBuilder(1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -08002005 StringWriter oomSw = new StringWriter();
2006 PrintWriter oomPw = new PrintWriter(oomSw);
2007 StringWriter catSw = new StringWriter();
2008 PrintWriter catPw = new PrintWriter(catSw);
2009 String[] emptyArgs = new String[] { };
2010 StringBuilder tag = new StringBuilder(128);
2011 StringBuilder stack = new StringBuilder(128);
2012 tag.append("Low on memory -- ");
2013 dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw,
2014 tag, stack);
2015 dropBuilder.append(stack);
2016 dropBuilder.append('\n');
2017 dropBuilder.append('\n');
2018 String oomString = oomSw.toString();
2019 dropBuilder.append(oomString);
2020 dropBuilder.append('\n');
2021 logBuilder.append(oomString);
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002022 try {
2023 java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
2024 "procrank", });
2025 final InputStreamReader converter = new InputStreamReader(
2026 proc.getInputStream());
2027 BufferedReader in = new BufferedReader(converter);
2028 String line;
2029 while (true) {
2030 line = in.readLine();
2031 if (line == null) {
2032 break;
2033 }
2034 if (line.length() > 0) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002035 logBuilder.append(line);
2036 logBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002037 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002038 dropBuilder.append(line);
2039 dropBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002040 }
2041 converter.close();
2042 } catch (IOException e) {
2043 }
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002044 synchronized (ActivityManagerService.this) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08002045 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002046 dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002047 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002048 dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002049 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002050 dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08002051 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002052 dropBuilder.append(catSw.toString());
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08002053 addErrorToDropBox("lowmem", null, "system_server", null,
2054 null, tag.toString(), dropBuilder.toString(), null, null);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08002055 Slog.i(TAG, logBuilder.toString());
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002056 synchronized (ActivityManagerService.this) {
2057 long now = SystemClock.uptimeMillis();
2058 if (mLastMemUsageReportTime < now) {
2059 mLastMemUsageReportTime = now;
2060 }
2061 }
2062 }
2063 };
2064 thread.start();
2065 break;
2066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 }
2068 }
2069 };
2070
2071 public static void setSystemProcess() {
2072 try {
2073 ActivityManagerService m = mSelf;
2074
2075 ServiceManager.addService("activity", m);
2076 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07002077 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
Jeff Brown6754ba22011-12-14 20:20:01 -08002078 ServiceManager.addService("dbinfo", new DbBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 if (MONITOR_CPU_USAGE) {
2080 ServiceManager.addService("cpuinfo", new CpuBinder(m));
2081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 ServiceManager.addService("permission", new PermissionController(m));
2083
2084 ApplicationInfo info =
2085 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07002086 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07002087 mSystemThread.installSystemApplicationInfo(info);
2088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 synchronized (mSelf) {
2090 ProcessRecord app = mSelf.newProcessRecordLocked(
2091 mSystemThread.getApplicationThread(), info,
2092 info.processName);
2093 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002094 app.pid = MY_PID;
Dianne Hackborn7d608422011-08-07 16:24:18 -07002095 app.maxAdj = ProcessList.SYSTEM_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
2097 synchronized (mSelf.mPidsSelfLocked) {
2098 mSelf.mPidsSelfLocked.put(app.pid, app);
2099 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002100 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 }
2102 } catch (PackageManager.NameNotFoundException e) {
2103 throw new RuntimeException(
2104 "Unable to find android system package", e);
2105 }
2106 }
2107
2108 public void setWindowManager(WindowManagerService wm) {
2109 mWindowManager = wm;
2110 }
2111
2112 public static final Context main(int factoryTest) {
2113 AThread thr = new AThread();
2114 thr.start();
2115
2116 synchronized (thr) {
2117 while (thr.mService == null) {
2118 try {
2119 thr.wait();
2120 } catch (InterruptedException e) {
2121 }
2122 }
2123 }
2124
2125 ActivityManagerService m = thr.mService;
2126 mSelf = m;
2127 ActivityThread at = ActivityThread.systemMain();
2128 mSystemThread = at;
2129 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08002130 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 m.mContext = context;
2132 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002133 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002134
2135 m.mBatteryStatsService.publish(context);
2136 m.mUsageStatsService.publish(context);
2137
2138 synchronized (thr) {
2139 thr.mReady = true;
2140 thr.notifyAll();
2141 }
2142
2143 m.startRunning(null, null, null, null);
2144
2145 return context;
2146 }
2147
2148 public static ActivityManagerService self() {
2149 return mSelf;
2150 }
2151
2152 static class AThread extends Thread {
2153 ActivityManagerService mService;
2154 boolean mReady = false;
2155
2156 public AThread() {
2157 super("ActivityManager");
2158 }
2159
2160 public void run() {
2161 Looper.prepare();
2162
2163 android.os.Process.setThreadPriority(
2164 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07002165 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166
2167 ActivityManagerService m = new ActivityManagerService();
2168
2169 synchronized (this) {
2170 mService = m;
2171 notifyAll();
2172 }
2173
2174 synchronized (this) {
2175 while (!mReady) {
2176 try {
2177 wait();
2178 } catch (InterruptedException e) {
2179 }
2180 }
2181 }
2182
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07002183 // For debug builds, log event loop stalls to dropbox for analysis.
2184 if (StrictMode.conditionallyEnableDebugLogging()) {
2185 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
2186 }
2187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 Looper.loop();
2189 }
2190 }
2191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 static class MemBinder extends Binder {
2193 ActivityManagerService mActivityManagerService;
2194 MemBinder(ActivityManagerService activityManagerService) {
2195 mActivityManagerService = activityManagerService;
2196 }
2197
2198 @Override
2199 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07002200 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2201 != PackageManager.PERMISSION_GRANTED) {
2202 pw.println("Permission Denial: can't dump meminfo from from pid="
2203 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2204 + " without permission " + android.Manifest.permission.DUMP);
2205 return;
2206 }
2207
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08002208 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args,
Dianne Hackborn672342c2011-11-29 11:29:02 -08002209 false, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 }
2211 }
2212
Chet Haase9c1e23b2011-03-24 10:51:31 -07002213 static class GraphicsBinder extends Binder {
2214 ActivityManagerService mActivityManagerService;
2215 GraphicsBinder(ActivityManagerService activityManagerService) {
2216 mActivityManagerService = activityManagerService;
2217 }
2218
2219 @Override
2220 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07002221 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2222 != PackageManager.PERMISSION_GRANTED) {
2223 pw.println("Permission Denial: can't dump gfxinfo from from pid="
2224 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2225 + " without permission " + android.Manifest.permission.DUMP);
2226 return;
2227 }
2228
Dianne Hackborne17aeb32011-04-07 15:11:57 -07002229 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07002230 }
2231 }
2232
Jeff Brown6754ba22011-12-14 20:20:01 -08002233 static class DbBinder extends Binder {
2234 ActivityManagerService mActivityManagerService;
2235 DbBinder(ActivityManagerService activityManagerService) {
2236 mActivityManagerService = activityManagerService;
2237 }
2238
2239 @Override
2240 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2241 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2242 != PackageManager.PERMISSION_GRANTED) {
2243 pw.println("Permission Denial: can't dump dbinfo from from pid="
2244 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2245 + " without permission " + android.Manifest.permission.DUMP);
2246 return;
2247 }
2248
2249 mActivityManagerService.dumpDbInfo(fd, pw, args);
2250 }
2251 }
2252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 static class CpuBinder extends Binder {
2254 ActivityManagerService mActivityManagerService;
2255 CpuBinder(ActivityManagerService activityManagerService) {
2256 mActivityManagerService = activityManagerService;
2257 }
2258
2259 @Override
2260 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07002261 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
2262 != PackageManager.PERMISSION_GRANTED) {
2263 pw.println("Permission Denial: can't dump cpuinfo from from pid="
2264 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2265 + " without permission " + android.Manifest.permission.DUMP);
2266 return;
2267 }
2268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002270 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
2271 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
2272 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 }
2274 }
2275 }
2276
2277 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002278 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07002279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 File dataDir = Environment.getDataDirectory();
2281 File systemDir = new File(dataDir, "system");
2282 systemDir.mkdirs();
2283 mBatteryStatsService = new BatteryStatsService(new File(
2284 systemDir, "batterystats.bin").toString());
2285 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07002286 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07002287 mOnBattery = DEBUG_POWER ? true
2288 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002289 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002291 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07002292 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293
Jack Palevichb90d28c2009-07-22 15:35:24 -07002294 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
2295 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
2296
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002297 mConfiguration.setToDefaults();
2298 mConfiguration.locale = Locale.getDefault();
Dianne Hackborn813075a62011-11-14 17:45:19 -08002299 mConfigurationSeq = mConfiguration.seq = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 mProcessStats.init();
2301
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002302 mCompatModePackages = new CompatModePackages(this, systemDir);
2303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 // Add ourself to the Watchdog monitors.
2305 Watchdog.getInstance().addMonitor(this);
2306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 mProcessStatsThread = new Thread("ProcessStats") {
2308 public void run() {
2309 while (true) {
2310 try {
2311 try {
2312 synchronized(this) {
2313 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002314 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002316 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 // + ", write delay=" + nextWriteDelay);
2318 if (nextWriteDelay < nextCpuDelay) {
2319 nextCpuDelay = nextWriteDelay;
2320 }
2321 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002322 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 this.wait(nextCpuDelay);
2324 }
2325 }
2326 } catch (InterruptedException e) {
2327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 updateCpuStatsNow();
2329 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002330 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 }
2332 }
2333 }
2334 };
2335 mProcessStatsThread.start();
2336 }
2337
2338 @Override
2339 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
2340 throws RemoteException {
2341 try {
2342 return super.onTransact(code, data, reply, flags);
2343 } catch (RuntimeException e) {
2344 // The activity manager only throws security exceptions, so let's
2345 // log all others.
2346 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002347 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 }
2349 throw e;
2350 }
2351 }
2352
2353 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002354 final long now = SystemClock.uptimeMillis();
2355 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
2356 return;
2357 }
2358 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
2359 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 mProcessStatsThread.notify();
2361 }
2362 }
2363 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 void updateCpuStatsNow() {
2366 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002367 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 final long now = SystemClock.uptimeMillis();
2369 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07002372 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
2373 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 haveNewCpuStats = true;
2375 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002376 //Slog.i(TAG, mProcessStats.printCurrentState());
2377 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 // + mProcessStats.getTotalCpuPercent() + "%");
2379
Joe Onorato8a9b2202010-02-26 18:56:32 -08002380 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 if ("true".equals(SystemProperties.get("events.cpu"))) {
2382 int user = mProcessStats.getLastUserTime();
2383 int system = mProcessStats.getLastSystemTime();
2384 int iowait = mProcessStats.getLastIoWaitTime();
2385 int irq = mProcessStats.getLastIrqTime();
2386 int softIrq = mProcessStats.getLastSoftIrqTime();
2387 int idle = mProcessStats.getLastIdleTime();
2388
2389 int total = user + system + iowait + irq + softIrq + idle;
2390 if (total == 0) total = 1;
2391
Doug Zongker2bec3d42009-12-04 12:52:44 -08002392 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 ((user+system+iowait+irq+softIrq) * 100) / total,
2394 (user * 100) / total,
2395 (system * 100) / total,
2396 (iowait * 100) / total,
2397 (irq * 100) / total,
2398 (softIrq * 100) / total);
2399 }
2400 }
2401
Amith Yamasanie43530a2009-08-21 13:11:37 -07002402 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07002403 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002404 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 synchronized(mPidsSelfLocked) {
2406 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002407 if (mOnBattery) {
2408 int perc = bstats.startAddingCpuLocked();
2409 int totalUTime = 0;
2410 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07002411 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07002413 ProcessStats.Stats st = mProcessStats.getStats(i);
2414 if (!st.working) {
2415 continue;
2416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002417 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002418 int otherUTime = (st.rel_utime*perc)/100;
2419 int otherSTime = (st.rel_stime*perc)/100;
2420 totalUTime += otherUTime;
2421 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 if (pr != null) {
2423 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002424 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
2425 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07002426 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07002427 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002428 } else {
2429 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07002430 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002431 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002432 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
2433 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07002434 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 }
2437 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002438 bstats.finishAddingCpuLocked(perc, totalUTime,
2439 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 }
2441 }
2442 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07002443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
2445 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07002446 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 }
2448 }
2449 }
2450 }
2451
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002452 @Override
2453 public void batteryNeedsCpuUpdate() {
2454 updateCpuStatsNow();
2455 }
2456
2457 @Override
2458 public void batteryPowerChanged(boolean onBattery) {
2459 // When plugging in, update the CPU stats first before changing
2460 // the plug state.
2461 updateCpuStatsNow();
2462 synchronized (this) {
2463 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07002464 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07002465 }
2466 }
2467 }
2468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 /**
2470 * Initialize the application bind args. These are passed to each
2471 * process when the bindApplication() IPC is sent to the process. They're
2472 * lazily setup to make sure the services are running when they're asked for.
2473 */
2474 private HashMap<String, IBinder> getCommonServicesLocked() {
2475 if (mAppBindArgs == null) {
2476 mAppBindArgs = new HashMap<String, IBinder>();
2477
2478 // Setup the application init args
2479 mAppBindArgs.put("package", ServiceManager.getService("package"));
2480 mAppBindArgs.put("window", ServiceManager.getService("window"));
2481 mAppBindArgs.put(Context.ALARM_SERVICE,
2482 ServiceManager.getService(Context.ALARM_SERVICE));
2483 }
2484 return mAppBindArgs;
2485 }
2486
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002487 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 if (mFocusedActivity != r) {
2489 mFocusedActivity = r;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08002490 if (r != null) {
2491 mWindowManager.setFocusedApp(r.appToken, true);
2492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 }
2494 }
2495
Dianne Hackborn906497c2010-05-10 15:57:38 -07002496 private final void updateLruProcessInternalLocked(ProcessRecord app,
2497 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002499 int lrui = mLruProcesses.indexOf(app);
2500 if (lrui >= 0) mLruProcesses.remove(lrui);
2501
2502 int i = mLruProcesses.size()-1;
2503 int skipTop = 0;
2504
Dianne Hackborn906497c2010-05-10 15:57:38 -07002505 app.lruSeq = mLruSeq;
2506
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002507 // compute the new weight for this process.
2508 if (updateActivityTime) {
2509 app.lastActivityTime = SystemClock.uptimeMillis();
2510 }
2511 if (app.activities.size() > 0) {
2512 // If this process has activities, we more strongly want to keep
2513 // it around.
2514 app.lruWeight = app.lastActivityTime;
2515 } else if (app.pubProviders.size() > 0) {
2516 // If this process contains content providers, we want to keep
2517 // it a little more strongly.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002518 app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002519 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002520 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002521 } else {
2522 // If this process doesn't have activities, we less strongly
2523 // want to keep it around, and generally want to avoid getting
2524 // in front of any very recently used activities.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002525 app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002526 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002527 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002528 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07002529
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002530 while (i >= 0) {
2531 ProcessRecord p = mLruProcesses.get(i);
2532 // If this app shouldn't be in front of the first N background
2533 // apps, then skip over that many that are currently hidden.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002534 if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002535 skipTop--;
2536 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07002537 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002538 mLruProcesses.add(i+1, app);
2539 break;
2540 }
2541 i--;
2542 }
2543 if (i < 0) {
2544 mLruProcesses.add(0, app);
2545 }
2546
Dianne Hackborn906497c2010-05-10 15:57:38 -07002547 // If the app is currently using a content provider or service,
2548 // bump those processes as well.
2549 if (app.connections.size() > 0) {
2550 for (ConnectionRecord cr : app.connections) {
2551 if (cr.binding != null && cr.binding.service != null
2552 && cr.binding.service.app != null
2553 && cr.binding.service.app.lruSeq != mLruSeq) {
2554 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
2555 updateActivityTime, i+1);
2556 }
2557 }
2558 }
2559 if (app.conProviders.size() > 0) {
2560 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07002561 if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
2562 updateLruProcessInternalLocked(cpr.proc, oomAdj,
Dianne Hackborn906497c2010-05-10 15:57:38 -07002563 updateActivityTime, i+1);
2564 }
2565 }
2566 }
2567
Joe Onorato8a9b2202010-02-26 18:56:32 -08002568 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 if (oomAdj) {
2570 updateOomAdjLocked();
2571 }
2572 }
2573
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002574 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07002575 boolean oomAdj, boolean updateActivityTime) {
2576 mLruSeq++;
2577 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
2578 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07002579
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 String processName, int uid) {
2582 if (uid == Process.SYSTEM_UID) {
2583 // The system gets to run in any process. If there are multiple
2584 // processes with the same uid, just pick the first (this
2585 // should never happen).
2586 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
2587 processName);
2588 return procs != null ? procs.valueAt(0) : null;
2589 }
2590 ProcessRecord proc = mProcessNames.get(processName, uid);
2591 return proc;
2592 }
2593
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002595 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002596 try {
2597 if (pm.performDexOpt(packageName)) {
2598 mDidDexOpt = true;
2599 }
2600 } catch (RemoteException e) {
2601 }
2602 }
2603
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002604 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 int transit = mWindowManager.getPendingAppTransition();
2606 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2607 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
2608 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
2609 }
2610
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002611 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002613 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2615 // We don't have to do anything more if:
2616 // (1) There is an existing application record; and
2617 // (2) The caller doesn't think it is dead, OR there is no thread
2618 // object attached to it so we know it couldn't have crashed; and
2619 // (3) There is a pid assigned to it, so it is either starting or
2620 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002621 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 + " app=" + app + " knownToBeDead=" + knownToBeDead
2623 + " thread=" + (app != null ? app.thread : null)
2624 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002625 if (app != null && app.pid > 0) {
2626 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002627 // We already have the app running, or are waiting for it to
2628 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002629 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002630 // If this is a new package in the process, add the package to the list
2631 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01002632 return app;
2633 } else {
2634 // An application record is attached to a previous process,
2635 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002636 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002637 handleAppDiedLocked(app, true, true);
Magnus Edlund7bb25812010-02-24 15:45:06 +01002638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 String hostingNameStr = hostingName != null
2642 ? hostingName.flattenToShortString() : null;
2643
2644 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2645 // If we are in the background, then check to see if this process
2646 // is bad. If so, we will just silently fail.
2647 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002648 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
2649 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 return null;
2651 }
2652 } else {
2653 // When the user is explicitly starting a process, then clear its
2654 // crash count so that we won't make it bad until they see at
2655 // least one crash dialog again, and make the process good again
2656 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002657 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
2658 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 mProcessCrashTimes.remove(info.processName, info.uid);
2660 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002661 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 info.processName);
2663 mBadProcesses.remove(info.processName, info.uid);
2664 if (app != null) {
2665 app.bad = false;
2666 }
2667 }
2668 }
2669
2670 if (app == null) {
2671 app = newProcessRecordLocked(null, info, processName);
2672 mProcessNames.put(processName, info.uid, app);
2673 } else {
2674 // If this is a new package in the process, add the package to the list
2675 app.addPackage(info.packageName);
2676 }
2677
2678 // If the system is not ready yet, then hold off on starting this
2679 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002680 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002681 && !isAllowedWhileBooting(info)
2682 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 if (!mProcessesOnHold.contains(app)) {
2684 mProcessesOnHold.add(app);
2685 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002686 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 return app;
2688 }
2689
2690 startProcessLocked(app, hostingType, hostingNameStr);
2691 return (app.pid != 0) ? app : null;
2692 }
2693
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002694 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2695 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2696 }
2697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 private final void startProcessLocked(ProcessRecord app,
2699 String hostingType, String hostingNameStr) {
2700 if (app.pid > 0 && app.pid != MY_PID) {
2701 synchronized (mPidsSelfLocked) {
2702 mPidsSelfLocked.remove(app.pid);
2703 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2704 }
2705 app.pid = 0;
2706 }
2707
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07002708 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
2709 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 mProcessesOnHold.remove(app);
2711
2712 updateCpuStats();
2713
2714 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2715 mProcDeaths[0] = 0;
2716
2717 try {
2718 int uid = app.info.uid;
2719 int[] gids = null;
2720 try {
2721 gids = mContext.getPackageManager().getPackageGids(
2722 app.info.packageName);
2723 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002724 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 }
2726 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2727 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2728 && mTopComponent != null
2729 && app.processName.equals(mTopComponent.getPackageName())) {
2730 uid = 0;
2731 }
2732 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2733 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2734 uid = 0;
2735 }
2736 }
2737 int debugFlags = 0;
2738 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2739 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07002740 // Also turn on CheckJNI for debuggable apps. It's quite
2741 // awkward to turn on otherwise.
2742 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002744 // Run the app in safe mode if its manifest requests so or the
2745 // system is booted in safe mode.
2746 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2747 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002748 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2751 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2752 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07002753 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
2754 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
2755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 if ("1".equals(SystemProperties.get("debug.assert"))) {
2757 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2758 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07002759
2760 // Start the process. It will either succeed and return a result containing
2761 // the PID of the new process, or else throw a RuntimeException.
2762 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07002763 app.processName, uid, uid, gids, debugFlags,
2764 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07002765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2767 synchronized (bs) {
2768 if (bs.isOnBattery()) {
2769 app.batteryStats.incStartsLocked();
2770 }
2771 }
2772
Jeff Brown3f9dd282011-07-08 20:02:19 -07002773 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 app.processName, hostingType,
2775 hostingNameStr != null ? hostingNameStr : "");
2776
2777 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07002778 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 }
2780
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002781 StringBuilder buf = mStringBuilder;
2782 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 buf.append("Start proc ");
2784 buf.append(app.processName);
2785 buf.append(" for ");
2786 buf.append(hostingType);
2787 if (hostingNameStr != null) {
2788 buf.append(" ");
2789 buf.append(hostingNameStr);
2790 }
2791 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07002792 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 buf.append(" uid=");
2794 buf.append(uid);
2795 buf.append(" gids={");
2796 if (gids != null) {
2797 for (int gi=0; gi<gids.length; gi++) {
2798 if (gi != 0) buf.append(", ");
2799 buf.append(gids[gi]);
2800
2801 }
2802 }
2803 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002804 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07002805 app.pid = startResult.pid;
2806 app.usingWrapper = startResult.usingWrapper;
2807 app.removed = false;
2808 synchronized (mPidsSelfLocked) {
2809 this.mPidsSelfLocked.put(startResult.pid, app);
2810 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2811 msg.obj = app;
2812 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2813 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 }
2815 } catch (RuntimeException e) {
2816 // XXX do better error recovery.
2817 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002818 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 }
2820 }
2821
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002822 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 if (resumed) {
2824 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2825 } else {
2826 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2827 }
2828 }
2829
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002830 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002831 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2832 && mTopAction == null) {
2833 // We are running in factory test mode, but unable to find
2834 // the factory test app, so just sit around displaying the
2835 // error message and don't try to start anything.
2836 return false;
2837 }
2838 Intent intent = new Intent(
2839 mTopAction,
2840 mTopData != null ? Uri.parse(mTopData) : null);
2841 intent.setComponent(mTopComponent);
2842 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2843 intent.addCategory(Intent.CATEGORY_HOME);
2844 }
2845 ActivityInfo aInfo =
2846 intent.resolveActivityInfo(mContext.getPackageManager(),
2847 STOCK_PM_FLAGS);
2848 if (aInfo != null) {
2849 intent.setComponent(new ComponentName(
2850 aInfo.applicationInfo.packageName, aInfo.name));
2851 // Don't do this if the home app is currently being
2852 // instrumented.
2853 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2854 aInfo.applicationInfo.uid);
2855 if (app == null || app.instrumentationClass == null) {
2856 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002857 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002858 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002859 }
2860 }
2861
2862
2863 return true;
2864 }
2865
2866 /**
2867 * Starts the "new version setup screen" if appropriate.
2868 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002869 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002870 // Only do this once per boot.
2871 if (mCheckedForSetup) {
2872 return;
2873 }
2874
2875 // We will show this screen if the current one is a different
2876 // version than the last one shown, and we are not running in
2877 // low-level factory test mode.
2878 final ContentResolver resolver = mContext.getContentResolver();
2879 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2880 Settings.Secure.getInt(resolver,
2881 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2882 mCheckedForSetup = true;
2883
2884 // See if we should be showing the platform update setup UI.
2885 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2886 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2887 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2888
2889 // We don't allow third party apps to replace this.
2890 ResolveInfo ri = null;
2891 for (int i=0; ris != null && i<ris.size(); i++) {
2892 if ((ris.get(i).activityInfo.applicationInfo.flags
2893 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2894 ri = ris.get(i);
2895 break;
2896 }
2897 }
2898
2899 if (ri != null) {
2900 String vers = ri.activityInfo.metaData != null
2901 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2902 : null;
2903 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2904 vers = ri.activityInfo.applicationInfo.metaData.getString(
2905 Intent.METADATA_SETUP_VERSION);
2906 }
2907 String lastVers = Settings.Secure.getString(
2908 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2909 if (vers != null && !vers.equals(lastVers)) {
2910 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2911 intent.setComponent(new ComponentName(
2912 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002913 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002914 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002915 }
2916 }
2917 }
2918 }
2919
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002920 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002921 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002922 }
2923
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002924 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002925 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002926 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2927 }
2928 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002929
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002930 public void setFrontActivityScreenCompatMode(int mode) {
2931 synchronized (this) {
2932 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2933 }
2934 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002935
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002936 public int getPackageScreenCompatMode(String packageName) {
2937 synchronized (this) {
2938 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2939 }
2940 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002941
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002942 public void setPackageScreenCompatMode(String packageName, int mode) {
2943 synchronized (this) {
2944 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002945 }
2946 }
2947
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002948 public boolean getPackageAskScreenCompat(String packageName) {
2949 synchronized (this) {
2950 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2951 }
2952 }
2953
2954 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2955 synchronized (this) {
2956 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2957 }
2958 }
2959
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002960 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002961 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002962
2963 final int identHash = System.identityHashCode(r);
2964 updateUsageStats(r, true);
2965
2966 int i = mWatchers.beginBroadcast();
2967 while (i > 0) {
2968 i--;
2969 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2970 if (w != null) {
2971 try {
2972 w.activityResuming(identHash);
2973 } catch (RemoteException e) {
2974 }
2975 }
2976 }
2977 mWatchers.finishBroadcast();
2978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979
Jeff Sharkeya4620792011-05-20 15:29:23 -07002980 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2981 int i = mProcessObservers.beginBroadcast();
2982 while (i > 0) {
2983 i--;
2984 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2985 if (observer != null) {
2986 try {
2987 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2988 } catch (RemoteException e) {
2989 }
2990 }
2991 }
2992 mProcessObservers.finishBroadcast();
2993 }
2994
2995 private void dispatchProcessDied(int pid, int uid) {
2996 int i = mProcessObservers.beginBroadcast();
2997 while (i > 0) {
2998 i--;
2999 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
3000 if (observer != null) {
3001 try {
3002 observer.onProcessDied(pid, uid);
3003 } catch (RemoteException e) {
3004 }
3005 }
3006 }
3007 mProcessObservers.finishBroadcast();
3008 }
3009
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003010 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003011 final int N = mPendingActivityLaunches.size();
3012 if (N <= 0) {
3013 return;
3014 }
3015 for (int i=0; i<N; i++) {
3016 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003017 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003018 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3019 doResume && i == (N-1));
3020 }
3021 mPendingActivityLaunches.clear();
3022 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003023
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003024 public final int startActivity(IApplicationThread caller,
3025 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3026 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003027 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
3028 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003029 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003030 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003031 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
3032 null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003033 }
3034
3035 public final WaitResult startActivityAndWait(IApplicationThread caller,
3036 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3037 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003038 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
3039 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003040 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003041 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003042 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003043 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
3044 res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003045 return res;
3046 }
3047
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003048 public final int startActivityWithConfig(IApplicationThread caller,
3049 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3050 int grantedMode, IBinder resultTo,
3051 String resultWho, int requestCode, boolean onlyIfNeeded,
3052 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003053 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003054 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003055 requestCode, onlyIfNeeded, debug, null, null, false, null, config);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003056 }
3057
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003058 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003059 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003060 IBinder resultTo, String resultWho, int requestCode,
3061 int flagsMask, int flagsValues) {
3062 // Refuse possible leaked file descriptors
3063 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3064 throw new IllegalArgumentException("File descriptors passed in Intent");
3065 }
3066
3067 IIntentSender sender = intent.getTarget();
3068 if (!(sender instanceof PendingIntentRecord)) {
3069 throw new IllegalArgumentException("Bad PendingIntent object");
3070 }
3071
3072 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003073
3074 synchronized (this) {
3075 // If this is coming from the currently resumed activity, it is
3076 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003077 if (mMainStack.mResumedActivity != null
3078 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003079 Binder.getCallingUid()) {
3080 mAppSwitchesAllowedTime = 0;
3081 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003082 }
3083
Dianne Hackborn6c418d52011-06-29 14:05:33 -07003084 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003085 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3086 }
3087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 public boolean startNextMatchingActivity(IBinder callingActivity,
3089 Intent intent) {
3090 // Refuse possible leaked file descriptors
3091 if (intent != null && intent.hasFileDescriptors() == true) {
3092 throw new IllegalArgumentException("File descriptors passed in Intent");
3093 }
3094
3095 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003096 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
3097 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 return false;
3099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 if (r.app == null || r.app.thread == null) {
3101 // The caller is not running... d'oh!
3102 return false;
3103 }
3104 intent = new Intent(intent);
3105 // The caller is not allowed to change the data.
3106 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3107 // And we are resetting to find the next component...
3108 intent.setComponent(null);
3109
3110 ActivityInfo aInfo = null;
3111 try {
3112 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003113 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003115 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116
3117 // Look for the original activity in the list...
3118 final int N = resolves != null ? resolves.size() : 0;
3119 for (int i=0; i<N; i++) {
3120 ResolveInfo rInfo = resolves.get(i);
3121 if (rInfo.activityInfo.packageName.equals(r.packageName)
3122 && rInfo.activityInfo.name.equals(r.info.name)) {
3123 // We found the current one... the next matching is
3124 // after it.
3125 i++;
3126 if (i<N) {
3127 aInfo = resolves.get(i).activityInfo;
3128 }
3129 break;
3130 }
3131 }
3132 } catch (RemoteException e) {
3133 }
3134
3135 if (aInfo == null) {
3136 // Nobody who is next!
3137 return false;
3138 }
3139
3140 intent.setComponent(new ComponentName(
3141 aInfo.applicationInfo.packageName, aInfo.name));
3142 intent.setFlags(intent.getFlags()&~(
3143 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3144 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3145 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3146 Intent.FLAG_ACTIVITY_NEW_TASK));
3147
3148 // Okay now we need to start the new activity, replacing the
3149 // currently running activity. This is a little tricky because
3150 // we want to start the new one as if the current one is finished,
3151 // but not finish the current one first so that there is no flicker.
3152 // And thus...
3153 final boolean wasFinishing = r.finishing;
3154 r.finishing = true;
3155
3156 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003157 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 final String resultWho = r.resultWho;
3159 final int requestCode = r.requestCode;
3160 r.resultTo = null;
3161 if (resultTo != null) {
3162 resultTo.removeResultsLocked(r, resultWho, requestCode);
3163 }
3164
3165 final long origId = Binder.clearCallingIdentity();
3166 // XXX we are not dealing with propagating grantedUriPermissions...
3167 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003168 int res = mMainStack.startActivityLocked(r.app.thread, intent,
Dianne Hackbornbe707852011-11-11 14:32:10 -08003169 r.resolvedType, null, 0, aInfo,
3170 resultTo != null ? resultTo.appToken : null, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003171 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 Binder.restoreCallingIdentity(origId);
3173
3174 r.finishing = wasFinishing;
3175 if (res != START_SUCCESS) {
3176 return false;
3177 }
3178 return true;
3179 }
3180 }
3181
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003182 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 Intent intent, String resolvedType, IBinder resultTo,
3184 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003185
3186 // This is so super not safe, that only the system (or okay root)
3187 // can do it.
3188 final int callingUid = Binder.getCallingUid();
3189 if (callingUid != 0 && callingUid != Process.myUid()) {
3190 throw new SecurityException(
3191 "startActivityInPackage only available to the system");
3192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003194 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003195 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
3196 null, null, false, null, null);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003197 }
3198
3199 public final int startActivities(IApplicationThread caller,
3200 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
3201 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
3202 }
3203
3204 public final int startActivitiesInPackage(int uid,
3205 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
3206
3207 // This is so super not safe, that only the system (or okay root)
3208 // can do it.
3209 final int callingUid = Binder.getCallingUid();
3210 if (callingUid != 0 && callingUid != Process.myUid()) {
3211 throw new SecurityException(
3212 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 }
3214
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003215 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 }
3217
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003218 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08003220 // Quick case: check if the top-most recent task is the same.
3221 if (N > 0 && mRecentTasks.get(0) == task) {
3222 return;
3223 }
3224 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 for (int i=0; i<N; i++) {
3226 TaskRecord tr = mRecentTasks.get(i);
3227 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3228 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3229 mRecentTasks.remove(i);
3230 i--;
3231 N--;
3232 if (task.intent == null) {
3233 // If the new recent task we are adding is not fully
3234 // specified, then replace it with the existing recent task.
3235 task = tr;
3236 }
3237 }
3238 }
3239 if (N >= MAX_RECENT_TASKS) {
3240 mRecentTasks.remove(N-1);
3241 }
3242 mRecentTasks.add(0, task);
3243 }
3244
3245 public void setRequestedOrientation(IBinder token,
3246 int requestedOrientation) {
3247 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003248 ActivityRecord r = mMainStack.isInStackLocked(token);
3249 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 return;
3251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbe707852011-11-11 14:32:10 -08003253 mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003255 mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -08003256 r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257 if (config != null) {
3258 r.frozenBeforeDestroy = true;
Dianne Hackborn813075a62011-11-14 17:45:19 -08003259 if (!updateConfigurationLocked(config, r, false, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003260 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 }
3262 }
3263 Binder.restoreCallingIdentity(origId);
3264 }
3265 }
3266
3267 public int getRequestedOrientation(IBinder token) {
3268 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003269 ActivityRecord r = mMainStack.isInStackLocked(token);
3270 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3272 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08003273 return mWindowManager.getAppOrientation(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 }
3275 }
3276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 /**
3278 * This is the internal entry point for handling Activity.finish().
3279 *
3280 * @param token The Binder token referencing the Activity we want to finish.
3281 * @param resultCode Result code, if any, from this Activity.
3282 * @param resultData Result data (Intent), if any, from this Activity.
3283 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11003284 * @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 -08003285 */
3286 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
3287 // Refuse possible leaked file descriptors
3288 if (resultData != null && resultData.hasFileDescriptors() == true) {
3289 throw new IllegalArgumentException("File descriptors passed in Intent");
3290 }
3291
3292 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003293 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003295 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 if (next != null) {
3297 // ask watcher if this is allowed
3298 boolean resumeOK = true;
3299 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003300 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003301 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003302 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 }
3304
3305 if (!resumeOK) {
3306 return false;
3307 }
3308 }
3309 }
3310 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003311 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 resultData, "app-request");
3313 Binder.restoreCallingIdentity(origId);
3314 return res;
3315 }
3316 }
3317
Dianne Hackborn860755f2010-06-03 18:47:52 -07003318 public final void finishHeavyWeightApp() {
3319 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3320 != PackageManager.PERMISSION_GRANTED) {
3321 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
3322 + Binder.getCallingPid()
3323 + ", uid=" + Binder.getCallingUid()
3324 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
3325 Slog.w(TAG, msg);
3326 throw new SecurityException(msg);
3327 }
3328
3329 synchronized(this) {
3330 if (mHeavyWeightProcess == null) {
3331 return;
3332 }
3333
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003334 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07003335 mHeavyWeightProcess.activities);
3336 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003337 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003338 if (!r.finishing) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003339 int index = mMainStack.indexOfTokenLocked(r.appToken);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003340 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003341 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07003342 null, "finish-heavy");
3343 }
3344 }
3345 }
3346
3347 mHeavyWeightProcess = null;
3348 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3349 }
3350 }
3351
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07003352 public void crashApplication(int uid, int initialPid, String packageName,
3353 String message) {
3354 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3355 != PackageManager.PERMISSION_GRANTED) {
3356 String msg = "Permission Denial: crashApplication() from pid="
3357 + Binder.getCallingPid()
3358 + ", uid=" + Binder.getCallingUid()
3359 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
3360 Slog.w(TAG, msg);
3361 throw new SecurityException(msg);
3362 }
3363
3364 synchronized(this) {
3365 ProcessRecord proc = null;
3366
3367 // Figure out which process to kill. We don't trust that initialPid
3368 // still has any relation to current pids, so must scan through the
3369 // list.
3370 synchronized (mPidsSelfLocked) {
3371 for (int i=0; i<mPidsSelfLocked.size(); i++) {
3372 ProcessRecord p = mPidsSelfLocked.valueAt(i);
3373 if (p.info.uid != uid) {
3374 continue;
3375 }
3376 if (p.pid == initialPid) {
3377 proc = p;
3378 break;
3379 }
3380 for (String str : p.pkgList) {
3381 if (str.equals(packageName)) {
3382 proc = p;
3383 }
3384 }
3385 }
3386 }
3387
3388 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07003389 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07003390 + " initialPid=" + initialPid
3391 + " packageName=" + packageName);
3392 return;
3393 }
3394
3395 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07003396 if (proc.pid == Process.myPid()) {
3397 Log.w(TAG, "crashApplication: trying to crash self!");
3398 return;
3399 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07003400 long ident = Binder.clearCallingIdentity();
3401 try {
3402 proc.thread.scheduleCrash(message);
3403 } catch (RemoteException e) {
3404 }
3405 Binder.restoreCallingIdentity(ident);
3406 }
3407 }
3408 }
3409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 public final void finishSubActivity(IBinder token, String resultWho,
3411 int requestCode) {
3412 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003413 ActivityRecord self = mMainStack.isInStackLocked(token);
3414 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 return;
3416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417
3418 final long origId = Binder.clearCallingIdentity();
3419
3420 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003421 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3422 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 if (r.resultTo == self && r.requestCode == requestCode) {
3424 if ((r.resultWho == null && resultWho == null) ||
3425 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003426 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 Activity.RESULT_CANCELED, null, "request-sub");
3428 }
3429 }
3430 }
3431
3432 Binder.restoreCallingIdentity(origId);
3433 }
3434 }
3435
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003436 public boolean willActivityBeVisible(IBinder token) {
3437 synchronized(this) {
3438 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003439 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3440 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08003441 if (r.appToken == token) {
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003442 return true;
3443 }
3444 if (r.fullscreen && !r.finishing) {
3445 return false;
3446 }
3447 }
3448 return true;
3449 }
3450 }
3451
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003452 public void overridePendingTransition(IBinder token, String packageName,
3453 int enterAnim, int exitAnim) {
3454 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003455 ActivityRecord self = mMainStack.isInStackLocked(token);
3456 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003457 return;
3458 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003459
3460 final long origId = Binder.clearCallingIdentity();
3461
3462 if (self.state == ActivityState.RESUMED
3463 || self.state == ActivityState.PAUSING) {
3464 mWindowManager.overridePendingAppTransition(packageName,
3465 enterAnim, exitAnim);
3466 }
3467
3468 Binder.restoreCallingIdentity(origId);
3469 }
3470 }
3471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 * Main function for removing an existing process from the activity manager
3474 * as a result of that process going away. Clears out all connections
3475 * to the process.
3476 */
3477 private final void handleAppDiedLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003478 boolean restarting, boolean allowRestart) {
3479 cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003481 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 }
3483
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003484 if (mProfileProc == app) {
3485 clearProfilerLocked();
3486 }
3487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003489 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
3490 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
3491 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003493 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
3494 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 }
3496
3497 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003498 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499
3500 boolean atTop = true;
3501 boolean hasVisibleActivities = false;
3502
3503 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003504 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003505 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 TAG, "Removing app " + app + " from history with " + i + " entries");
3507 while (i > 0) {
3508 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003509 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003510 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 TAG, "Record #" + i + " " + r + ": app=" + r.app);
3512 if (r.app == app) {
3513 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003514 if (ActivityStack.DEBUG_ADD_REMOVE) {
3515 RuntimeException here = new RuntimeException("here");
3516 here.fillInStackTrace();
3517 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
3518 + ": haveState=" + r.haveState
3519 + " stateNotNeeded=" + r.stateNotNeeded
3520 + " finishing=" + r.finishing
3521 + " state=" + r.state, here);
3522 }
3523 if (!r.finishing) {
3524 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -08003525 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3526 System.identityHashCode(r),
3527 r.task.taskId, r.shortComponentName,
3528 "proc died without state saved");
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003529 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08003530 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003531 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003532 r.takeFromHistory();
Dianne Hackbornbe707852011-11-11 14:32:10 -08003533 mWindowManager.removeAppToken(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003534 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003535 mMainStack.validateAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003537 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538
3539 } else {
3540 // We have the current state for this activity, so
3541 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003542 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 TAG, "Keeping entry, setting app to null");
3544 if (r.visible) {
3545 hasVisibleActivities = true;
3546 }
3547 r.app = null;
3548 r.nowVisible = false;
3549 if (!r.haveState) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003550 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
3551 "App died, clearing saved state of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 r.icicle = null;
3553 }
3554 }
3555
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003556 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 }
3558 atTop = false;
3559 }
3560
3561 app.activities.clear();
3562
3563 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003564 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 + " running instrumentation " + app.instrumentationClass);
3566 Bundle info = new Bundle();
3567 info.putString("shortMsg", "Process crashed.");
3568 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
3569 }
3570
3571 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003572 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 // If there was nothing to resume, and we are not already
3574 // restarting this process, but there is a visible activity that
3575 // is hosted by the process... then make sure all visible
3576 // activities are running, taking care of restarting this
3577 // process.
3578 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003579 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 }
3581 }
3582 }
3583 }
3584
3585 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
3586 IBinder threadBinder = thread.asBinder();
3587
3588 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003589 for (int i=mLruProcesses.size()-1; i>=0; i--) {
3590 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
3592 return i;
3593 }
3594 }
3595 return -1;
3596 }
3597
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003598 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 IApplicationThread thread) {
3600 if (thread == null) {
3601 return null;
3602 }
3603
3604 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003605 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 }
3607
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003608 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 IApplicationThread thread) {
3610
3611 mProcDeaths[0]++;
3612
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003613 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
3614 synchronized (stats) {
3615 stats.noteProcessDiedLocked(app.info.uid, pid);
3616 }
3617
Magnus Edlund7bb25812010-02-24 15:45:06 +01003618 // Clean up already done if the process has been re-started.
3619 if (app.pid == pid && app.thread != null &&
3620 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07003621 if (!app.killedBackground) {
3622 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
3623 + ") has died.");
3624 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003625 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003626 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 TAG, "Dying app: " + app + ", pid: " + pid
3628 + ", thread: " + thread.asBinder());
3629 boolean doLowMem = app.instrumentationClass == null;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003630 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631
3632 if (doLowMem) {
3633 // If there are no longer any background processes running,
3634 // and the app that died was not running instrumentation,
3635 // then tell everyone we are now low on memory.
3636 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003637 for (int i=mLruProcesses.size()-1; i>=0; i--) {
3638 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -07003639 if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003640 haveBg = true;
3641 break;
3642 }
3643 }
3644
3645 if (!haveBg) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003646 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003647 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003648 for (int i=mLruProcesses.size()-1; i>=0; i--) {
3649 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07003650 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003651 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
3652 // The low memory report is overriding any current
3653 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07003654 // heavy/important/visible/foreground processes first.
Dianne Hackborn7d608422011-08-07 16:24:18 -07003655 if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003656 rec.lastRequestedGc = 0;
3657 } else {
3658 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003660 rec.reportLowMemory = true;
3661 rec.lastLowMemory = now;
3662 mProcessesToGc.remove(rec);
3663 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 }
3665 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07003666 mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003667 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 }
3669 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01003670 } else if (app.pid != pid) {
3671 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003672 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01003673 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08003674 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003675 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003676 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 + thread.asBinder());
3678 }
3679 }
3680
Dan Egnor42471dd2010-01-07 17:25:22 -08003681 /**
3682 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07003683 * @param clearTraces causes the dump file to be erased prior to the new
3684 * traces being written, if true; when false, the new traces will be
3685 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003686 * @param firstPids of dalvik VM processes to dump stack traces for first
3687 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08003688 * @return file containing stack traces, or null if no dump file is configured
3689 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003690 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
3691 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003692 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
3693 if (tracesPath == null || tracesPath.length() == 0) {
3694 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003696
3697 File tracesFile = new File(tracesPath);
3698 try {
3699 File tracesDir = tracesFile.getParentFile();
3700 if (!tracesDir.exists()) tracesFile.mkdirs();
3701 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
3702
Christopher Tate6ee412d2010-05-28 12:01:56 -07003703 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08003704 tracesFile.createNewFile();
3705 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
3706 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003707 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08003708 return null;
3709 }
3710
3711 // Use a FileObserver to detect when traces finish writing.
3712 // The order of traces is considered important to maintain for legibility.
3713 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
3714 public synchronized void onEvent(int event, String path) { notify(); }
3715 };
3716
3717 try {
3718 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003719
3720 // First collect all of the stacks of the most important pids.
3721 try {
3722 int num = firstPids.size();
3723 for (int i = 0; i < num; i++) {
3724 synchronized (observer) {
3725 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
3726 observer.wait(200); // Wait for write-close, give up after 200msec
3727 }
3728 }
3729 } catch (InterruptedException e) {
3730 Log.wtf(TAG, e);
3731 }
3732
3733 // Next measure CPU usage.
3734 if (processStats != null) {
3735 processStats.init();
3736 System.gc();
3737 processStats.update();
3738 try {
3739 synchronized (processStats) {
3740 processStats.wait(500); // measure over 1/2 second.
3741 }
3742 } catch (InterruptedException e) {
3743 }
3744 processStats.update();
3745
3746 // We'll take the stack crawls of just the top apps using CPU.
3747 final int N = processStats.countWorkingStats();
3748 int numProcs = 0;
3749 for (int i=0; i<N && numProcs<5; i++) {
3750 ProcessStats.Stats stats = processStats.getWorkingStats(i);
3751 if (lastPids.indexOfKey(stats.pid) >= 0) {
3752 numProcs++;
3753 try {
3754 synchronized (observer) {
3755 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
3756 observer.wait(200); // Wait for write-close, give up after 200msec
3757 }
3758 } catch (InterruptedException e) {
3759 Log.wtf(TAG, e);
3760 }
3761
3762 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003763 }
3764 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003765
3766 return tracesFile;
3767
Dan Egnor42471dd2010-01-07 17:25:22 -08003768 } finally {
3769 observer.stopWatching();
3770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 }
3772
Jeff Brown4d94a762010-09-23 11:33:28 -07003773 private final class AppNotResponding implements Runnable {
3774 private final ProcessRecord mApp;
3775 private final String mAnnotation;
3776
3777 public AppNotResponding(ProcessRecord app, String annotation) {
3778 mApp = app;
3779 mAnnotation = annotation;
3780 }
3781
3782 @Override
3783 public void run() {
3784 appNotResponding(mApp, null, null, mAnnotation);
3785 }
3786 }
3787
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003788 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
3789 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003790 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
3791 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
3792
Dianne Hackborn287952c2010-09-22 22:34:31 -07003793 if (mController != null) {
3794 try {
3795 // 0 == continue, -1 = kill process immediately
3796 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
3797 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3798 } catch (RemoteException e) {
3799 mController = null;
3800 }
3801 }
3802
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003803 long anrTime = SystemClock.uptimeMillis();
3804 if (MONITOR_CPU_USAGE) {
3805 updateCpuStatsNow();
3806 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003807
3808 synchronized (this) {
3809 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
3810 if (mShuttingDown) {
3811 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
3812 return;
3813 } else if (app.notResponding) {
3814 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
3815 return;
3816 } else if (app.crashing) {
3817 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3818 return;
3819 }
3820
3821 // In case we come through here for the same app before completing
3822 // this one, mark as anring now so we will bail out.
3823 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003824
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003825 // Log the ANR to the event log.
3826 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3827 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003828
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003829 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003830 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003831
3832 int parentPid = app.pid;
3833 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003834 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003835
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003836 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003837
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003838 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3839 ProcessRecord r = mLruProcesses.get(i);
3840 if (r != null && r.thread != null) {
3841 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003842 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3843 if (r.persistent) {
3844 firstPids.add(pid);
3845 } else {
3846 lastPids.put(pid, Boolean.TRUE);
3847 }
3848 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 }
3851 }
3852
Dan Egnor42471dd2010-01-07 17:25:22 -08003853 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003854 StringBuilder info = mStringBuilder;
3855 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003856 info.append("ANR in ").append(app.processName);
3857 if (activity != null && activity.shortComponentName != null) {
3858 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003859 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003860 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003862 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003864 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003865 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867
Dianne Hackborn287952c2010-09-22 22:34:31 -07003868 final ProcessStats processStats = new ProcessStats(true);
3869
3870 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3871
Dan Egnor42471dd2010-01-07 17:25:22 -08003872 String cpuInfo = null;
3873 if (MONITOR_CPU_USAGE) {
3874 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003875 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003876 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003877 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003878 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003879 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 }
3881
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003882 info.append(processStats.printCurrentState(anrTime));
3883
Joe Onorato8a9b2202010-02-26 18:56:32 -08003884 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003885 if (tracesFile == null) {
3886 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3887 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3888 }
3889
Jeff Sharkeya353d262011-10-28 11:12:06 -07003890 addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
3891 cpuInfo, tracesFile, null);
Dan Egnor42471dd2010-01-07 17:25:22 -08003892
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003893 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003895 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3896 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003898 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3899 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900 }
3901 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003902 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 }
3904 }
3905
Dan Egnor42471dd2010-01-07 17:25:22 -08003906 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3907 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3908 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003909
3910 synchronized (this) {
3911 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003912 Slog.w(TAG, "Killing " + app + ": background ANR");
3913 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3914 app.processName, app.setAdj, "background ANR");
3915 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003916 return;
3917 }
3918
3919 // Set the app's notResponding state, and look up the errorReportReceiver
3920 makeAppNotRespondingLocked(app,
3921 activity != null ? activity.shortComponentName : null,
3922 annotation != null ? "ANR " + annotation : "ANR",
3923 info.toString());
3924
3925 // Bring up the infamous App Not Responding dialog
3926 Message msg = Message.obtain();
3927 HashMap map = new HashMap();
3928 msg.what = SHOW_NOT_RESPONDING_MSG;
3929 msg.obj = map;
3930 map.put("app", app);
3931 if (activity != null) {
3932 map.put("activity", activity);
3933 }
3934
3935 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 }
3938
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003939 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3940 if (!mLaunchWarningShown) {
3941 mLaunchWarningShown = true;
3942 mHandler.post(new Runnable() {
3943 @Override
3944 public void run() {
3945 synchronized (ActivityManagerService.this) {
3946 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3947 d.show();
3948 mHandler.postDelayed(new Runnable() {
3949 @Override
3950 public void run() {
3951 synchronized (ActivityManagerService.this) {
3952 d.dismiss();
3953 mLaunchWarningShown = false;
3954 }
3955 }
3956 }, 4000);
3957 }
3958 }
3959 });
3960 }
3961 }
3962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 public boolean clearApplicationUserData(final String packageName,
3964 final IPackageDataObserver observer) {
3965 int uid = Binder.getCallingUid();
3966 int pid = Binder.getCallingPid();
3967 long callingId = Binder.clearCallingIdentity();
3968 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003969 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 int pkgUid = -1;
3971 synchronized(this) {
3972 try {
3973 pkgUid = pm.getPackageUid(packageName);
3974 } catch (RemoteException e) {
3975 }
3976 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003977 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 return false;
3979 }
3980 if (uid == pkgUid || checkComponentPermission(
3981 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003982 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003984 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003985 } else {
3986 throw new SecurityException(pid+" does not have permission:"+
3987 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3988 "for process:"+packageName);
3989 }
3990 }
3991
3992 try {
3993 //clear application user data
3994 pm.clearApplicationUserData(packageName, observer);
3995 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3996 Uri.fromParts("package", packageName, null));
3997 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003998 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3999 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 } catch (RemoteException e) {
4001 }
4002 } finally {
4003 Binder.restoreCallingIdentity(callingId);
4004 }
4005 return true;
4006 }
4007
Dianne Hackborn03abb812010-01-04 18:43:19 -08004008 public void killBackgroundProcesses(final String packageName) {
4009 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4010 != PackageManager.PERMISSION_GRANTED &&
4011 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4012 != PackageManager.PERMISSION_GRANTED) {
4013 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 + Binder.getCallingPid()
4015 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004016 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 throw new SecurityException(msg);
4019 }
4020
4021 long callingId = Binder.clearCallingIdentity();
4022 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004023 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 int pkgUid = -1;
4025 synchronized(this) {
4026 try {
4027 pkgUid = pm.getPackageUid(packageName);
4028 } catch (RemoteException e) {
4029 }
4030 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004031 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 return;
4033 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004034 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004035 ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
4036 }
4037 } finally {
4038 Binder.restoreCallingIdentity(callingId);
4039 }
4040 }
4041
4042 public void killAllBackgroundProcesses() {
4043 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4044 != PackageManager.PERMISSION_GRANTED) {
4045 String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
4046 + Binder.getCallingPid()
4047 + ", uid=" + Binder.getCallingUid()
4048 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
4049 Slog.w(TAG, msg);
4050 throw new SecurityException(msg);
4051 }
4052
4053 long callingId = Binder.clearCallingIdentity();
4054 try {
4055 synchronized(this) {
4056 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
4057 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
4058 final int NA = apps.size();
4059 for (int ia=0; ia<NA; ia++) {
4060 ProcessRecord app = apps.valueAt(ia);
4061 if (app.persistent) {
4062 // we don't kill persistent processes
4063 continue;
4064 }
4065 if (app.removed) {
4066 procs.add(app);
4067 } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
4068 app.removed = true;
4069 procs.add(app);
4070 }
4071 }
4072 }
4073
4074 int N = procs.size();
4075 for (int i=0; i<N; i++) {
4076 removeProcessLocked(procs.get(i), false, true, "kill all background");
4077 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004078 }
4079 } finally {
4080 Binder.restoreCallingIdentity(callingId);
4081 }
4082 }
4083
4084 public void forceStopPackage(final String packageName) {
4085 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4086 != PackageManager.PERMISSION_GRANTED) {
4087 String msg = "Permission Denial: forceStopPackage() from pid="
4088 + Binder.getCallingPid()
4089 + ", uid=" + Binder.getCallingUid()
4090 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004091 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004092 throw new SecurityException(msg);
4093 }
4094
4095 long callingId = Binder.clearCallingIdentity();
4096 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004097 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08004098 int pkgUid = -1;
4099 synchronized(this) {
4100 try {
4101 pkgUid = pm.getPackageUid(packageName);
4102 } catch (RemoteException e) {
4103 }
4104 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004105 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004106 return;
4107 }
4108 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08004109 try {
4110 pm.setPackageStoppedState(packageName, true);
4111 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08004112 } catch (IllegalArgumentException e) {
4113 Slog.w(TAG, "Failed trying to unstop package "
4114 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08004115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 }
4117 } finally {
4118 Binder.restoreCallingIdentity(callingId);
4119 }
4120 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004121
4122 /*
4123 * The pkg name and uid have to be specified.
4124 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4125 */
4126 public void killApplicationWithUid(String pkg, int uid) {
4127 if (pkg == null) {
4128 return;
4129 }
4130 // Make sure the uid is valid.
4131 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004132 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004133 return;
4134 }
4135 int callerUid = Binder.getCallingUid();
4136 // Only the system server can kill an application
4137 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004138 // Post an aysnc message to kill the application
4139 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4140 msg.arg1 = uid;
4141 msg.arg2 = 0;
4142 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004143 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004144 } else {
4145 throw new SecurityException(callerUid + " cannot kill pkg: " +
4146 pkg);
4147 }
4148 }
4149
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004150 public void closeSystemDialogs(String reason) {
4151 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004152 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004153 if (reason != null) {
4154 intent.putExtra("reason", reason);
4155 }
4156
4157 final int uid = Binder.getCallingUid();
4158 final long origId = Binder.clearCallingIdentity();
4159 synchronized (this) {
4160 int i = mWatchers.beginBroadcast();
4161 while (i > 0) {
4162 i--;
4163 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4164 if (w != null) {
4165 try {
4166 w.closingSystemDialogs(reason);
4167 } catch (RemoteException e) {
4168 }
4169 }
4170 }
4171 mWatchers.finishBroadcast();
4172
Dianne Hackbornffa42482009-09-23 22:20:11 -07004173 mWindowManager.closeSystemDialogs(reason);
4174
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004175 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
4176 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07004177 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004178 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07004179 Activity.RESULT_CANCELED, null, "close-sys");
4180 }
4181 }
4182
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004183 broadcastIntentLocked(null, null, intent, null,
4184 null, 0, null, null, null, false, false, -1, uid);
4185 }
4186 Binder.restoreCallingIdentity(origId);
4187 }
4188
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004189 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004190 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004191 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4192 for (int i=pids.length-1; i>=0; i--) {
4193 infos[i] = new Debug.MemoryInfo();
4194 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004195 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004196 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004197 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004198
Dianne Hackbornb437e092011-08-05 17:50:29 -07004199 public long[] getProcessPss(int[] pids) throws RemoteException {
4200 long[] pss = new long[pids.length];
4201 for (int i=pids.length-1; i>=0; i--) {
4202 pss[i] = Debug.getPss(pids[i]);
4203 }
4204 return pss;
4205 }
4206
Christopher Tate5e1ab332009-09-01 20:32:49 -07004207 public void killApplicationProcess(String processName, int uid) {
4208 if (processName == null) {
4209 return;
4210 }
4211
4212 int callerUid = Binder.getCallingUid();
4213 // Only the system server can kill an application
4214 if (callerUid == Process.SYSTEM_UID) {
4215 synchronized (this) {
4216 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07004217 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07004218 try {
4219 app.thread.scheduleSuicide();
4220 } catch (RemoteException e) {
4221 // If the other end already died, then our work here is done.
4222 }
4223 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004224 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07004225 + processName + " / " + uid);
4226 }
4227 }
4228 } else {
4229 throw new SecurityException(callerUid + " cannot kill app process: " +
4230 processName);
4231 }
4232 }
4233
Dianne Hackborn03abb812010-01-04 18:43:19 -08004234 private void forceStopPackageLocked(final String packageName, int uid) {
Christopher Tate3dacd842011-08-19 14:56:15 -07004235 forceStopPackageLocked(packageName, uid, false, false, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4237 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004238 if (!mProcessesReady) {
4239 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
4240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 intent.putExtra(Intent.EXTRA_UID, uid);
4242 broadcastIntentLocked(null, null, intent,
4243 null, null, 0, null, null, null,
4244 false, false, MY_PID, Process.SYSTEM_UID);
4245 }
4246
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004247 private final boolean killPackageProcessesLocked(String packageName, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07004248 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004249 boolean evenPersistent, String reason) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004250 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251
Dianne Hackborn03abb812010-01-04 18:43:19 -08004252 // Remove all processes this package may have touched: all with the
4253 // same UID (except for the system or root user), and all whose name
4254 // matches the package name.
4255 final String procNamePrefix = packageName + ":";
4256 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
4257 final int NA = apps.size();
4258 for (int ia=0; ia<NA; ia++) {
4259 ProcessRecord app = apps.valueAt(ia);
Christopher Tate3dacd842011-08-19 14:56:15 -07004260 if (app.persistent && !evenPersistent) {
Christopher Tate064d8422011-07-26 15:38:07 -07004261 // we don't kill persistent processes
4262 continue;
4263 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004264 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004265 if (doit) {
4266 procs.add(app);
4267 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004268 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
4269 || app.processName.equals(packageName)
4270 || app.processName.startsWith(procNamePrefix)) {
4271 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004272 if (!doit) {
4273 return true;
4274 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004275 app.removed = true;
4276 procs.add(app);
4277 }
4278 }
4279 }
4280 }
4281
4282 int N = procs.size();
4283 for (int i=0; i<N; i++) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004284 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004285 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004286 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08004287 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004288
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004289 private final boolean forceStopPackageLocked(String name, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07004290 boolean callerWillRestart, boolean purgeCache, boolean doit,
4291 boolean evenPersistent) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07004292 int i;
4293 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 if (uid < 0) {
4296 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004297 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 } catch (RemoteException e) {
4299 }
4300 }
4301
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004302 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004303 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004304
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004305 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
4306 while (badApps.hasNext()) {
4307 SparseArray<Long> ba = badApps.next();
4308 if (ba.get(uid) != null) {
4309 badApps.remove();
4310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 }
4312 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004313
4314 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004315 callerWillRestart, false, doit, evenPersistent, "force stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004317 TaskRecord lastTask = null;
4318 for (i=0; i<mMainStack.mHistory.size(); i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004319 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004320 final boolean samePackage = r.packageName.equals(name);
4321 if ((samePackage || r.task == lastTask)
Christopher Tate3dacd842011-08-19 14:56:15 -07004322 && (r.app == null || evenPersistent || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004323 if (!doit) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004324 if (r.finishing) {
4325 // If this activity is just finishing, then it is not
4326 // interesting as far as something to stop.
4327 continue;
4328 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004329 return true;
4330 }
4331 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004332 Slog.i(TAG, " Force finishing activity " + r);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004333 if (samePackage) {
4334 if (r.app != null) {
4335 r.app.removed = true;
4336 }
4337 r.app = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 }
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07004339 lastTask = r.task;
4340 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
4341 null, "force-stop")) {
4342 i--;
4343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
4345 }
4346
4347 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
4348 for (ServiceRecord service : mServices.values()) {
Christopher Tate064d8422011-07-26 15:38:07 -07004349 if (service.packageName.equals(name)
Christopher Tate3dacd842011-08-19 14:56:15 -07004350 && (service.app == null || evenPersistent || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004351 if (!doit) {
4352 return true;
4353 }
4354 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004355 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 if (service.app != null) {
4357 service.app.removed = true;
4358 }
4359 service.app = null;
4360 services.add(service);
4361 }
4362 }
4363
4364 N = services.size();
4365 for (i=0; i<N; i++) {
4366 bringDownServiceLocked(services.get(i), true);
4367 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07004368
4369 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
4370 for (ContentProviderRecord provider : mProvidersByClass.values()) {
4371 if (provider.info.packageName.equals(name)
4372 && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
4373 if (!doit) {
4374 return true;
4375 }
4376 didSomething = true;
4377 providers.add(provider);
4378 }
4379 }
4380
4381 N = providers.size();
4382 for (i=0; i<N; i++) {
4383 removeDyingProviderLocked(null, providers.get(i));
4384 }
4385
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004386 if (doit) {
4387 if (purgeCache) {
4388 AttributeCache ac = AttributeCache.instance();
4389 if (ac != null) {
4390 ac.removePackage(name);
4391 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004392 }
Dianne Hackborn38cc8962011-10-13 11:33:55 -07004393 if (mBooted) {
4394 mMainStack.resumeTopActivityLocked(null);
4395 mMainStack.scheduleIdleLocked();
4396 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004397 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004398
4399 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 }
4401
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004402 private final boolean removeProcessLocked(ProcessRecord app,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004403 boolean callerWillRestart, boolean allowRestart, String reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 final String name = app.processName;
4405 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004406 if (DEBUG_PROCESSES) Slog.d(
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004407 TAG, "Force removing proc " + app.toShortString() + " (" + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 + "/" + uid + ")");
4409
4410 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004411 if (mHeavyWeightProcess == app) {
4412 mHeavyWeightProcess = null;
4413 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 boolean needRestart = false;
4416 if (app.pid > 0 && app.pid != MY_PID) {
4417 int pid = app.pid;
4418 synchronized (mPidsSelfLocked) {
4419 mPidsSelfLocked.remove(pid);
4420 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4421 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004422 Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004423 handleAppDiedLocked(app, true, allowRestart);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004424 mLruProcesses.remove(app);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08004425 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426
4427 if (app.persistent) {
4428 if (!callerWillRestart) {
4429 addAppLocked(app.info);
4430 } else {
4431 needRestart = true;
4432 }
4433 }
4434 } else {
4435 mRemovedProcesses.add(app);
4436 }
4437
4438 return needRestart;
4439 }
4440
4441 private final void processStartTimedOutLocked(ProcessRecord app) {
4442 final int pid = app.pid;
4443 boolean gone = false;
4444 synchronized (mPidsSelfLocked) {
4445 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
4446 if (knownApp != null && knownApp.thread == null) {
4447 mPidsSelfLocked.remove(pid);
4448 gone = true;
4449 }
4450 }
4451
4452 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004453 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004454 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004455 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004457 if (mHeavyWeightProcess == app) {
4458 mHeavyWeightProcess = null;
4459 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4460 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004461 // Take care of any launching providers waiting for this process.
4462 checkAppInLaunchingProvidersLocked(app, true);
4463 // Take care of any services that are waiting for the process.
4464 for (int i=0; i<mPendingServices.size(); i++) {
4465 ServiceRecord sr = mPendingServices.get(i);
4466 if (app.info.uid == sr.appInfo.uid
4467 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004468 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004469 mPendingServices.remove(i);
4470 i--;
4471 bringDownServiceLocked(sr, true);
4472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004474 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
4475 app.processName, app.setAdj, "start timeout");
4476 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07004477 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004478 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07004479 try {
4480 IBackupManager bm = IBackupManager.Stub.asInterface(
4481 ServiceManager.getService(Context.BACKUP_SERVICE));
4482 bm.agentDisconnected(app.info.packageName);
4483 } catch (RemoteException e) {
4484 // Can't happen; the backup manager is local
4485 }
4486 }
Christopher Tatef46723b2012-01-26 14:19:24 -08004487 if (isPendingBroadcastProcessLocked(pid)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Christopher Tatef46723b2012-01-26 14:19:24 -08004489 skipPendingBroadcastLocked(pid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08004490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004492 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 }
4494 }
4495
4496 private final boolean attachApplicationLocked(IApplicationThread thread,
4497 int pid) {
4498
4499 // Find the application record that is being attached... either via
4500 // the pid if we are running in multiple processes, or just pull the
4501 // next app record if we are emulating process with anonymous threads.
4502 ProcessRecord app;
4503 if (pid != MY_PID && pid >= 0) {
4504 synchronized (mPidsSelfLocked) {
4505 app = mPidsSelfLocked.get(pid);
4506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 } else {
4508 app = null;
4509 }
4510
4511 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004512 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004514 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004516 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004517 } else {
4518 try {
4519 thread.scheduleExit();
4520 } catch (Exception e) {
4521 // Ignore exceptions.
4522 }
4523 }
4524 return false;
4525 }
4526
4527 // If this application record is still attached to a previous
4528 // process, clean it up now.
4529 if (app.thread != null) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004530 handleAppDiedLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 }
4532
4533 // Tell the process all about itself.
4534
Joe Onorato8a9b2202010-02-26 18:56:32 -08004535 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 TAG, "Binding process pid " + pid + " to record " + app);
4537
4538 String processName = app.processName;
4539 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07004540 AppDeathRecipient adr = new AppDeathRecipient(
4541 app, pid, thread);
4542 thread.asBinder().linkToDeath(adr, 0);
4543 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 } catch (RemoteException e) {
4545 app.resetPackageList();
4546 startProcessLocked(app, "link fail", processName);
4547 return false;
4548 }
4549
Doug Zongker2bec3d42009-12-04 12:52:44 -08004550 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551
4552 app.thread = thread;
4553 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08004554 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
4555 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 app.forcingToForeground = null;
4557 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07004558 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 app.debugging = false;
4560
4561 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4562
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004563 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004564 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004566 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004568 }
4569
Joe Onorato8a9b2202010-02-26 18:56:32 -08004570 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 TAG, "New app record " + app
4572 + " thread=" + thread.asBinder() + " pid=" + pid);
4573 try {
4574 int testMode = IApplicationThread.DEBUG_OFF;
4575 if (mDebugApp != null && mDebugApp.equals(processName)) {
4576 testMode = mWaitForDebugger
4577 ? IApplicationThread.DEBUG_WAIT
4578 : IApplicationThread.DEBUG_ON;
4579 app.debugging = true;
4580 if (mDebugTransient) {
4581 mDebugApp = mOrigDebugApp;
4582 mWaitForDebugger = mOrigWaitForDebugger;
4583 }
4584 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004585 String profileFile = app.instrumentationProfileFile;
4586 ParcelFileDescriptor profileFd = null;
4587 boolean profileAutoStop = false;
4588 if (mProfileApp != null && mProfileApp.equals(processName)) {
4589 mProfileProc = app;
4590 profileFile = mProfileFile;
4591 profileFd = mProfileFd;
4592 profileAutoStop = mAutoStopProfiler;
4593 }
4594
Christopher Tate181fafa2009-05-14 11:12:14 -07004595 // If the app is being launched for restore or full backup, set it up specially
4596 boolean isRestrictedBackupMode = false;
4597 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
4598 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07004599 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07004600 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
4601 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004602
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07004603 ensurePackageDexOpt(app.instrumentationInfo != null
4604 ? app.instrumentationInfo.packageName
4605 : app.info.packageName);
4606 if (app.instrumentationClass != null) {
4607 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004608 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004609 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07004610 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004611 ApplicationInfo appInfo = app.instrumentationInfo != null
4612 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07004613 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004614 if (profileFd != null) {
4615 profileFd = profileFd.dup();
4616 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004617 thread.bindApplication(processName, appInfo, providers,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004618 app.instrumentationClass, profileFile, profileFd, profileAutoStop,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn5d927c22011-09-02 12:22:18 -07004620 isRestrictedBackupMode || !normalMode, app.persistent,
Dianne Hackborn813075a62011-11-14 17:45:19 -08004621 new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08004622 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004623 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004624 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 } catch (Exception e) {
4626 // todo: Yikes! What should we do? For now we will try to
4627 // start another process, but that could easily get us in
4628 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004629 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630
4631 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07004632 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 startProcessLocked(app, "bind fail", processName);
4634 return false;
4635 }
4636
4637 // Remove this record from the list of starting applications.
4638 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004639 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
4640 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 mProcessesOnHold.remove(app);
4642
4643 boolean badApp = false;
4644 boolean didSomething = false;
4645
4646 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004647 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07004648 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
4650 && processName.equals(hr.processName)) {
4651 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004652 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 didSomething = true;
4654 }
4655 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004656 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 + hr.intent.getComponent().flattenToShortString(), e);
4658 badApp = true;
4659 }
4660 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004661 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 }
4663 }
4664
4665 // Find any services that should be running in this process...
4666 if (!badApp && mPendingServices.size() > 0) {
4667 ServiceRecord sr = null;
4668 try {
4669 for (int i=0; i<mPendingServices.size(); i++) {
4670 sr = mPendingServices.get(i);
4671 if (app.info.uid != sr.appInfo.uid
4672 || !processName.equals(sr.processName)) {
4673 continue;
4674 }
4675
4676 mPendingServices.remove(i);
4677 i--;
4678 realStartServiceLocked(sr, app);
4679 didSomething = true;
4680 }
4681 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004682 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683 + sr.shortName, e);
4684 badApp = true;
4685 }
4686 }
4687
Christopher Tatef46723b2012-01-26 14:19:24 -08004688 // Check if a next-broadcast receiver is in this process...
4689 if (!badApp && isPendingBroadcastProcessLocked(pid)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004690 try {
Christopher Tatef46723b2012-01-26 14:19:24 -08004691 didSomething = sendPendingBroadcastsLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 } catch (Exception e) {
Christopher Tatef46723b2012-01-26 14:19:24 -08004693 // If the app died trying to launch the receiver we declare it 'bad'
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 badApp = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 }
4696 }
4697
Christopher Tate181fafa2009-05-14 11:12:14 -07004698 // Check whether the next backup agent is in this process...
4699 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004700 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004701 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07004702 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004703 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
4704 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
4705 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07004706 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004707 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07004708 e.printStackTrace();
4709 }
4710 }
4711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 if (badApp) {
4713 // todo: Also need to kill application to deal with all
4714 // kinds of exceptions.
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004715 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 return false;
4717 }
4718
4719 if (!didSomething) {
4720 updateOomAdjLocked();
4721 }
4722
4723 return true;
4724 }
4725
4726 public final void attachApplication(IApplicationThread thread) {
4727 synchronized (this) {
4728 int callingPid = Binder.getCallingPid();
4729 final long origId = Binder.clearCallingIdentity();
4730 attachApplicationLocked(thread, callingPid);
4731 Binder.restoreCallingIdentity(origId);
4732 }
4733 }
4734
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004735 public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004737 ActivityRecord r = mMainStack.activityIdleInternal(token, false, config);
4738 if (stopProfiling) {
4739 synchronized (this) {
4740 if (mProfileProc == r.app) {
4741 if (mProfileFd != null) {
4742 try {
4743 mProfileFd.close();
4744 } catch (IOException e) {
4745 }
4746 clearProfilerLocked();
4747 }
4748 }
4749 }
4750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751 Binder.restoreCallingIdentity(origId);
4752 }
4753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08004755 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004756 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 mWindowManager.enableScreenAfterBoot();
4758 }
4759
Dianne Hackborn661cd522011-08-22 00:26:20 -07004760 public void showBootMessage(final CharSequence msg, final boolean always) {
4761 mWindowManager.showBootMessage(msg, always);
4762 }
4763
Dianne Hackborn90c52de2011-09-23 12:57:44 -07004764 public void dismissKeyguardOnNextActivity() {
4765 synchronized (this) {
4766 mMainStack.dismissKeyguardOnNextActivityLocked();
4767 }
4768 }
4769
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004770 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004771 IntentFilter pkgFilter = new IntentFilter();
4772 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
4773 pkgFilter.addDataScheme("package");
4774 mContext.registerReceiver(new BroadcastReceiver() {
4775 @Override
4776 public void onReceive(Context context, Intent intent) {
4777 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4778 if (pkgs != null) {
4779 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004780 synchronized (ActivityManagerService.this) {
Christopher Tate3dacd842011-08-19 14:56:15 -07004781 if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004782 setResultCode(Activity.RESULT_OK);
4783 return;
4784 }
4785 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004786 }
4787 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004788 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004789 }, pkgFilter);
4790
4791 synchronized (this) {
4792 // Ensure that any processes we had put on hold are now started
4793 // up.
4794 final int NP = mProcessesOnHold.size();
4795 if (NP > 0) {
4796 ArrayList<ProcessRecord> procs =
4797 new ArrayList<ProcessRecord>(mProcessesOnHold);
4798 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004799 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
4800 + procs.get(ip));
4801 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004802 }
4803 }
4804
4805 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07004806 // Start looking for apps that are abusing wake locks.
4807 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07004808 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004809 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07004810 SystemProperties.set("sys.boot_completed", "1");
Guang Zhu191713a2012-01-12 12:02:22 -08004811 SystemProperties.set("dev.bootcomplete", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004812 broadcastIntentLocked(null, null,
4813 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
4814 null, null, 0, null, null,
4815 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
4816 false, false, MY_PID, Process.SYSTEM_UID);
4817 }
4818 }
4819 }
4820
4821 final void ensureBootCompleted() {
4822 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004823 boolean enableScreen;
4824 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004825 booting = mBooting;
4826 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004827 enableScreen = !mBooted;
4828 mBooted = true;
4829 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004830
4831 if (booting) {
4832 finishBooting();
4833 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004834
4835 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004836 enableScreenAfterBoot();
4837 }
4838 }
4839
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004840 public final void activityPaused(IBinder token) {
4841 final long origId = Binder.clearCallingIdentity();
4842 mMainStack.activityPaused(token, false);
4843 Binder.restoreCallingIdentity(origId);
4844 }
4845
4846 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
4847 CharSequence description) {
4848 if (localLOGV) Slog.v(
4849 TAG, "Activity stopped: token=" + token);
4850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 // Refuse possible leaked file descriptors
4852 if (icicle != null && icicle.hasFileDescriptors()) {
4853 throw new IllegalArgumentException("File descriptors passed in Bundle");
4854 }
4855
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004856 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857
4858 final long origId = Binder.clearCallingIdentity();
4859
4860 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004861 r = mMainStack.isInStackLocked(token);
4862 if (r != null) {
4863 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864 }
4865 }
4866
4867 if (r != null) {
4868 sendPendingThumbnail(r, null, null, null, false);
4869 }
4870
4871 trimApplications();
4872
4873 Binder.restoreCallingIdentity(origId);
4874 }
4875
4876 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004877 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004878 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 }
4880
4881 public String getCallingPackage(IBinder token) {
4882 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004883 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07004884 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 }
4886 }
4887
4888 public ComponentName getCallingActivity(IBinder token) {
4889 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004890 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 return r != null ? r.intent.getComponent() : null;
4892 }
4893 }
4894
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004895 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004896 ActivityRecord r = mMainStack.isInStackLocked(token);
4897 if (r == null) {
4898 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004900 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 }
4902
4903 public ComponentName getActivityClassForToken(IBinder token) {
4904 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004905 ActivityRecord r = mMainStack.isInStackLocked(token);
4906 if (r == null) {
4907 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004909 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 }
4911 }
4912
4913 public String getPackageForToken(IBinder token) {
4914 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004915 ActivityRecord r = mMainStack.isInStackLocked(token);
4916 if (r == null) {
4917 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004919 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 }
4921 }
4922
4923 public IIntentSender getIntentSender(int type,
4924 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004925 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004927 if (intents != null) {
4928 if (intents.length < 1) {
4929 throw new IllegalArgumentException("Intents array length must be >= 1");
4930 }
4931 for (int i=0; i<intents.length; i++) {
4932 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004933 if (intent != null) {
4934 if (intent.hasFileDescriptors()) {
4935 throw new IllegalArgumentException("File descriptors passed in Intent");
4936 }
4937 if (type == INTENT_SENDER_BROADCAST &&
4938 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4939 throw new IllegalArgumentException(
4940 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4941 }
4942 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004943 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004944 }
4945 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004946 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004947 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004948 }
4949 }
4950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 synchronized(this) {
4952 int callingUid = Binder.getCallingUid();
4953 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004954 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004955 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 .getPackageUid(packageName);
4957 if (uid != Binder.getCallingUid()) {
4958 String msg = "Permission Denial: getIntentSender() from pid="
4959 + Binder.getCallingPid()
4960 + ", uid=" + Binder.getCallingUid()
4961 + ", (need uid=" + uid + ")"
4962 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004963 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 throw new SecurityException(msg);
4965 }
4966 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004967
4968 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004969 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 } catch (RemoteException e) {
4972 throw new SecurityException(e);
4973 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004974 }
4975 }
4976
4977 IIntentSender getIntentSenderLocked(int type,
4978 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004979 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004980 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004981 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004982 activity = mMainStack.isInStackLocked(token);
4983 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004984 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004986 if (activity.finishing) {
4987 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004989 }
4990
4991 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4992 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4993 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4994 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4995 |PendingIntent.FLAG_UPDATE_CURRENT);
4996
4997 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4998 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004999 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005000 WeakReference<PendingIntentRecord> ref;
5001 ref = mIntentSenderRecords.get(key);
5002 PendingIntentRecord rec = ref != null ? ref.get() : null;
5003 if (rec != null) {
5004 if (!cancelCurrent) {
5005 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005006 if (rec.key.requestIntent != null) {
5007 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
5008 }
5009 if (intents != null) {
5010 intents[intents.length-1] = rec.key.requestIntent;
5011 rec.key.allIntents = intents;
5012 rec.key.allResolvedTypes = resolvedTypes;
5013 } else {
5014 rec.key.allIntents = null;
5015 rec.key.allResolvedTypes = null;
5016 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 return rec;
5019 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005020 rec.canceled = true;
5021 mIntentSenderRecords.remove(key);
5022 }
5023 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 return rec;
5025 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005026 rec = new PendingIntentRecord(this, key, callingUid);
5027 mIntentSenderRecords.put(key, rec.ref);
5028 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5029 if (activity.pendingResults == null) {
5030 activity.pendingResults
5031 = new HashSet<WeakReference<PendingIntentRecord>>();
5032 }
5033 activity.pendingResults.add(rec.ref);
5034 }
5035 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 }
5037
5038 public void cancelIntentSender(IIntentSender sender) {
5039 if (!(sender instanceof PendingIntentRecord)) {
5040 return;
5041 }
5042 synchronized(this) {
5043 PendingIntentRecord rec = (PendingIntentRecord)sender;
5044 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005045 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 .getPackageUid(rec.key.packageName);
5047 if (uid != Binder.getCallingUid()) {
5048 String msg = "Permission Denial: cancelIntentSender() from pid="
5049 + Binder.getCallingPid()
5050 + ", uid=" + Binder.getCallingUid()
5051 + " is not allowed to cancel packges "
5052 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005053 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 throw new SecurityException(msg);
5055 }
5056 } catch (RemoteException e) {
5057 throw new SecurityException(e);
5058 }
5059 cancelIntentSenderLocked(rec, true);
5060 }
5061 }
5062
5063 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5064 rec.canceled = true;
5065 mIntentSenderRecords.remove(rec.key);
5066 if (cleanActivity && rec.key.activity != null) {
5067 rec.key.activity.pendingResults.remove(rec.ref);
5068 }
5069 }
5070
5071 public String getPackageForIntentSender(IIntentSender pendingResult) {
5072 if (!(pendingResult instanceof PendingIntentRecord)) {
5073 return null;
5074 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07005075 try {
5076 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5077 return res.key.packageName;
5078 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 }
5080 return null;
5081 }
5082
Dianne Hackborn6c418d52011-06-29 14:05:33 -07005083 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
5084 if (!(pendingResult instanceof PendingIntentRecord)) {
5085 return false;
5086 }
5087 try {
5088 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5089 if (res.key.allIntents == null) {
5090 return false;
5091 }
5092 for (int i=0; i<res.key.allIntents.length; i++) {
5093 Intent intent = res.key.allIntents[i];
5094 if (intent.getPackage() != null && intent.getComponent() != null) {
5095 return false;
5096 }
5097 }
5098 return true;
5099 } catch (ClassCastException e) {
5100 }
5101 return false;
5102 }
5103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 public void setProcessLimit(int max) {
5105 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5106 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005107 synchronized (this) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07005108 mProcessLimit = max < 0 ? ProcessList.MAX_HIDDEN_APPS : max;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005109 mProcessLimitOverride = max;
5110 }
5111 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
5113
5114 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005115 synchronized (this) {
5116 return mProcessLimitOverride;
5117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 }
5119
5120 void foregroundTokenDied(ForegroundToken token) {
5121 synchronized (ActivityManagerService.this) {
5122 synchronized (mPidsSelfLocked) {
5123 ForegroundToken cur
5124 = mForegroundProcesses.get(token.pid);
5125 if (cur != token) {
5126 return;
5127 }
5128 mForegroundProcesses.remove(token.pid);
5129 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5130 if (pr == null) {
5131 return;
5132 }
5133 pr.forcingToForeground = null;
5134 pr.foregroundServices = false;
5135 }
5136 updateOomAdjLocked();
5137 }
5138 }
5139
5140 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5141 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5142 "setProcessForeground()");
5143 synchronized(this) {
5144 boolean changed = false;
5145
5146 synchronized (mPidsSelfLocked) {
5147 ProcessRecord pr = mPidsSelfLocked.get(pid);
5148 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005149 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 return;
5151 }
5152 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5153 if (oldToken != null) {
5154 oldToken.token.unlinkToDeath(oldToken, 0);
5155 mForegroundProcesses.remove(pid);
5156 pr.forcingToForeground = null;
5157 changed = true;
5158 }
5159 if (isForeground && token != null) {
5160 ForegroundToken newToken = new ForegroundToken() {
5161 public void binderDied() {
5162 foregroundTokenDied(this);
5163 }
5164 };
5165 newToken.pid = pid;
5166 newToken.token = token;
5167 try {
5168 token.linkToDeath(newToken, 0);
5169 mForegroundProcesses.put(pid, newToken);
5170 pr.forcingToForeground = token;
5171 changed = true;
5172 } catch (RemoteException e) {
5173 // If the process died while doing this, we will later
5174 // do the cleanup with the process death link.
5175 }
5176 }
5177 }
5178
5179 if (changed) {
5180 updateOomAdjLocked();
5181 }
5182 }
5183 }
5184
5185 // =========================================================
5186 // PERMISSIONS
5187 // =========================================================
5188
5189 static class PermissionController extends IPermissionController.Stub {
5190 ActivityManagerService mActivityManagerService;
5191 PermissionController(ActivityManagerService activityManagerService) {
5192 mActivityManagerService = activityManagerService;
5193 }
5194
5195 public boolean checkPermission(String permission, int pid, int uid) {
5196 return mActivityManagerService.checkPermission(permission, pid,
5197 uid) == PackageManager.PERMISSION_GRANTED;
5198 }
5199 }
5200
5201 /**
5202 * This can be called with or without the global lock held.
5203 */
5204 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005205 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 // We might be performing an operation on behalf of an indirect binder
5207 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
5208 // client identity accordingly before proceeding.
5209 Identity tlsIdentity = sCallerIdentity.get();
5210 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005211 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
5213 uid = tlsIdentity.uid;
5214 pid = tlsIdentity.pid;
5215 }
5216
5217 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07005218 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 return PackageManager.PERMISSION_GRANTED;
5220 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005221 // If there is a uid that owns whatever is being accessed, it has
5222 // blanket access to it regardless of the permissions it requires.
5223 if (owningUid >= 0 && uid == owningUid) {
5224 return PackageManager.PERMISSION_GRANTED;
5225 }
5226 // If the target is not exported, then nobody else can get to it.
5227 if (!exported) {
5228 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 return PackageManager.PERMISSION_DENIED;
5230 }
5231 if (permission == null) {
5232 return PackageManager.PERMISSION_GRANTED;
5233 }
5234 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005235 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 .checkUidPermission(permission, uid);
5237 } catch (RemoteException e) {
5238 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005239 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 }
5241 return PackageManager.PERMISSION_DENIED;
5242 }
5243
5244 /**
5245 * As the only public entry point for permissions checking, this method
5246 * can enforce the semantic that requesting a check on a null global
5247 * permission is automatically denied. (Internally a null permission
5248 * string is used when calling {@link #checkComponentPermission} in cases
5249 * when only uid-based security is needed.)
5250 *
5251 * This can be called with or without the global lock held.
5252 */
5253 public int checkPermission(String permission, int pid, int uid) {
5254 if (permission == null) {
5255 return PackageManager.PERMISSION_DENIED;
5256 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005257 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 }
5259
5260 /**
5261 * Binder IPC calls go through the public entry point.
5262 * This can be called with or without the global lock held.
5263 */
5264 int checkCallingPermission(String permission) {
5265 return checkPermission(permission,
5266 Binder.getCallingPid(),
5267 Binder.getCallingUid());
5268 }
5269
5270 /**
5271 * This can be called with or without the global lock held.
5272 */
5273 void enforceCallingPermission(String permission, String func) {
5274 if (checkCallingPermission(permission)
5275 == PackageManager.PERMISSION_GRANTED) {
5276 return;
5277 }
5278
5279 String msg = "Permission Denial: " + func + " from pid="
5280 + Binder.getCallingPid()
5281 + ", uid=" + Binder.getCallingUid()
5282 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005283 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 throw new SecurityException(msg);
5285 }
5286
5287 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07005288 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
5289 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
5290 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
5291 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5292 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07005294 // Is the component private from the target uid?
5295 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
5296
5297 // Acceptable if the there is no read permission needed from the
5298 // target or the target is holding the read permission.
5299 if (!readPerm) {
5300 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07005302 == PackageManager.PERMISSION_GRANTED)) {
5303 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 }
5305 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07005306
5307 // Acceptable if the there is no write permission needed from the
5308 // target or the target is holding the read permission.
5309 if (!writePerm) {
5310 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07005312 == PackageManager.PERMISSION_GRANTED)) {
5313 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 }
5315 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07005316
5317 // Acceptable if there is a path permission matching the URI that
5318 // the target holds the permission on.
5319 PathPermission[] pps = pi.pathPermissions;
5320 if (pps != null && (!readPerm || !writePerm)) {
5321 final String path = uri.getPath();
5322 int i = pps.length;
5323 while (i > 0 && (!readPerm || !writePerm)) {
5324 i--;
5325 PathPermission pp = pps[i];
5326 if (!readPerm) {
5327 final String pprperm = pp.getReadPermission();
5328 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
5329 + pprperm + " for " + pp.getPath()
5330 + ": match=" + pp.match(path)
5331 + " check=" + pm.checkUidPermission(pprperm, uid));
5332 if (pprperm != null && pp.match(path) &&
5333 (pm.checkUidPermission(pprperm, uid)
5334 == PackageManager.PERMISSION_GRANTED)) {
5335 readPerm = true;
5336 }
5337 }
5338 if (!writePerm) {
5339 final String ppwperm = pp.getWritePermission();
5340 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
5341 + ppwperm + " for " + pp.getPath()
5342 + ": match=" + pp.match(path)
5343 + " check=" + pm.checkUidPermission(ppwperm, uid));
5344 if (ppwperm != null && pp.match(path) &&
5345 (pm.checkUidPermission(ppwperm, uid)
5346 == PackageManager.PERMISSION_GRANTED)) {
5347 writePerm = true;
5348 }
5349 }
5350 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07005351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 } catch (RemoteException e) {
5353 return false;
5354 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07005355
5356 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 }
5358
5359 private final boolean checkUriPermissionLocked(Uri uri, int uid,
5360 int modeFlags) {
5361 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07005362 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 return true;
5364 }
5365 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
5366 if (perms == null) return false;
5367 UriPermission perm = perms.get(uri);
5368 if (perm == null) return false;
5369 return (modeFlags&perm.modeFlags) == modeFlags;
5370 }
5371
5372 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
5373 // Another redirected-binder-call permissions check as in
5374 // {@link checkComponentPermission}.
5375 Identity tlsIdentity = sCallerIdentity.get();
5376 if (tlsIdentity != null) {
5377 uid = tlsIdentity.uid;
5378 pid = tlsIdentity.pid;
5379 }
5380
5381 // Our own process gets to do everything.
5382 if (pid == MY_PID) {
5383 return PackageManager.PERMISSION_GRANTED;
5384 }
5385 synchronized(this) {
5386 return checkUriPermissionLocked(uri, uid, modeFlags)
5387 ? PackageManager.PERMISSION_GRANTED
5388 : PackageManager.PERMISSION_DENIED;
5389 }
5390 }
5391
Dianne Hackborn39792d22010-08-19 18:01:52 -07005392 /**
5393 * Check if the targetPkg can be granted permission to access uri by
5394 * the callingUid using the given modeFlags. Throws a security exception
5395 * if callingUid is not allowed to do this. Returns the uid of the target
5396 * if the URI permission grant should be performed; returns -1 if it is not
5397 * needed (for example targetPkg already has permission to access the URI).
5398 */
5399 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
5400 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5402 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5403 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005404 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 }
5406
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005407 if (targetPkg != null) {
5408 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5409 "Checking grant " + targetPkg + " permission to " + uri);
5410 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005411
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005412 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413
5414 // If this is not a content: uri, we can't do anything with it.
5415 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005416 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005417 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07005418 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 }
5420
5421 String name = uri.getAuthority();
5422 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005423 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 if (cpr != null) {
5425 pi = cpr.info;
5426 } else {
5427 try {
5428 pi = pm.resolveContentProvider(name,
5429 PackageManager.GET_URI_PERMISSION_PATTERNS);
5430 } catch (RemoteException ex) {
5431 }
5432 }
5433 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005434 Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString());
Dianne Hackborn39792d22010-08-19 18:01:52 -07005435 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 }
5437
5438 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005439 if (targetPkg != null) {
5440 try {
5441 targetUid = pm.getPackageUid(targetPkg);
5442 if (targetUid < 0) {
5443 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5444 "Can't grant URI permission no uid for: " + targetPkg);
5445 return -1;
5446 }
5447 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005448 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005450 } else {
5451 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005452 }
5453
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005454 if (targetUid >= 0) {
5455 // First... does the target actually need this permission?
5456 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
5457 // No need to grant the target this permission.
5458 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
5459 "Target " + targetPkg + " already has full permission to " + uri);
5460 return -1;
5461 }
5462 } else {
5463 // First... there is no target package, so can anyone access it?
5464 boolean allowed = pi.exported;
5465 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5466 if (pi.readPermission != null) {
5467 allowed = false;
5468 }
5469 }
5470 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5471 if (pi.writePermission != null) {
5472 allowed = false;
5473 }
5474 }
5475 if (allowed) {
5476 return -1;
5477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 }
5479
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005480 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 if (!pi.grantUriPermissions) {
5482 throw new SecurityException("Provider " + pi.packageName
5483 + "/" + pi.name
5484 + " does not allow granting of Uri permissions (uri "
5485 + uri + ")");
5486 }
5487 if (pi.uriPermissionPatterns != null) {
5488 final int N = pi.uriPermissionPatterns.length;
5489 boolean allowed = false;
5490 for (int i=0; i<N; i++) {
5491 if (pi.uriPermissionPatterns[i] != null
5492 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
5493 allowed = true;
5494 break;
5495 }
5496 }
5497 if (!allowed) {
5498 throw new SecurityException("Provider " + pi.packageName
5499 + "/" + pi.name
5500 + " does not allow granting of permission to path of Uri "
5501 + uri);
5502 }
5503 }
5504
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005505 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005507 if (callingUid != Process.myUid()) {
5508 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
5509 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5510 throw new SecurityException("Uid " + callingUid
5511 + " does not have permission to uri " + uri);
5512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 }
5514 }
5515
Dianne Hackborn39792d22010-08-19 18:01:52 -07005516 return targetUid;
5517 }
5518
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005519 public int checkGrantUriPermission(int callingUid, String targetPkg,
5520 Uri uri, int modeFlags) {
5521 synchronized(this) {
5522 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
5523 }
5524 }
5525
Dianne Hackborn39792d22010-08-19 18:01:52 -07005526 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
5527 Uri uri, int modeFlags, UriPermissionOwner owner) {
5528 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5529 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5530 if (modeFlags == 0) {
5531 return;
5532 }
5533
5534 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 // to the uri, and the target doesn't. Let's now give this to
5536 // the target.
5537
Joe Onorato8a9b2202010-02-26 18:56:32 -08005538 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07005539 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 HashMap<Uri, UriPermission> targetUris
5542 = mGrantedUriPermissions.get(targetUid);
5543 if (targetUris == null) {
5544 targetUris = new HashMap<Uri, UriPermission>();
5545 mGrantedUriPermissions.put(targetUid, targetUris);
5546 }
5547
5548 UriPermission perm = targetUris.get(uri);
5549 if (perm == null) {
5550 perm = new UriPermission(targetUid, uri);
5551 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07005553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07005555 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08005557 } else {
5558 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5559 perm.readOwners.add(owner);
5560 owner.addReadPermission(perm);
5561 }
5562 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5563 perm.writeOwners.add(owner);
5564 owner.addWritePermission(perm);
5565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005566 }
5567 }
5568
Dianne Hackborn39792d22010-08-19 18:01:52 -07005569 void grantUriPermissionLocked(int callingUid,
5570 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005571 if (targetPkg == null) {
5572 throw new NullPointerException("targetPkg");
5573 }
5574
Dianne Hackborn39792d22010-08-19 18:01:52 -07005575 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
5576 if (targetUid < 0) {
5577 return;
5578 }
5579
5580 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
5581 }
5582
5583 /**
5584 * Like checkGrantUriPermissionLocked, but takes an Intent.
5585 */
5586 int checkGrantUriPermissionFromIntentLocked(int callingUid,
5587 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07005588 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07005589 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005590 + " from " + intent + "; flags=0x"
5591 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
5592
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07005593 if (targetPkg == null) {
5594 throw new NullPointerException("targetPkg");
5595 }
5596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005598 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 }
5600 Uri data = intent.getData();
5601 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07005602 return -1;
5603 }
5604 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
5605 intent.getFlags());
5606 }
5607
5608 /**
5609 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
5610 */
5611 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
5612 String targetPkg, Intent intent, UriPermissionOwner owner) {
5613 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
5614 intent.getFlags(), owner);
5615 }
5616
5617 void grantUriPermissionFromIntentLocked(int callingUid,
5618 String targetPkg, Intent intent, UriPermissionOwner owner) {
5619 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
5620 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 return;
5622 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07005623
5624 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 }
5626
5627 public void grantUriPermission(IApplicationThread caller, String targetPkg,
5628 Uri uri, int modeFlags) {
5629 synchronized(this) {
5630 final ProcessRecord r = getRecordForAppLocked(caller);
5631 if (r == null) {
5632 throw new SecurityException("Unable to find app for caller "
5633 + caller
5634 + " when granting permission to uri " + uri);
5635 }
5636 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07005637 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005638 }
5639 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07005640 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 }
5642
5643 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
5644 null);
5645 }
5646 }
5647
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005648 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
5650 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
5651 HashMap<Uri, UriPermission> perms
5652 = mGrantedUriPermissions.get(perm.uid);
5653 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005654 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005655 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 perms.remove(perm.uri);
5657 if (perms.size() == 0) {
5658 mGrantedUriPermissions.remove(perm.uid);
5659 }
5660 }
5661 }
5662 }
5663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005664 private void revokeUriPermissionLocked(int callingUid, Uri uri,
5665 int modeFlags) {
5666 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5667 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5668 if (modeFlags == 0) {
5669 return;
5670 }
5671
Joe Onorato8a9b2202010-02-26 18:56:32 -08005672 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005673 "Revoking all granted permissions to " + uri);
5674
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005675 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676
5677 final String authority = uri.getAuthority();
5678 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005679 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 if (cpr != null) {
5681 pi = cpr.info;
5682 } else {
5683 try {
5684 pi = pm.resolveContentProvider(authority,
5685 PackageManager.GET_URI_PERMISSION_PATTERNS);
5686 } catch (RemoteException ex) {
5687 }
5688 }
5689 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005690 Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 return;
5692 }
5693
5694 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07005695 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 // Right now, if you are not the original owner of the permission,
5697 // you are not allowed to revoke it.
5698 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5699 throw new SecurityException("Uid " + callingUid
5700 + " does not have permission to uri " + uri);
5701 //}
5702 }
5703
5704 // Go through all of the permissions and remove any that match.
5705 final List<String> SEGMENTS = uri.getPathSegments();
5706 if (SEGMENTS != null) {
5707 final int NS = SEGMENTS.size();
5708 int N = mGrantedUriPermissions.size();
5709 for (int i=0; i<N; i++) {
5710 HashMap<Uri, UriPermission> perms
5711 = mGrantedUriPermissions.valueAt(i);
5712 Iterator<UriPermission> it = perms.values().iterator();
5713 toploop:
5714 while (it.hasNext()) {
5715 UriPermission perm = it.next();
5716 Uri targetUri = perm.uri;
5717 if (!authority.equals(targetUri.getAuthority())) {
5718 continue;
5719 }
5720 List<String> targetSegments = targetUri.getPathSegments();
5721 if (targetSegments == null) {
5722 continue;
5723 }
5724 if (targetSegments.size() < NS) {
5725 continue;
5726 }
5727 for (int j=0; j<NS; j++) {
5728 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
5729 continue toploop;
5730 }
5731 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005732 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005733 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 perm.clearModes(modeFlags);
5735 if (perm.modeFlags == 0) {
5736 it.remove();
5737 }
5738 }
5739 if (perms.size() == 0) {
5740 mGrantedUriPermissions.remove(
5741 mGrantedUriPermissions.keyAt(i));
5742 N--;
5743 i--;
5744 }
5745 }
5746 }
5747 }
5748
5749 public void revokeUriPermission(IApplicationThread caller, Uri uri,
5750 int modeFlags) {
5751 synchronized(this) {
5752 final ProcessRecord r = getRecordForAppLocked(caller);
5753 if (r == null) {
5754 throw new SecurityException("Unable to find app for caller "
5755 + caller
5756 + " when revoking permission to uri " + uri);
5757 }
5758 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005759 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 return;
5761 }
5762
5763 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5764 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5765 if (modeFlags == 0) {
5766 return;
5767 }
5768
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005769 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770
5771 final String authority = uri.getAuthority();
5772 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005773 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 if (cpr != null) {
5775 pi = cpr.info;
5776 } else {
5777 try {
5778 pi = pm.resolveContentProvider(authority,
5779 PackageManager.GET_URI_PERMISSION_PATTERNS);
5780 } catch (RemoteException ex) {
5781 }
5782 }
5783 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005784 Slog.w(TAG, "No content provider found for permission revoke: "
5785 + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 return;
5787 }
5788
5789 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
5790 }
5791 }
5792
Dianne Hackborn7e269642010-08-25 19:50:20 -07005793 @Override
5794 public IBinder newUriPermissionOwner(String name) {
5795 synchronized(this) {
5796 UriPermissionOwner owner = new UriPermissionOwner(this, name);
5797 return owner.getExternalTokenLocked();
5798 }
5799 }
5800
5801 @Override
5802 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
5803 Uri uri, int modeFlags) {
5804 synchronized(this) {
5805 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5806 if (owner == null) {
5807 throw new IllegalArgumentException("Unknown owner: " + token);
5808 }
5809 if (fromUid != Binder.getCallingUid()) {
5810 if (Binder.getCallingUid() != Process.myUid()) {
5811 // Only system code can grant URI permissions on behalf
5812 // of other users.
5813 throw new SecurityException("nice try");
5814 }
5815 }
5816 if (targetPkg == null) {
5817 throw new IllegalArgumentException("null target");
5818 }
5819 if (uri == null) {
5820 throw new IllegalArgumentException("null uri");
5821 }
5822
5823 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
5824 }
5825 }
5826
5827 @Override
5828 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
5829 synchronized(this) {
5830 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5831 if (owner == null) {
5832 throw new IllegalArgumentException("Unknown owner: " + token);
5833 }
5834
5835 if (uri == null) {
5836 owner.removeUriPermissionsLocked(mode);
5837 } else {
5838 owner.removeUriPermissionLocked(uri, mode);
5839 }
5840 }
5841 }
5842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
5844 synchronized (this) {
5845 ProcessRecord app =
5846 who != null ? getRecordForAppLocked(who) : null;
5847 if (app == null) return;
5848
5849 Message msg = Message.obtain();
5850 msg.what = WAIT_FOR_DEBUGGER_MSG;
5851 msg.obj = app;
5852 msg.arg1 = waiting ? 1 : 0;
5853 mHandler.sendMessage(msg);
5854 }
5855 }
5856
5857 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07005858 final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
5859 final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 outInfo.availMem = Process.getFreeMemory();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005861 outInfo.threshold = homeAppMem;
5862 outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
5863 outInfo.hiddenAppThreshold = hiddenAppMem;
5864 outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
Dianne Hackborne02c88a2011-10-28 13:58:15 -07005865 ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005866 outInfo.visibleAppThreshold = mProcessList.getMemLevel(
5867 ProcessList.VISIBLE_APP_ADJ);
5868 outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
5869 ProcessList.FOREGROUND_APP_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005870 }
5871
5872 // =========================================================
5873 // TASK MANAGEMENT
5874 // =========================================================
5875
5876 public List getTasks(int maxNum, int flags,
5877 IThumbnailReceiver receiver) {
5878 ArrayList list = new ArrayList();
5879
5880 PendingThumbnailsRecord pending = null;
5881 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005882 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883
5884 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005885 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
5887 + ", receiver=" + receiver);
5888
5889 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
5890 != PackageManager.PERMISSION_GRANTED) {
5891 if (receiver != null) {
5892 // If the caller wants to wait for pending thumbnails,
5893 // it ain't gonna get them.
5894 try {
5895 receiver.finished();
5896 } catch (RemoteException ex) {
5897 }
5898 }
5899 String msg = "Permission Denial: getTasks() from pid="
5900 + Binder.getCallingPid()
5901 + ", uid=" + Binder.getCallingUid()
5902 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005903 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 throw new SecurityException(msg);
5905 }
5906
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005907 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005908 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005909 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005910 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005911 TaskRecord curTask = null;
5912 int numActivities = 0;
5913 int numRunning = 0;
5914 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005915 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005917 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918
5919 // Initialize state for next task if needed.
5920 if (top == null ||
5921 (top.state == ActivityState.INITIALIZING
5922 && top.task == r.task)) {
5923 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 curTask = r.task;
5925 numActivities = numRunning = 0;
5926 }
5927
5928 // Add 'r' into the current task.
5929 numActivities++;
5930 if (r.app != null && r.app.thread != null) {
5931 numRunning++;
5932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933
Joe Onorato8a9b2202010-02-26 18:56:32 -08005934 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 TAG, r.intent.getComponent().flattenToShortString()
5936 + ": task=" + r.task);
5937
5938 // If the next one is a different task, generate a new
5939 // TaskInfo entry for what we have.
5940 if (next == null || next.task != curTask) {
5941 ActivityManager.RunningTaskInfo ci
5942 = new ActivityManager.RunningTaskInfo();
5943 ci.id = curTask.taskId;
5944 ci.baseActivity = r.intent.getComponent();
5945 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005946 if (top.thumbHolder != null) {
5947 ci.description = top.thumbHolder.lastDescription;
5948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 ci.numActivities = numActivities;
5950 ci.numRunning = numRunning;
5951 //System.out.println(
5952 // "#" + maxNum + ": " + " descr=" + ci.description);
5953 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005954 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 TAG, "State=" + top.state + "Idle=" + top.idle
5956 + " app=" + top.app
5957 + " thr=" + (top.app != null ? top.app.thread : null));
5958 if (top.state == ActivityState.RESUMED
5959 || top.state == ActivityState.PAUSING) {
5960 if (top.idle && top.app != null
5961 && top.app.thread != null) {
5962 topRecord = top;
5963 topThumbnail = top.app.thread;
5964 } else {
5965 top.thumbnailNeeded = true;
5966 }
5967 }
5968 if (pending == null) {
5969 pending = new PendingThumbnailsRecord(receiver);
5970 }
5971 pending.pendingRecords.add(top);
5972 }
5973 list.add(ci);
5974 maxNum--;
5975 top = null;
5976 }
5977 }
5978
5979 if (pending != null) {
5980 mPendingThumbnails.add(pending);
5981 }
5982 }
5983
Joe Onorato8a9b2202010-02-26 18:56:32 -08005984 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985
5986 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005987 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08005989 topThumbnail.requestThumbnail(topRecord.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005991 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005992 sendPendingThumbnail(null, topRecord.appToken, null, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 }
5994 }
5995
5996 if (pending == null && receiver != null) {
5997 // In this case all thumbnails were available and the client
5998 // is being asked to be told when the remaining ones come in...
5999 // which is unusually, since the top-most currently running
6000 // activity should never have a canned thumbnail! Oh well.
6001 try {
6002 receiver.finished();
6003 } catch (RemoteException ex) {
6004 }
6005 }
6006
6007 return list;
6008 }
6009
6010 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6011 int flags) {
6012 synchronized (this) {
6013 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6014 "getRecentTasks()");
6015
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006016 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 final int N = mRecentTasks.size();
6019 ArrayList<ActivityManager.RecentTaskInfo> res
6020 = new ArrayList<ActivityManager.RecentTaskInfo>(
6021 maxNum < N ? maxNum : N);
6022 for (int i=0; i<N && maxNum > 0; i++) {
6023 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackborn905577f2011-09-07 18:31:28 -07006024 // Return the entry if desired by the caller. We always return
6025 // the first entry, because callers always expect this to be the
6026 // forground app. We may filter others if the caller has
6027 // not supplied RECENT_WITH_EXCLUDED and there is some reason
6028 // we should exclude the entry.
6029 if (i == 0
6030 || ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 || (tr.intent == null)
6032 || ((tr.intent.getFlags()
6033 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6034 ActivityManager.RecentTaskInfo rti
6035 = new ActivityManager.RecentTaskInfo();
6036 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08006037 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 rti.baseIntent = new Intent(
6039 tr.intent != null ? tr.intent : tr.affinityIntent);
6040 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08006041 rti.description = tr.lastDescription;
6042
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006043 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6044 // Check whether this activity is currently available.
6045 try {
6046 if (rti.origActivity != null) {
6047 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6048 continue;
6049 }
6050 } else if (rti.baseIntent != null) {
6051 if (pm.queryIntentActivities(rti.baseIntent,
6052 null, 0) == null) {
6053 continue;
6054 }
6055 }
6056 } catch (RemoteException e) {
6057 // Will never happen.
6058 }
6059 }
6060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006061 res.add(rti);
6062 maxNum--;
6063 }
6064 }
6065 return res;
6066 }
6067 }
6068
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006069 private TaskRecord taskForIdLocked(int id) {
6070 final int N = mRecentTasks.size();
6071 for (int i=0; i<N; i++) {
6072 TaskRecord tr = mRecentTasks.get(i);
6073 if (tr.taskId == id) {
6074 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08006075 }
6076 }
6077 return null;
6078 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006079
6080 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
6081 synchronized (this) {
6082 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
6083 "getTaskThumbnails()");
6084 TaskRecord tr = taskForIdLocked(id);
6085 if (tr != null) {
6086 return mMainStack.getTaskThumbnailsLocked(tr);
6087 }
6088 }
6089 return null;
6090 }
6091
6092 public boolean removeSubTask(int taskId, int subTaskIndex) {
6093 synchronized (this) {
6094 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
6095 "removeSubTask()");
6096 long ident = Binder.clearCallingIdentity();
6097 try {
6098 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
6099 } finally {
6100 Binder.restoreCallingIdentity(ident);
6101 }
6102 }
6103 }
6104
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006105 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006106 TaskRecord tr = root.task;
6107 Intent baseIntent = new Intent(
6108 tr.intent != null ? tr.intent : tr.affinityIntent);
6109 ComponentName component = baseIntent.getComponent();
6110 if (component == null) {
6111 Slog.w(TAG, "Now component for base intent of task: " + tr);
6112 return;
6113 }
6114
6115 // Find any running services associated with this app.
6116 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
6117 for (ServiceRecord sr : mServices.values()) {
6118 if (sr.packageName.equals(component.getPackageName())) {
6119 services.add(sr);
6120 }
6121 }
6122
6123 // Take care of any running services associated with the app.
6124 for (int i=0; i<services.size(); i++) {
6125 ServiceRecord sr = services.get(i);
6126 if (sr.startRequested) {
6127 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006128 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006129 stopServiceLocked(sr);
6130 } else {
6131 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
6132 sr.makeNextStartId(), baseIntent, -1));
6133 if (sr.app != null && sr.app.thread != null) {
6134 sendServiceArgsLocked(sr, false);
6135 }
6136 }
6137 }
6138 }
6139
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006140 if (killProcesses) {
6141 // Find any running processes associated with this app.
6142 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
6143 SparseArray<ProcessRecord> appProcs
6144 = mProcessNames.getMap().get(component.getPackageName());
6145 if (appProcs != null) {
6146 for (int i=0; i<appProcs.size(); i++) {
6147 procs.add(appProcs.valueAt(i));
6148 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006149 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006150
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006151 // Kill the running processes.
6152 for (int i=0; i<procs.size(); i++) {
6153 ProcessRecord pr = procs.get(i);
6154 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
6155 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
6156 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
6157 pr.processName, pr.setAdj, "remove task");
6158 Process.killProcessQuiet(pr.pid);
6159 } else {
6160 pr.waitingToKill = "remove task";
6161 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006162 }
6163 }
6164 }
6165
6166 public boolean removeTask(int taskId, int flags) {
6167 synchronized (this) {
6168 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
6169 "removeTask()");
6170 long ident = Binder.clearCallingIdentity();
6171 try {
6172 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
6173 if (r != null) {
6174 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07006175 cleanUpRemovedTaskLocked(r,
6176 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006177 return true;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -07006178 } else {
6179 TaskRecord tr = null;
6180 int i=0;
6181 while (i < mRecentTasks.size()) {
6182 TaskRecord t = mRecentTasks.get(i);
6183 if (t.taskId == taskId) {
6184 tr = t;
6185 break;
6186 }
6187 i++;
6188 }
6189 if (tr != null) {
6190 if (tr.numActivities <= 0) {
6191 // Caller is just removing a recent task that is
6192 // not actively running. That is easy!
6193 mRecentTasks.remove(i);
6194 } else {
6195 Slog.w(TAG, "removeTask: task " + taskId
6196 + " does not have activities to remove, "
6197 + " but numActivities=" + tr.numActivities
6198 + ": " + tr);
6199 }
6200 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006201 }
6202 } finally {
6203 Binder.restoreCallingIdentity(ident);
6204 }
6205 }
6206 return false;
6207 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08006208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006209 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6210 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006211 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 TaskRecord jt = startTask;
6213
6214 // First look backwards
6215 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006216 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006217 if (r.task != jt) {
6218 jt = r.task;
6219 if (affinity.equals(jt.affinity)) {
6220 return j;
6221 }
6222 }
6223 }
6224
6225 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006226 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 jt = startTask;
6228 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006229 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 if (r.task != jt) {
6231 if (affinity.equals(jt.affinity)) {
6232 return j;
6233 }
6234 jt = r.task;
6235 }
6236 }
6237
6238 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006239 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 return N-1;
6241 }
6242
6243 return -1;
6244 }
6245
6246 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006247 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08006249 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6251 "moveTaskToFront()");
6252
6253 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006254 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6255 Binder.getCallingUid(), "Task to front")) {
6256 return;
6257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 final long origId = Binder.clearCallingIdentity();
6259 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006260 TaskRecord tr = taskForIdLocked(task);
6261 if (tr != null) {
6262 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
6263 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006264 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006265 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
6266 // Caller wants the home activity moved with it. To accomplish this,
6267 // we'll just move the home task to the top first.
6268 mMainStack.moveHomeToFrontLocked();
6269 }
6270 mMainStack.moveTaskToFrontLocked(tr, null);
6271 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006273 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6274 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006275 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08006276 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
6277 mMainStack.mUserLeaving = true;
6278 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08006279 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
6280 // Caller wants the home activity moved with it. To accomplish this,
6281 // we'll just move the home task to the top first.
6282 mMainStack.moveHomeToFrontLocked();
6283 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006284 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 return;
6286 }
6287 }
6288 } finally {
6289 Binder.restoreCallingIdentity(origId);
6290 }
6291 }
6292 }
6293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 public void moveTaskToBack(int task) {
6295 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6296 "moveTaskToBack()");
6297
6298 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006299 if (mMainStack.mResumedActivity != null
6300 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006301 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6302 Binder.getCallingUid(), "Task to back")) {
6303 return;
6304 }
6305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006307 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 Binder.restoreCallingIdentity(origId);
6309 }
6310 }
6311
6312 /**
6313 * Moves an activity, and all of the other activities within the same task, to the bottom
6314 * of the history stack. The activity's order within the task is unchanged.
6315 *
6316 * @param token A reference to the activity we wish to move
6317 * @param nonRoot If false then this only works if the activity is the root
6318 * of a task; if true it will work for any activity in a task.
6319 * @return Returns true if the move completed, false if not.
6320 */
6321 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
6322 synchronized(this) {
6323 final long origId = Binder.clearCallingIdentity();
6324 int taskId = getTaskForActivityLocked(token, !nonRoot);
6325 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006326 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 }
6328 Binder.restoreCallingIdentity(origId);
6329 }
6330 return false;
6331 }
6332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006333 public void moveTaskBackwards(int task) {
6334 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6335 "moveTaskBackwards()");
6336
6337 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006338 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6339 Binder.getCallingUid(), "Task backwards")) {
6340 return;
6341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 final long origId = Binder.clearCallingIdentity();
6343 moveTaskBackwardsLocked(task);
6344 Binder.restoreCallingIdentity(origId);
6345 }
6346 }
6347
6348 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006349 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006350 }
6351
6352 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
6353 synchronized(this) {
6354 return getTaskForActivityLocked(token, onlyRoot);
6355 }
6356 }
6357
6358 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006359 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360 TaskRecord lastTask = null;
6361 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006362 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08006363 if (r.appToken == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 if (!onlyRoot || lastTask != r.task) {
6365 return r.task.taskId;
6366 }
6367 return -1;
6368 }
6369 lastTask = r.task;
6370 }
6371
6372 return -1;
6373 }
6374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 public void finishOtherInstances(IBinder token, ComponentName className) {
6376 synchronized(this) {
6377 final long origId = Binder.clearCallingIdentity();
6378
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006379 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 TaskRecord lastTask = null;
6381 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006382 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 if (r.realActivity.equals(className)
Dianne Hackbornbe707852011-11-11 14:32:10 -08006384 && r.appToken != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006385 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 null, "others")) {
6387 i--;
6388 N--;
6389 }
6390 }
6391 lastTask = r.task;
6392 }
6393
6394 Binder.restoreCallingIdentity(origId);
6395 }
6396 }
6397
6398 // =========================================================
6399 // THUMBNAILS
6400 // =========================================================
6401
6402 public void reportThumbnail(IBinder token,
6403 Bitmap thumbnail, CharSequence description) {
6404 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
6405 final long origId = Binder.clearCallingIdentity();
6406 sendPendingThumbnail(null, token, thumbnail, description, true);
6407 Binder.restoreCallingIdentity(origId);
6408 }
6409
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006410 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 Bitmap thumbnail, CharSequence description, boolean always) {
6412 TaskRecord task = null;
6413 ArrayList receivers = null;
6414
6415 //System.out.println("Send pending thumbnail: " + r);
6416
6417 synchronized(this) {
6418 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006419 r = mMainStack.isInStackLocked(token);
6420 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 return;
6422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006423 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07006424 if (thumbnail == null && r.thumbHolder != null) {
6425 thumbnail = r.thumbHolder.lastThumbnail;
6426 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006427 }
6428 if (thumbnail == null && !always) {
6429 // If there is no thumbnail, and this entry is not actually
6430 // going away, then abort for now and pick up the next
6431 // thumbnail we get.
6432 return;
6433 }
6434 task = r.task;
6435
6436 int N = mPendingThumbnails.size();
6437 int i=0;
6438 while (i<N) {
6439 PendingThumbnailsRecord pr =
6440 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
6441 //System.out.println("Looking in " + pr.pendingRecords);
6442 if (pr.pendingRecords.remove(r)) {
6443 if (receivers == null) {
6444 receivers = new ArrayList();
6445 }
6446 receivers.add(pr);
6447 if (pr.pendingRecords.size() == 0) {
6448 pr.finished = true;
6449 mPendingThumbnails.remove(i);
6450 N--;
6451 continue;
6452 }
6453 }
6454 i++;
6455 }
6456 }
6457
6458 if (receivers != null) {
6459 final int N = receivers.size();
6460 for (int i=0; i<N; i++) {
6461 try {
6462 PendingThumbnailsRecord pr =
6463 (PendingThumbnailsRecord)receivers.get(i);
6464 pr.receiver.newThumbnail(
6465 task != null ? task.taskId : -1, thumbnail, description);
6466 if (pr.finished) {
6467 pr.receiver.finished();
6468 }
6469 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006470 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 }
6472 }
6473 }
6474 }
6475
6476 // =========================================================
6477 // CONTENT PROVIDERS
6478 // =========================================================
6479
Jeff Brown10e89712011-07-08 18:52:57 -07006480 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
6481 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006483 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006485 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 } catch (RemoteException ex) {
6487 }
6488 if (providers != null) {
6489 final int N = providers.size();
6490 for (int i=0; i<N; i++) {
6491 ProviderInfo cpi =
6492 (ProviderInfo)providers.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006493 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
6494 ContentProviderRecord cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006495 if (cpr == null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006496 cpr = new ContentProviderRecord(cpi, app.info, comp);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006497 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 }
6499 app.pubProviders.put(cpi.name, cpr);
6500 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07006501 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006502 }
6503 }
6504 return providers;
6505 }
6506
6507 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07006508 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006509 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
6510 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
6511 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006512 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07006513 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 return null;
6515 }
6516 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006517 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 == PackageManager.PERMISSION_GRANTED) {
6519 return null;
6520 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07006521
6522 PathPermission[] pps = cpi.pathPermissions;
6523 if (pps != null) {
6524 int i = pps.length;
6525 while (i > 0) {
6526 i--;
6527 PathPermission pp = pps[i];
6528 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006529 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07006530 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07006531 return null;
6532 }
6533 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006534 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07006535 == PackageManager.PERMISSION_GRANTED) {
6536 return null;
6537 }
6538 }
6539 }
6540
Dianne Hackbornb424b632010-08-18 15:59:05 -07006541 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
6542 if (perms != null) {
6543 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
6544 if (uri.getKey().getAuthority().equals(cpi.authority)) {
6545 return null;
6546 }
6547 }
6548 }
6549
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006550 String msg;
6551 if (!cpi.exported) {
6552 msg = "Permission Denial: opening provider " + cpi.name
6553 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
6554 + ", uid=" + callingUid + ") that is not exported from uid "
6555 + cpi.applicationInfo.uid;
6556 } else {
6557 msg = "Permission Denial: opening provider " + cpi.name
6558 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
6559 + ", uid=" + callingUid + ") requires "
6560 + cpi.readPermission + " or " + cpi.writePermission;
6561 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006562 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006563 return msg;
6564 }
6565
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006566 boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
6567 if (r != null) {
6568 Integer cnt = r.conProviders.get(cpr);
6569 if (DEBUG_PROVIDER) Slog.v(TAG,
6570 "Adding provider requested by "
6571 + r.processName + " from process "
6572 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
6573 + " cnt=" + (cnt == null ? 1 : cnt));
6574 if (cnt == null) {
6575 cpr.clients.add(r);
6576 r.conProviders.put(cpr, new Integer(1));
6577 return true;
6578 } else {
6579 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
6580 }
6581 } else {
6582 cpr.externals++;
6583 }
6584 return false;
6585 }
6586
6587 boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
6588 if (r != null) {
6589 Integer cnt = r.conProviders.get(cpr);
6590 if (DEBUG_PROVIDER) Slog.v(TAG,
6591 "Removing provider requested by "
6592 + r.processName + " from process "
6593 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
6594 + " cnt=" + cnt);
6595 if (cnt == null || cnt.intValue() <= 1) {
6596 cpr.clients.remove(r);
6597 r.conProviders.remove(cpr);
6598 return true;
6599 } else {
6600 r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
6601 }
6602 } else {
6603 cpr.externals++;
6604 }
6605 return false;
6606 }
6607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 private final ContentProviderHolder getContentProviderImpl(
6609 IApplicationThread caller, String name) {
6610 ContentProviderRecord cpr;
6611 ProviderInfo cpi = null;
6612
6613 synchronized(this) {
6614 ProcessRecord r = null;
6615 if (caller != null) {
6616 r = getRecordForAppLocked(caller);
6617 if (r == null) {
6618 throw new SecurityException(
6619 "Unable to find app for caller " + caller
6620 + " (pid=" + Binder.getCallingPid()
6621 + ") when getting content provider " + name);
6622 }
6623 }
6624
6625 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07006626 cpr = mProvidersByName.get(name);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006627 boolean providerRunning = cpr != null;
6628 if (providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07006630 String msg;
6631 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
6632 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006633 }
6634
6635 if (r != null && cpr.canRunHere(r)) {
6636 // This provider has been published or is in the process
6637 // of being published... but it is also allowed to run
6638 // in the caller's process, so don't make a connection
6639 // and just let the caller instantiate its own instance.
6640 if (cpr.provider != null) {
6641 // don't give caller the provider object, it needs
6642 // to make its own.
6643 cpr = new ContentProviderRecord(cpr);
6644 }
6645 return cpr;
6646 }
6647
6648 final long origId = Binder.clearCallingIdentity();
6649
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006650 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 // return it right away.
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006652 final boolean countChanged = incProviderCount(r, cpr);
6653 if (countChanged) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006654 if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006655 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07006656 // make sure to count it as being accessed and thus
6657 // back up on the LRU list. This is good because
6658 // content providers are often expensive to start.
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006659 updateLruProcessLocked(cpr.proc, false, true);
Dianne Hackborn906497c2010-05-10 15:57:38 -07006660 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07006661 }
6662
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006663 if (cpr.proc != null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006664 if (false) {
6665 if (cpr.name.flattenToShortString().equals(
6666 "com.android.providers.calendar/.CalendarProvider2")) {
6667 Slog.v(TAG, "****************** KILLING "
6668 + cpr.name.flattenToShortString());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006669 Process.killProcess(cpr.proc.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006670 }
6671 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006672 boolean success = updateOomAdjLocked(cpr.proc);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006673 if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
6674 // NOTE: there is still a race here where a signal could be
6675 // pending on the process even though we managed to update its
6676 // adj level. Not sure what to do about this, but at least
6677 // the race is now smaller.
6678 if (!success) {
6679 // Uh oh... it looks like the provider's process
6680 // has been killed on us. We need to wait for a new
6681 // process to be started, and make sure its death
6682 // doesn't kill our process.
6683 Slog.i(TAG,
6684 "Existing provider " + cpr.name.flattenToShortString()
6685 + " is crashing; detaching " + r);
6686 boolean lastRef = decProviderCount(r, cpr);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006687 appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006688 if (!lastRef) {
6689 // This wasn't the last ref our process had on
6690 // the provider... we have now been killed, bail.
6691 return null;
6692 }
6693 providerRunning = false;
6694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 }
6696
6697 Binder.restoreCallingIdentity(origId);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006700 if (!providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006702 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006703 resolveContentProvider(name,
6704 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 } catch (RemoteException ex) {
6706 }
6707 if (cpi == null) {
6708 return null;
6709 }
6710
Dianne Hackbornb424b632010-08-18 15:59:05 -07006711 String msg;
6712 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
6713 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 }
6715
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006716 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006717 && !cpi.processName.equals("system")) {
6718 // If this content provider does not run in the system
6719 // process, and the system is not yet ready to run other
6720 // processes, then fail fast instead of hanging.
6721 throw new IllegalArgumentException(
6722 "Attempt to launch content provider before system ready");
6723 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006724
6725 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
6726 cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006727 final boolean firstClass = cpr == null;
6728 if (firstClass) {
6729 try {
6730 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006731 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 getApplicationInfo(
6733 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006734 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006736 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006737 + cpi.name);
6738 return null;
6739 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006740 cpr = new ContentProviderRecord(cpi, ai, comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 } catch (RemoteException ex) {
6742 // pm is in same process, this will never happen.
6743 }
6744 }
6745
6746 if (r != null && cpr.canRunHere(r)) {
6747 // If this is a multiprocess provider, then just return its
6748 // info and allow the caller to instantiate it. Only do
6749 // this if the provider is the same user as the caller's
6750 // process, or can run as root (so can be in any process).
6751 return cpr;
6752 }
6753
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006754 if (DEBUG_PROVIDER) {
6755 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006756 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006757 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 }
6759
6760 // This is single process, and our app is now connecting to it.
6761 // See if we are already in the process of launching this
6762 // provider.
6763 final int N = mLaunchingProviders.size();
6764 int i;
6765 for (i=0; i<N; i++) {
6766 if (mLaunchingProviders.get(i) == cpr) {
6767 break;
6768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 }
6770
6771 // If the provider is not already being launched, then get it
6772 // started.
6773 if (i >= N) {
6774 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08006775
6776 try {
6777 // Content provider is now in use, its package can't be stopped.
6778 try {
6779 AppGlobals.getPackageManager().setPackageStoppedState(
6780 cpr.appInfo.packageName, false);
6781 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006782 } catch (IllegalArgumentException e) {
6783 Slog.w(TAG, "Failed trying to unstop package "
6784 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006785 }
6786
6787 ProcessRecord proc = startProcessLocked(cpi.processName,
6788 cpr.appInfo, false, 0, "content provider",
6789 new ComponentName(cpi.applicationInfo.packageName,
6790 cpi.name), false);
6791 if (proc == null) {
6792 Slog.w(TAG, "Unable to launch app "
6793 + cpi.applicationInfo.packageName + "/"
6794 + cpi.applicationInfo.uid + " for provider "
6795 + name + ": process is bad");
6796 return null;
6797 }
6798 cpr.launchingApp = proc;
6799 mLaunchingProviders.add(cpr);
6800 } finally {
6801 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803 }
6804
6805 // Make sure the provider is published (the same provider class
6806 // may be published under multiple names).
6807 if (firstClass) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006808 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 }
6810 mProvidersByName.put(name, cpr);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006811 incProviderCount(r, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 }
6813 }
6814
6815 // Wait for the provider to be published...
6816 synchronized (cpr) {
6817 while (cpr.provider == null) {
6818 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006819 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006820 + cpi.applicationInfo.packageName + "/"
6821 + cpi.applicationInfo.uid + " for provider "
6822 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006823 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006824 cpi.applicationInfo.packageName,
6825 cpi.applicationInfo.uid, name);
6826 return null;
6827 }
6828 try {
6829 cpr.wait();
6830 } catch (InterruptedException ex) {
6831 }
6832 }
6833 }
6834 return cpr;
6835 }
6836
6837 public final ContentProviderHolder getContentProvider(
6838 IApplicationThread caller, String name) {
6839 if (caller == null) {
6840 String msg = "null IApplicationThread when getting content provider "
6841 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006842 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 throw new SecurityException(msg);
6844 }
6845
6846 return getContentProviderImpl(caller, name);
6847 }
6848
6849 private ContentProviderHolder getContentProviderExternal(String name) {
6850 return getContentProviderImpl(null, name);
6851 }
6852
6853 /**
6854 * Drop a content provider from a ProcessRecord's bookkeeping
6855 * @param cpr
6856 */
6857 public void removeContentProvider(IApplicationThread caller, String name) {
6858 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006859 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006860 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006861 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006862 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006863 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864 return;
6865 }
6866 final ProcessRecord r = getRecordForAppLocked(caller);
6867 if (r == null) {
6868 throw new SecurityException(
6869 "Unable to find app for caller " + caller +
6870 " when removing content provider " + name);
6871 }
6872 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006873 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
6874 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006875 if (localCpr.proc == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08006877 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006878 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 return;
6880 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006881 if (decProviderCount(r, localCpr)) {
6882 updateOomAdjLocked();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07006883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006885 }
6886 }
6887
6888 private void removeContentProviderExternal(String name) {
6889 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006890 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 if(cpr == null) {
6892 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006893 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006894 return;
6895 }
6896
6897 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006898 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
6899 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 localCpr.externals--;
6901 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006902 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 }
6904 updateOomAdjLocked();
6905 }
6906 }
6907
6908 public final void publishContentProviders(IApplicationThread caller,
6909 List<ContentProviderHolder> providers) {
6910 if (providers == null) {
6911 return;
6912 }
6913
6914 synchronized(this) {
6915 final ProcessRecord r = getRecordForAppLocked(caller);
6916 if (r == null) {
6917 throw new SecurityException(
6918 "Unable to find app for caller " + caller
6919 + " (pid=" + Binder.getCallingPid()
6920 + ") when publishing content providers");
6921 }
6922
6923 final long origId = Binder.clearCallingIdentity();
6924
6925 final int N = providers.size();
6926 for (int i=0; i<N; i++) {
6927 ContentProviderHolder src = providers.get(i);
6928 if (src == null || src.info == null || src.provider == null) {
6929 continue;
6930 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006931 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006932 if (dst != null) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006933 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
6934 mProvidersByClass.put(comp, dst);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 String names[] = dst.info.authority.split(";");
6936 for (int j = 0; j < names.length; j++) {
6937 mProvidersByName.put(names[j], dst);
6938 }
6939
6940 int NL = mLaunchingProviders.size();
6941 int j;
6942 for (j=0; j<NL; j++) {
6943 if (mLaunchingProviders.get(j) == dst) {
6944 mLaunchingProviders.remove(j);
6945 j--;
6946 NL--;
6947 }
6948 }
6949 synchronized (dst) {
6950 dst.provider = src.provider;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006951 dst.proc = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 dst.notifyAll();
6953 }
6954 updateOomAdjLocked(r);
6955 }
6956 }
6957
6958 Binder.restoreCallingIdentity(origId);
6959 }
6960 }
6961
6962 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07006963 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06006964 synchronized (mSelf) {
6965 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
6966 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08006967 if (providers != null) {
6968 for (int i=providers.size()-1; i>=0; i--) {
6969 ProviderInfo pi = (ProviderInfo)providers.get(i);
6970 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6971 Slog.w(TAG, "Not installing system proc provider " + pi.name
6972 + ": not system .apk");
6973 providers.remove(i);
6974 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006975 }
6976 }
6977 }
Josh Bartel2ecce342010-02-25 10:55:48 -06006978 if (providers != null) {
6979 mSystemThread.installSystemProviders(providers);
6980 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08006981
6982 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
Mark Brophyc6350272011-08-05 16:16:39 +01006983
6984 mSelf.mUsageStatsService.monitorPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 }
6986
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07006987 /**
6988 * Allows app to retrieve the MIME type of a URI without having permission
6989 * to access its content provider.
6990 *
6991 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
6992 *
6993 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
6994 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
6995 */
6996 public String getProviderMimeType(Uri uri) {
6997 final String name = uri.getAuthority();
6998 final long ident = Binder.clearCallingIdentity();
6999 ContentProviderHolder holder = null;
7000
7001 try {
7002 holder = getContentProviderExternal(name);
7003 if (holder != null) {
7004 return holder.provider.getType(uri);
7005 }
7006 } catch (RemoteException e) {
7007 Log.w(TAG, "Content provider dead retrieving " + uri, e);
7008 return null;
7009 } finally {
7010 if (holder != null) {
7011 removeContentProviderExternal(name);
7012 }
7013 Binder.restoreCallingIdentity(ident);
7014 }
7015
7016 return null;
7017 }
7018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007019 // =========================================================
7020 // GLOBAL MANAGEMENT
7021 // =========================================================
7022
7023 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7024 ApplicationInfo info, String customProcess) {
7025 String proc = customProcess != null ? customProcess : info.processName;
7026 BatteryStatsImpl.Uid.Proc ps = null;
7027 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7028 synchronized (stats) {
7029 ps = stats.getProcessStatsLocked(info.uid, proc);
7030 }
7031 return new ProcessRecord(ps, thread, info, proc);
7032 }
7033
7034 final ProcessRecord addAppLocked(ApplicationInfo info) {
7035 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7036
7037 if (app == null) {
7038 app = newProcessRecordLocked(null, info, null);
7039 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007040 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 }
7042
Dianne Hackborne7f97212011-02-24 14:40:20 -08007043 // This package really, really can not be stopped.
7044 try {
7045 AppGlobals.getPackageManager().setPackageStoppedState(
7046 info.packageName, false);
7047 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08007048 } catch (IllegalArgumentException e) {
7049 Slog.w(TAG, "Failed trying to unstop package "
7050 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007051 }
7052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7054 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7055 app.persistent = true;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007056 app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 }
7058 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7059 mPersistentStartingProcesses.add(app);
7060 startProcessLocked(app, "added application", app.processName);
7061 }
7062
7063 return app;
7064 }
7065
7066 public void unhandledBack() {
7067 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7068 "unhandledBack()");
7069
7070 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007071 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007072 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073 TAG, "Performing unhandledBack(): stack size = " + count);
7074 if (count > 1) {
7075 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007076 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7078 Binder.restoreCallingIdentity(origId);
7079 }
7080 }
7081 }
7082
7083 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7084 String name = uri.getAuthority();
7085 ContentProviderHolder cph = getContentProviderExternal(name);
7086 ParcelFileDescriptor pfd = null;
7087 if (cph != null) {
7088 // We record the binder invoker's uid in thread-local storage before
7089 // going to the content provider to open the file. Later, in the code
7090 // that handles all permissions checks, we look for this uid and use
7091 // that rather than the Activity Manager's own uid. The effect is that
7092 // we do the check against the caller's permissions even though it looks
7093 // to the content provider like the Activity Manager itself is making
7094 // the request.
7095 sCallerIdentity.set(new Identity(
7096 Binder.getCallingPid(), Binder.getCallingUid()));
7097 try {
7098 pfd = cph.provider.openFile(uri, "r");
7099 } catch (FileNotFoundException e) {
7100 // do nothing; pfd will be returned null
7101 } finally {
7102 // Ensure that whatever happens, we clean up the identity state
7103 sCallerIdentity.remove();
7104 }
7105
7106 // We've got the fd now, so we're done with the provider.
7107 removeContentProviderExternal(name);
7108 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007109 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007110 }
7111 return pfd;
7112 }
7113
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007114 // Actually is sleeping or shutting down or whatever else in the future
7115 // is an inactive state.
7116 public boolean isSleeping() {
7117 return mSleeping || mShuttingDown;
7118 }
7119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 public void goingToSleep() {
7121 synchronized(this) {
7122 mSleeping = true;
7123 mWindowManager.setEventDispatching(false);
7124
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007125 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07007126
7127 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07007128 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07007129 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
7130 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007131 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007132 }
7133 }
7134
Dianne Hackborn55280a92009-05-07 15:53:46 -07007135 public boolean shutdown(int timeout) {
7136 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7137 != PackageManager.PERMISSION_GRANTED) {
7138 throw new SecurityException("Requires permission "
7139 + android.Manifest.permission.SHUTDOWN);
7140 }
7141
7142 boolean timedout = false;
7143
7144 synchronized(this) {
7145 mShuttingDown = true;
7146 mWindowManager.setEventDispatching(false);
7147
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007148 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007149 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07007150 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007151 while (mMainStack.mResumedActivity != null
7152 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007153 long delay = endTime - System.currentTimeMillis();
7154 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007155 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07007156 timedout = true;
7157 break;
7158 }
7159 try {
7160 this.wait();
7161 } catch (InterruptedException e) {
7162 }
7163 }
7164 }
7165 }
7166
7167 mUsageStatsService.shutdown();
7168 mBatteryStatsService.shutdown();
7169
7170 return timedout;
7171 }
7172
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007173 public final void activitySlept(IBinder token) {
7174 if (localLOGV) Slog.v(
7175 TAG, "Activity slept: token=" + token);
7176
7177 ActivityRecord r = null;
7178
7179 final long origId = Binder.clearCallingIdentity();
7180
7181 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07007182 r = mMainStack.isInStackLocked(token);
7183 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007184 mMainStack.activitySleptLocked(r);
7185 }
7186 }
7187
7188 Binder.restoreCallingIdentity(origId);
7189 }
7190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007191 public void wakingUp() {
7192 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 mWindowManager.setEventDispatching(true);
7194 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007195 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007196 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 }
7198 }
7199
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007200 public void stopAppSwitches() {
7201 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7202 != PackageManager.PERMISSION_GRANTED) {
7203 throw new SecurityException("Requires permission "
7204 + android.Manifest.permission.STOP_APP_SWITCHES);
7205 }
7206
7207 synchronized(this) {
7208 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
7209 + APP_SWITCH_DELAY_TIME;
7210 mDidAppSwitch = false;
7211 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7212 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7213 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
7214 }
7215 }
7216
7217 public void resumeAppSwitches() {
7218 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7219 != PackageManager.PERMISSION_GRANTED) {
7220 throw new SecurityException("Requires permission "
7221 + android.Manifest.permission.STOP_APP_SWITCHES);
7222 }
7223
7224 synchronized(this) {
7225 // Note that we don't execute any pending app switches... we will
7226 // let those wait until either the timeout, or the next start
7227 // activity request.
7228 mAppSwitchesAllowedTime = 0;
7229 }
7230 }
7231
7232 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
7233 String name) {
7234 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
7235 return true;
7236 }
7237
7238 final int perm = checkComponentPermission(
7239 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08007240 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007241 if (perm == PackageManager.PERMISSION_GRANTED) {
7242 return true;
7243 }
7244
Joe Onorato8a9b2202010-02-26 18:56:32 -08007245 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007246 return false;
7247 }
7248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 public void setDebugApp(String packageName, boolean waitForDebugger,
7250 boolean persistent) {
7251 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
7252 "setDebugApp()");
7253
7254 // Note that this is not really thread safe if there are multiple
7255 // callers into it at the same time, but that's not a situation we
7256 // care about.
7257 if (persistent) {
7258 final ContentResolver resolver = mContext.getContentResolver();
7259 Settings.System.putString(
7260 resolver, Settings.System.DEBUG_APP,
7261 packageName);
7262 Settings.System.putInt(
7263 resolver, Settings.System.WAIT_FOR_DEBUGGER,
7264 waitForDebugger ? 1 : 0);
7265 }
7266
7267 synchronized (this) {
7268 if (!persistent) {
7269 mOrigDebugApp = mDebugApp;
7270 mOrigWaitForDebugger = mWaitForDebugger;
7271 }
7272 mDebugApp = packageName;
7273 mWaitForDebugger = waitForDebugger;
7274 mDebugTransient = !persistent;
7275 if (packageName != null) {
7276 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -07007277 forceStopPackageLocked(packageName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 Binder.restoreCallingIdentity(origId);
7279 }
7280 }
7281 }
7282
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07007283 void setProfileApp(ApplicationInfo app, String processName, String profileFile,
7284 ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
7285 synchronized (this) {
7286 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
7287 if (!isDebuggable) {
7288 if ((app.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
7289 throw new SecurityException("Process not debuggable: " + app.packageName);
7290 }
7291 }
7292 mProfileApp = processName;
7293 mProfileFile = profileFile;
7294 if (mProfileFd != null) {
7295 try {
7296 mProfileFd.close();
7297 } catch (IOException e) {
7298 }
7299 mProfileFd = null;
7300 }
7301 mProfileFd = profileFd;
7302 mProfileType = 0;
7303 mAutoStopProfiler = autoStopProfiler;
7304 }
7305 }
7306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 public void setAlwaysFinish(boolean enabled) {
7308 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
7309 "setAlwaysFinish()");
7310
7311 Settings.System.putInt(
7312 mContext.getContentResolver(),
7313 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
7314
7315 synchronized (this) {
7316 mAlwaysFinishActivities = enabled;
7317 }
7318 }
7319
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007320 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007322 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007323 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007324 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007325 }
7326 }
7327
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08007328 public boolean isUserAMonkey() {
7329 // For now the fact that there is a controller implies
7330 // we have a monkey.
7331 synchronized (this) {
7332 return mController != null;
7333 }
7334 }
7335
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007336 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06007337 synchronized (this) {
7338 mWatchers.register(watcher);
7339 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007340 }
7341
7342 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06007343 synchronized (this) {
7344 mWatchers.unregister(watcher);
7345 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007346 }
7347
Jeff Sharkeya4620792011-05-20 15:29:23 -07007348 public void registerProcessObserver(IProcessObserver observer) {
7349 mProcessObservers.register(observer);
7350 }
7351
7352 public void unregisterProcessObserver(IProcessObserver observer) {
7353 mProcessObservers.unregister(observer);
7354 }
7355
Daniel Sandler69a48172010-06-23 16:29:36 -04007356 public void setImmersive(IBinder token, boolean immersive) {
7357 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07007358 ActivityRecord r = mMainStack.isInStackLocked(token);
7359 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04007360 throw new IllegalArgumentException();
7361 }
Daniel Sandler69a48172010-06-23 16:29:36 -04007362 r.immersive = immersive;
7363 }
7364 }
7365
7366 public boolean isImmersive(IBinder token) {
7367 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07007368 ActivityRecord r = mMainStack.isInStackLocked(token);
7369 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04007370 throw new IllegalArgumentException();
7371 }
Daniel Sandler69a48172010-06-23 16:29:36 -04007372 return r.immersive;
7373 }
7374 }
7375
7376 public boolean isTopActivityImmersive() {
7377 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007378 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04007379 return (r != null) ? r.immersive : false;
7380 }
7381 }
7382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 public final void enterSafeMode() {
7384 synchronized(this) {
7385 // It only makes sense to do this before the system is ready
7386 // and started launching other packages.
7387 if (!mSystemReady) {
7388 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007389 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 } catch (RemoteException e) {
7391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 }
7393 }
7394 }
7395
Jeff Brownb09abc12011-01-13 21:08:27 -08007396 public final void showSafeModeOverlay() {
7397 View v = LayoutInflater.from(mContext).inflate(
7398 com.android.internal.R.layout.safe_mode, null);
7399 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
7400 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
7401 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
7402 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
7403 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
7404 lp.format = v.getBackground().getOpacity();
7405 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
7406 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
7407 ((WindowManager)mContext.getSystemService(
7408 Context.WINDOW_SERVICE)).addView(v, lp);
7409 }
7410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 public void noteWakeupAlarm(IIntentSender sender) {
7412 if (!(sender instanceof PendingIntentRecord)) {
7413 return;
7414 }
7415 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7416 synchronized (stats) {
7417 if (mBatteryStatsService.isOnBattery()) {
7418 mBatteryStatsService.enforceCallingPermission();
7419 PendingIntentRecord rec = (PendingIntentRecord)sender;
7420 int MY_UID = Binder.getCallingUid();
7421 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
7422 BatteryStatsImpl.Uid.Pkg pkg =
7423 stats.getPackageStatsLocked(uid, rec.key.packageName);
7424 pkg.incWakeupsLocked();
7425 }
7426 }
7427 }
7428
Dianne Hackborn64825172011-03-02 21:32:58 -08007429 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007431 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007433 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 // XXX Note: don't acquire main activity lock here, because the window
7435 // manager calls in with its locks held.
7436
7437 boolean killed = false;
7438 synchronized (mPidsSelfLocked) {
7439 int[] types = new int[pids.length];
7440 int worstType = 0;
7441 for (int i=0; i<pids.length; i++) {
7442 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7443 if (proc != null) {
7444 int type = proc.setAdj;
7445 types[i] = type;
7446 if (type > worstType) {
7447 worstType = type;
7448 }
7449 }
7450 }
7451
Dianne Hackborn64825172011-03-02 21:32:58 -08007452 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453 // then constrain it so we will kill all hidden procs.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007454 if (worstType < ProcessList.HIDDEN_APP_MAX_ADJ
7455 && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07007456 worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 }
Dianne Hackborn64825172011-03-02 21:32:58 -08007458
7459 // If this is not a secure call, don't let it kill processes that
7460 // are important.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007461 if (!secure && worstType < ProcessList.SERVICE_ADJ) {
7462 worstType = ProcessList.SERVICE_ADJ;
Dianne Hackborn64825172011-03-02 21:32:58 -08007463 }
7464
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007465 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 for (int i=0; i<pids.length; i++) {
7467 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7468 if (proc == null) {
7469 continue;
7470 }
7471 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07007472 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007473 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07007474 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
7475 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07007477 proc.killedBackground = true;
7478 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 }
7480 }
7481 }
7482 return killed;
7483 }
7484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485 public final void startRunning(String pkg, String cls, String action,
7486 String data) {
7487 synchronized(this) {
7488 if (mStartRunning) {
7489 return;
7490 }
7491 mStartRunning = true;
7492 mTopComponent = pkg != null && cls != null
7493 ? new ComponentName(pkg, cls) : null;
7494 mTopAction = action != null ? action : Intent.ACTION_MAIN;
7495 mTopData = data;
7496 if (!mSystemReady) {
7497 return;
7498 }
7499 }
7500
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007501 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 }
7503
7504 private void retrieveSettings() {
7505 final ContentResolver resolver = mContext.getContentResolver();
7506 String debugApp = Settings.System.getString(
7507 resolver, Settings.System.DEBUG_APP);
7508 boolean waitForDebugger = Settings.System.getInt(
7509 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
7510 boolean alwaysFinishActivities = Settings.System.getInt(
7511 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
7512
7513 Configuration configuration = new Configuration();
7514 Settings.System.getConfiguration(resolver, configuration);
7515
7516 synchronized (this) {
7517 mDebugApp = mOrigDebugApp = debugApp;
7518 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
7519 mAlwaysFinishActivities = alwaysFinishActivities;
7520 // This happens before any activities are started, so we can
7521 // change mConfiguration in-place.
Dianne Hackborn813075a62011-11-14 17:45:19 -08007522 updateConfigurationLocked(configuration, null, false, true);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007523 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007524 }
7525 }
7526
7527 public boolean testIsSystemReady() {
7528 // no need to synchronize(this) just to read & return the value
7529 return mSystemReady;
7530 }
7531
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007532 private static File getCalledPreBootReceiversFile() {
7533 File dataDir = Environment.getDataDirectory();
7534 File systemDir = new File(dataDir, "system");
7535 File fname = new File(systemDir, "called_pre_boots.dat");
7536 return fname;
7537 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07007538
7539 static final int LAST_DONE_VERSION = 10000;
7540
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007541 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
7542 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
7543 File file = getCalledPreBootReceiversFile();
7544 FileInputStream fis = null;
7545 try {
7546 fis = new FileInputStream(file);
7547 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07007548 int fvers = dis.readInt();
7549 if (fvers == LAST_DONE_VERSION) {
7550 String vers = dis.readUTF();
7551 String codename = dis.readUTF();
7552 String build = dis.readUTF();
7553 if (android.os.Build.VERSION.RELEASE.equals(vers)
7554 && android.os.Build.VERSION.CODENAME.equals(codename)
7555 && android.os.Build.VERSION.INCREMENTAL.equals(build)) {
7556 int num = dis.readInt();
7557 while (num > 0) {
7558 num--;
7559 String pkg = dis.readUTF();
7560 String cls = dis.readUTF();
7561 lastDoneReceivers.add(new ComponentName(pkg, cls));
7562 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007563 }
7564 }
7565 } catch (FileNotFoundException e) {
7566 } catch (IOException e) {
7567 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
7568 } finally {
7569 if (fis != null) {
7570 try {
7571 fis.close();
7572 } catch (IOException e) {
7573 }
7574 }
7575 }
7576 return lastDoneReceivers;
7577 }
7578
7579 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
7580 File file = getCalledPreBootReceiversFile();
7581 FileOutputStream fos = null;
7582 DataOutputStream dos = null;
7583 try {
7584 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
7585 fos = new FileOutputStream(file);
7586 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07007587 dos.writeInt(LAST_DONE_VERSION);
7588 dos.writeUTF(android.os.Build.VERSION.RELEASE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007589 dos.writeUTF(android.os.Build.VERSION.CODENAME);
Dianne Hackborn661cd522011-08-22 00:26:20 -07007590 dos.writeUTF(android.os.Build.VERSION.INCREMENTAL);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007591 dos.writeInt(list.size());
7592 for (int i=0; i<list.size(); i++) {
7593 dos.writeUTF(list.get(i).getPackageName());
7594 dos.writeUTF(list.get(i).getClassName());
7595 }
7596 } catch (IOException e) {
7597 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
7598 file.delete();
7599 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07007600 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007601 if (dos != null) {
7602 try {
7603 dos.close();
7604 } catch (IOException e) {
7605 // TODO Auto-generated catch block
7606 e.printStackTrace();
7607 }
7608 }
7609 }
7610 }
7611
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007612 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 synchronized(this) {
7614 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007615 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007616 return;
7617 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007618
7619 // Check to see if there are any update receivers to run.
7620 if (!mDidUpdate) {
7621 if (mWaitingUpdate) {
7622 return;
7623 }
7624 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
7625 List<ResolveInfo> ris = null;
7626 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007627 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007628 intent, null, 0);
7629 } catch (RemoteException e) {
7630 }
7631 if (ris != null) {
7632 for (int i=ris.size()-1; i>=0; i--) {
7633 if ((ris.get(i).activityInfo.applicationInfo.flags
7634 &ApplicationInfo.FLAG_SYSTEM) == 0) {
7635 ris.remove(i);
7636 }
7637 }
7638 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007639
7640 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
7641
7642 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007643 for (int i=0; i<ris.size(); i++) {
7644 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007645 ComponentName comp = new ComponentName(ai.packageName, ai.name);
7646 if (lastDoneReceivers.contains(comp)) {
7647 ris.remove(i);
7648 i--;
7649 }
7650 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07007651
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007652 for (int i=0; i<ris.size(); i++) {
7653 ActivityInfo ai = ris.get(i).activityInfo;
7654 ComponentName comp = new ComponentName(ai.packageName, ai.name);
7655 doneReceivers.add(comp);
7656 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007657 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08007658 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007659 finisher = new IIntentReceiver.Stub() {
7660 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07007661 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07007662 boolean sticky) {
7663 // The raw IIntentReceiver interface is called
7664 // with the AM lock held, so redispatch to
7665 // execute our code without the lock.
7666 mHandler.post(new Runnable() {
7667 public void run() {
7668 synchronized (ActivityManagerService.this) {
7669 mDidUpdate = true;
7670 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007671 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn661cd522011-08-22 00:26:20 -07007672 showBootMessage(mContext.getText(
7673 R.string.android_upgrading_complete),
7674 false);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07007675 systemReady(goingCallback);
7676 }
7677 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007678 }
7679 };
7680 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007681 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007682 broadcastIntentLocked(null, null, intent, null, finisher,
7683 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08007684 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007685 mWaitingUpdate = true;
7686 }
7687 }
7688 }
7689 if (mWaitingUpdate) {
7690 return;
7691 }
7692 mDidUpdate = true;
7693 }
7694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 mSystemReady = true;
7696 if (!mStartRunning) {
7697 return;
7698 }
7699 }
7700
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007701 ArrayList<ProcessRecord> procsToKill = null;
7702 synchronized(mPidsSelfLocked) {
7703 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
7704 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
7705 if (!isAllowedWhileBooting(proc.info)){
7706 if (procsToKill == null) {
7707 procsToKill = new ArrayList<ProcessRecord>();
7708 }
7709 procsToKill.add(proc);
7710 }
7711 }
7712 }
7713
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007714 synchronized(this) {
7715 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007716 for (int i=procsToKill.size()-1; i>=0; i--) {
7717 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007718 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007719 removeProcessLocked(proc, true, false, "system update done");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007720 }
7721 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007722
7723 // Now that we have cleaned up any update processes, we
7724 // are ready to start launching real processes and know that
7725 // we won't trample on them any more.
7726 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007727 }
7728
Joe Onorato8a9b2202010-02-26 18:56:32 -08007729 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007730 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 SystemClock.uptimeMillis());
7732
7733 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007734 // Make sure we have no pre-ready processes sitting around.
7735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
7737 ResolveInfo ri = mContext.getPackageManager()
7738 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07007739 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 CharSequence errorMsg = null;
7741 if (ri != null) {
7742 ActivityInfo ai = ri.activityInfo;
7743 ApplicationInfo app = ai.applicationInfo;
7744 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7745 mTopAction = Intent.ACTION_FACTORY_TEST;
7746 mTopData = null;
7747 mTopComponent = new ComponentName(app.packageName,
7748 ai.name);
7749 } else {
7750 errorMsg = mContext.getResources().getText(
7751 com.android.internal.R.string.factorytest_not_system);
7752 }
7753 } else {
7754 errorMsg = mContext.getResources().getText(
7755 com.android.internal.R.string.factorytest_no_action);
7756 }
7757 if (errorMsg != null) {
7758 mTopAction = null;
7759 mTopData = null;
7760 mTopComponent = null;
7761 Message msg = Message.obtain();
7762 msg.what = SHOW_FACTORY_ERROR_MSG;
7763 msg.getData().putCharSequence("msg", errorMsg);
7764 mHandler.sendMessage(msg);
7765 }
7766 }
7767 }
7768
7769 retrieveSettings();
7770
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007771 if (goingCallback != null) goingCallback.run();
7772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 synchronized (this) {
7774 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
7775 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007776 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007777 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007778 if (apps != null) {
7779 int N = apps.size();
7780 int i;
7781 for (i=0; i<N; i++) {
7782 ApplicationInfo info
7783 = (ApplicationInfo)apps.get(i);
7784 if (info != null &&
7785 !info.packageName.equals("android")) {
7786 addAppLocked(info);
7787 }
7788 }
7789 }
7790 } catch (RemoteException ex) {
7791 // pm is in same process, this will never happen.
7792 }
7793 }
7794
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007795 // Start up initial activity.
7796 mBooting = true;
7797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007799 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 Message msg = Message.obtain();
7801 msg.what = SHOW_UID_ERROR_MSG;
7802 mHandler.sendMessage(msg);
7803 }
7804 } catch (RemoteException e) {
7805 }
7806
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007807 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 }
7809 }
7810
Dan Egnorb7f03672009-12-09 16:22:32 -08007811 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007812 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007814 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007815 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 startAppProblemLocked(app);
7817 app.stopFreezingAllLocked();
7818 return handleAppCrashLocked(app);
7819 }
7820
Dan Egnorb7f03672009-12-09 16:22:32 -08007821 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007822 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007824 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007825 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
7826 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 startAppProblemLocked(app);
7828 app.stopFreezingAllLocked();
7829 }
7830
7831 /**
7832 * Generate a process error record, suitable for attachment to a ProcessRecord.
7833 *
7834 * @param app The ProcessRecord in which the error occurred.
7835 * @param condition Crashing, Application Not Responding, etc. Values are defined in
7836 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08007837 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 * @param shortMsg Short message describing the crash.
7839 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08007840 * @param stackTrace Full crash stack trace, may be null.
7841 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 * @return Returns a fully-formed AppErrorStateInfo record.
7843 */
7844 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007845 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08007847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 report.condition = condition;
7849 report.processName = app.processName;
7850 report.pid = app.pid;
7851 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08007852 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 report.shortMsg = shortMsg;
7854 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08007855 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856
7857 return report;
7858 }
7859
Dan Egnor42471dd2010-01-07 17:25:22 -08007860 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861 synchronized (this) {
7862 app.crashing = false;
7863 app.crashingReport = null;
7864 app.notResponding = false;
7865 app.notRespondingReport = null;
7866 if (app.anrDialog == fromDialog) {
7867 app.anrDialog = null;
7868 }
7869 if (app.waitDialog == fromDialog) {
7870 app.waitDialog = null;
7871 }
7872 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08007873 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007874 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07007875 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
7876 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007877 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 }
7880 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007881
Dan Egnorb7f03672009-12-09 16:22:32 -08007882 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 long now = SystemClock.uptimeMillis();
7884
7885 Long crashTime = mProcessCrashTimes.get(app.info.processName,
7886 app.info.uid);
Dianne Hackborn7d608422011-08-07 16:24:18 -07007887 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007889 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007891 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007893 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
7894 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007896 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007898 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 }
7900 }
7901 if (!app.persistent) {
7902 // We don't want to start this process again until the user
7903 // explicitly does so... but for persistent process, we really
7904 // need to keep it running. If a persistent process is actually
7905 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08007906 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 app.info.processName);
7908 mBadProcesses.put(app.info.processName, app.info.uid, now);
7909 app.bad = true;
7910 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
7911 app.removed = true;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07007912 // Don't let services in this process be restarted and potentially
7913 // annoy the user repeatedly. Unless it is persistent, since those
7914 // processes run critical code.
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007915 removeProcessLocked(app, false, false, "crash");
Dianne Hackborncb44d962011-03-10 17:02:27 -08007916 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 return false;
7918 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08007919 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007920 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007921 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007922 if (r.app == app) {
7923 // If the top running activity is from this crashing
7924 // process, then terminate it to avoid getting in a loop.
7925 Slog.w(TAG, " Force finishing activity "
7926 + r.intent.getComponent().flattenToShortString());
Dianne Hackbornbe707852011-11-11 14:32:10 -08007927 int index = mMainStack.indexOfActivityLocked(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007928 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007929 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08007930 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007931 // stopped, to avoid a situation where one will get
7932 // re-start our crashing activity once it gets resumed again.
7933 index--;
7934 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007935 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007936 if (r.state == ActivityState.RESUMED
7937 || r.state == ActivityState.PAUSING
7938 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08007939 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007940 Slog.w(TAG, " Force finishing activity "
7941 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007942 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007943 Activity.RESULT_CANCELED, null, "crashed");
7944 }
7945 }
7946 }
7947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 }
7949
7950 // Bump up the crash count of any services currently running in the proc.
7951 if (app.services.size() != 0) {
7952 // Any services running in the application need to be placed
7953 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007954 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007956 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 sr.crashCount++;
7958 }
7959 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02007960
7961 // If the crashing process is what we consider to be the "home process" and it has been
7962 // replaced by a third-party app, clear the package preferred activities from packages
7963 // with a home activity running in the process to prevent a repeatedly crashing app
7964 // from blocking the user to manually clear the list.
7965 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
7966 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
7967 Iterator it = mHomeProcess.activities.iterator();
7968 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07007969 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02007970 if (r.isHomeActivity) {
7971 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
7972 try {
7973 ActivityThread.getPackageManager()
7974 .clearPackagePreferredActivities(r.packageName);
7975 } catch (RemoteException c) {
7976 // pm is in same process, this will never happen.
7977 }
7978 }
7979 }
7980 }
7981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007982 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
7983 return true;
7984 }
7985
7986 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007987 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
7988 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989 skipCurrentReceiverLocked(app);
7990 }
7991
7992 void skipCurrentReceiverLocked(ProcessRecord app) {
Christopher Tatef46723b2012-01-26 14:19:24 -08007993 for (BroadcastQueue queue : mBroadcastQueues) {
7994 queue.skipCurrentReceiverLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007995 }
7996 }
7997
Dan Egnor60d87622009-12-16 16:32:58 -08007998 /**
7999 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8000 * The application process will exit immediately after this call returns.
8001 * @param app object of the crashing app, null for the system server
8002 * @param crashInfo describing the exception
8003 */
8004 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08008005 ProcessRecord r = findAppProcess(app, "Crash");
Jeff Sharkeya353d262011-10-28 11:12:06 -07008006 final String processName = app == null ? "system_server"
8007 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08008008
8009 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07008010 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08008011 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008012 crashInfo.exceptionClassName,
8013 crashInfo.exceptionMessage,
8014 crashInfo.throwFileName,
8015 crashInfo.throwLineNumber);
8016
Jeff Sharkeya353d262011-10-28 11:12:06 -07008017 addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008018
8019 crashApplication(r, crashInfo);
8020 }
8021
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008022 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008023 IBinder app,
8024 int violationMask,
8025 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08008026 ProcessRecord r = findAppProcess(app, "StrictMode");
8027 if (r == null) {
8028 return;
8029 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008030
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008031 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08008032 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008033 boolean logIt = true;
8034 synchronized (mAlreadyLoggedViolatedStacks) {
8035 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
8036 logIt = false;
8037 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008038 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008039 // the relative pain numbers, without logging all
8040 // the stack traces repeatedly. We'd want to do
8041 // likewise in the client code, which also does
8042 // dup suppression, before the Binder call.
8043 } else {
8044 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
8045 mAlreadyLoggedViolatedStacks.clear();
8046 }
8047 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
8048 }
8049 }
8050 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008051 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008052 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008053 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008054
8055 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
8056 AppErrorResult result = new AppErrorResult();
8057 synchronized (this) {
8058 final long origId = Binder.clearCallingIdentity();
8059
8060 Message msg = Message.obtain();
8061 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
8062 HashMap<String, Object> data = new HashMap<String, Object>();
8063 data.put("result", result);
8064 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07008065 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008066 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008067 msg.obj = data;
8068 mHandler.sendMessage(msg);
8069
8070 Binder.restoreCallingIdentity(origId);
8071 }
8072 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07008073 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07008074 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07008075 }
8076
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008077 // Depending on the policy in effect, there could be a bunch of
8078 // these in quick succession so we try to batch these together to
8079 // minimize disk writes, number of dropbox entries, and maximize
8080 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008081 private void logStrictModeViolationToDropBox(
8082 ProcessRecord process,
8083 StrictMode.ViolationInfo info) {
8084 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008085 return;
8086 }
8087 final boolean isSystemApp = process == null ||
8088 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
8089 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07008090 final String processName = process == null ? "unknown" : process.processName;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008091 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
8092 final DropBoxManager dbox = (DropBoxManager)
8093 mContext.getSystemService(Context.DROPBOX_SERVICE);
8094
8095 // Exit early if the dropbox isn't configured to accept this report type.
8096 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
8097
8098 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008099 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008100 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
8101 synchronized (sb) {
8102 bufferWasEmpty = sb.length() == 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07008103 appendDropBoxProcessHeaders(process, processName, sb);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008104 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8105 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008106 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
8107 if (info.violationNumThisLoop != 0) {
8108 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
8109 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07008110 if (info.numAnimationsRunning != 0) {
8111 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
8112 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07008113 if (info.broadcastIntentAction != null) {
8114 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
8115 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08008116 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008117 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008118 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08008119 if (info.numInstances != -1) {
8120 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
8121 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08008122 if (info.tags != null) {
8123 for (String tag : info.tags) {
8124 sb.append("Span-Tag: ").append(tag).append("\n");
8125 }
8126 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008127 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07008128 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
8129 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008130 }
8131 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008132
8133 // Only buffer up to ~64k. Various logging bits truncate
8134 // things at 128k.
8135 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008136 }
8137
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008138 // Flush immediately if the buffer's grown too large, or this
8139 // is a non-system app. Non-system apps are isolated with a
8140 // different tag & policy and not batched.
8141 //
8142 // Batching is useful during internal testing with
8143 // StrictMode settings turned up high. Without batching,
8144 // thousands of separate files could be created on boot.
8145 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008146 new Thread("Error dump: " + dropboxTag) {
8147 @Override
8148 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008149 String report;
8150 synchronized (sb) {
8151 report = sb.toString();
8152 sb.delete(0, sb.length());
8153 sb.trimToSize();
8154 }
8155 if (report.length() != 0) {
8156 dbox.addText(dropboxTag, report);
8157 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008158 }
8159 }.start();
8160 return;
8161 }
8162
8163 // System app batching:
8164 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07008165 // An existing dropbox-writing thread is outstanding, so
8166 // we don't need to start it up. The existing thread will
8167 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008168 return;
8169 }
8170
8171 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
8172 // (After this point, we shouldn't access AMS internal data structures.)
8173 new Thread("Error dump: " + dropboxTag) {
8174 @Override
8175 public void run() {
8176 // 5 second sleep to let stacks arrive and be batched together
8177 try {
8178 Thread.sleep(5000); // 5 seconds
8179 } catch (InterruptedException e) {}
8180
8181 String errorReport;
8182 synchronized (mStrictModeBuffer) {
8183 errorReport = mStrictModeBuffer.toString();
8184 if (errorReport.length() == 0) {
8185 return;
8186 }
8187 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
8188 mStrictModeBuffer.trimToSize();
8189 }
8190 dbox.addText(dropboxTag, errorReport);
8191 }
8192 }.start();
8193 }
8194
Dan Egnor60d87622009-12-16 16:32:58 -08008195 /**
8196 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8197 * @param app object of the crashing app, null for the system server
8198 * @param tag reported by the caller
8199 * @param crashInfo describing the context of the error
8200 * @return true if the process should exit immediately (WTF is fatal)
8201 */
8202 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008203 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08008204 ProcessRecord r = findAppProcess(app, "WTF");
Jeff Sharkeya353d262011-10-28 11:12:06 -07008205 final String processName = app == null ? "system_server"
8206 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08008207
8208 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07008209 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08008210 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008211 tag, crashInfo.exceptionMessage);
8212
Jeff Sharkeya353d262011-10-28 11:12:06 -07008213 addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008214
Dianne Hackborn1ab43772011-03-15 14:38:02 -07008215 if (r != null && r.pid != Process.myPid() &&
8216 Settings.Secure.getInt(mContext.getContentResolver(),
8217 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008218 crashApplication(r, crashInfo);
8219 return true;
8220 } else {
8221 return false;
8222 }
8223 }
8224
8225 /**
8226 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8227 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8228 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08008229 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08008230 if (app == null) {
8231 return null;
8232 }
8233
8234 synchronized (this) {
8235 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8236 final int NA = apps.size();
8237 for (int ia=0; ia<NA; ia++) {
8238 ProcessRecord p = apps.valueAt(ia);
8239 if (p.thread != null && p.thread.asBinder() == app) {
8240 return p;
8241 }
8242 }
8243 }
8244
Dianne Hackborncb44d962011-03-10 17:02:27 -08008245 Slog.w(TAG, "Can't find mystery application for " + reason
8246 + " from pid=" + Binder.getCallingPid()
8247 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008248 return null;
8249 }
8250 }
8251
8252 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008253 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
8254 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08008255 */
Jeff Sharkeya353d262011-10-28 11:12:06 -07008256 private void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
8257 StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08008258 // Watchdog thread ends up invoking this function (with
8259 // a null ProcessRecord) to add the stack file to dropbox.
8260 // Do not acquire a lock on this (am) in such cases, as it
8261 // could cause a potential deadlock, if and when watchdog
8262 // is invoked due to unavailability of lock on am and it
8263 // would prevent watchdog from killing system_server.
8264 if (process == null) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07008265 sb.append("Process: ").append(processName).append("\n");
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08008266 return;
8267 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07008268 // Note: ProcessRecord 'process' is guarded by the service
8269 // instance. (notably process.pkgList, which could otherwise change
8270 // concurrently during execution of this method)
8271 synchronized (this) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07008272 sb.append("Process: ").append(processName).append("\n");
Dan Egnora455d192010-03-12 08:52:28 -08008273 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008274 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08008275 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8276 for (String pkg : process.pkgList) {
8277 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08008278 try {
Dan Egnora455d192010-03-12 08:52:28 -08008279 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8280 if (pi != null) {
8281 sb.append(" v").append(pi.versionCode);
8282 if (pi.versionName != null) {
8283 sb.append(" (").append(pi.versionName).append(")");
8284 }
8285 }
8286 } catch (RemoteException e) {
8287 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008288 }
Dan Egnora455d192010-03-12 08:52:28 -08008289 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08008290 }
Dan Egnora455d192010-03-12 08:52:28 -08008291 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008292 }
8293
8294 private static String processClass(ProcessRecord process) {
8295 if (process == null || process.pid == MY_PID) {
8296 return "system_server";
8297 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
8298 return "system_app";
8299 } else {
8300 return "data_app";
8301 }
8302 }
8303
8304 /**
8305 * Write a description of an error (crash, WTF, ANR) to the drop box.
8306 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
8307 * @param process which caused the error, null means the system server
8308 * @param activity which triggered the error, null if unknown
8309 * @param parent activity related to the error, null if unknown
8310 * @param subject line related to the error, null if absent
8311 * @param report in long form describing the error, null if absent
8312 * @param logFile to include in the report, null if none
8313 * @param crashInfo giving an application stack trace, null if absent
8314 */
8315 public void addErrorToDropBox(String eventType,
Jeff Sharkeya353d262011-10-28 11:12:06 -07008316 ProcessRecord process, String processName, ActivityRecord activity,
8317 ActivityRecord parent, String subject,
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07008318 final String report, final File logFile,
8319 final ApplicationErrorReport.CrashInfo crashInfo) {
8320 // NOTE -- this must never acquire the ActivityManagerService lock,
8321 // otherwise the watchdog may be prevented from resetting the system.
8322
8323 final String dropboxTag = processClass(process) + "_" + eventType;
8324 final DropBoxManager dbox = (DropBoxManager)
8325 mContext.getSystemService(Context.DROPBOX_SERVICE);
8326
8327 // Exit early if the dropbox isn't configured to accept this report type.
8328 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
8329
8330 final StringBuilder sb = new StringBuilder(1024);
Jeff Sharkeya353d262011-10-28 11:12:06 -07008331 appendDropBoxProcessHeaders(process, processName, sb);
Dan Egnora455d192010-03-12 08:52:28 -08008332 if (activity != null) {
8333 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8334 }
8335 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8336 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8337 }
8338 if (parent != null && parent != activity) {
8339 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8340 }
8341 if (subject != null) {
8342 sb.append("Subject: ").append(subject).append("\n");
8343 }
8344 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02008345 if (Debug.isDebuggerConnected()) {
8346 sb.append("Debugger: Connected\n");
8347 }
Dan Egnora455d192010-03-12 08:52:28 -08008348 sb.append("\n");
8349
8350 // Do the rest in a worker thread to avoid blocking the caller on I/O
8351 // (After this point, we shouldn't access AMS internal data structures.)
8352 Thread worker = new Thread("Error dump: " + dropboxTag) {
8353 @Override
8354 public void run() {
8355 if (report != null) {
8356 sb.append(report);
8357 }
8358 if (logFile != null) {
8359 try {
8360 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8361 } catch (IOException e) {
8362 Slog.e(TAG, "Error reading " + logFile, e);
8363 }
8364 }
8365 if (crashInfo != null && crashInfo.stackTrace != null) {
8366 sb.append(crashInfo.stackTrace);
8367 }
8368
8369 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
8370 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
8371 if (lines > 0) {
8372 sb.append("\n");
8373
8374 // Merge several logcat streams, and take the last N lines
8375 InputStreamReader input = null;
8376 try {
8377 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
8378 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
8379 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
8380
8381 try { logcat.getOutputStream().close(); } catch (IOException e) {}
8382 try { logcat.getErrorStream().close(); } catch (IOException e) {}
8383 input = new InputStreamReader(logcat.getInputStream());
8384
8385 int num;
8386 char[] buf = new char[8192];
8387 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
8388 } catch (IOException e) {
8389 Slog.e(TAG, "Error running logcat", e);
8390 } finally {
8391 if (input != null) try { input.close(); } catch (IOException e) {}
8392 }
8393 }
8394
8395 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08008396 }
Dan Egnora455d192010-03-12 08:52:28 -08008397 };
8398
8399 if (process == null || process.pid == MY_PID) {
8400 worker.run(); // We may be about to die -- need to run this synchronously
8401 } else {
8402 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08008403 }
8404 }
8405
8406 /**
8407 * Bring up the "unexpected error" dialog box for a crashing app.
8408 * Deal with edge cases (intercepts from instrumented applications,
8409 * ActivityController, error intent receivers, that sort of thing).
8410 * @param r the application crashing
8411 * @param crashInfo describing the failure
8412 */
8413 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008414 long timeMillis = System.currentTimeMillis();
8415 String shortMsg = crashInfo.exceptionClassName;
8416 String longMsg = crashInfo.exceptionMessage;
8417 String stackTrace = crashInfo.stackTrace;
8418 if (shortMsg != null && longMsg != null) {
8419 longMsg = shortMsg + ": " + longMsg;
8420 } else if (shortMsg != null) {
8421 longMsg = shortMsg;
8422 }
8423
Dan Egnor60d87622009-12-16 16:32:58 -08008424 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008426 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427 try {
8428 String name = r != null ? r.processName : null;
8429 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008430 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008431 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008432 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 + " at watcher's request");
8434 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008435 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 }
8437 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008438 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 }
8440 }
8441
8442 final long origId = Binder.clearCallingIdentity();
8443
8444 // If this process is running instrumentation, finish it.
8445 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008446 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008448 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
8449 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008450 Bundle info = new Bundle();
8451 info.putString("shortMsg", shortMsg);
8452 info.putString("longMsg", longMsg);
8453 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8454 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008455 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008456 }
8457
Dan Egnor60d87622009-12-16 16:32:58 -08008458 // If we can't identify the process or it's already exceeded its crash quota,
8459 // quit right away without showing a crash dialog.
8460 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008462 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 }
8464
8465 Message msg = Message.obtain();
8466 msg.what = SHOW_ERROR_MSG;
8467 HashMap data = new HashMap();
8468 data.put("result", result);
8469 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 msg.obj = data;
8471 mHandler.sendMessage(msg);
8472
8473 Binder.restoreCallingIdentity(origId);
8474 }
8475
8476 int res = result.get();
8477
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008478 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 synchronized (this) {
8480 if (r != null) {
8481 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8482 SystemClock.uptimeMillis());
8483 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008484 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008485 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008486 }
8487 }
8488
8489 if (appErrorIntent != null) {
8490 try {
8491 mContext.startActivity(appErrorIntent);
8492 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008493 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 }
Dan Egnorb7f03672009-12-09 16:22:32 -08008497
8498 Intent createAppErrorIntentLocked(ProcessRecord r,
8499 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
8500 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008501 if (report == null) {
8502 return null;
8503 }
8504 Intent result = new Intent(Intent.ACTION_APP_ERROR);
8505 result.setComponent(r.errorReportReceiver);
8506 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
8507 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8508 return result;
8509 }
8510
Dan Egnorb7f03672009-12-09 16:22:32 -08008511 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
8512 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008513 if (r.errorReportReceiver == null) {
8514 return null;
8515 }
8516
8517 if (!r.crashing && !r.notResponding) {
8518 return null;
8519 }
8520
Dan Egnorb7f03672009-12-09 16:22:32 -08008521 ApplicationErrorReport report = new ApplicationErrorReport();
8522 report.packageName = r.info.packageName;
8523 report.installerPackageName = r.errorReportReceiver.getPackageName();
8524 report.processName = r.processName;
8525 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01008526 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008527
Dan Egnorb7f03672009-12-09 16:22:32 -08008528 if (r.crashing) {
8529 report.type = ApplicationErrorReport.TYPE_CRASH;
8530 report.crashInfo = crashInfo;
8531 } else if (r.notResponding) {
8532 report.type = ApplicationErrorReport.TYPE_ANR;
8533 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008534
Dan Egnorb7f03672009-12-09 16:22:32 -08008535 report.anrInfo.activity = r.notRespondingReport.tag;
8536 report.anrInfo.cause = r.notRespondingReport.shortMsg;
8537 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008538 }
8539
Dan Egnorb7f03672009-12-09 16:22:32 -08008540 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008541 }
8542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
8544 // assume our apps are happy - lazy create the list
8545 List<ActivityManager.ProcessErrorStateInfo> errList = null;
8546
8547 synchronized (this) {
8548
8549 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008550 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8551 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 if ((app.thread != null) && (app.crashing || app.notResponding)) {
8553 // This one's in trouble, so we'll generate a report for it
8554 // crashes are higher priority (in case there's a crash *and* an anr)
8555 ActivityManager.ProcessErrorStateInfo report = null;
8556 if (app.crashing) {
8557 report = app.crashingReport;
8558 } else if (app.notResponding) {
8559 report = app.notRespondingReport;
8560 }
8561
8562 if (report != null) {
8563 if (errList == null) {
8564 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
8565 }
8566 errList.add(report);
8567 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008568 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 " crashing = " + app.crashing +
8570 " notResponding = " + app.notResponding);
8571 }
8572 }
8573 }
8574 }
8575
8576 return errList;
8577 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07008578
8579 static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008580 if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07008581 if (currApp != null) {
8582 currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
8583 }
8584 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008585 } else if (adj >= ProcessList.SERVICE_B_ADJ) {
8586 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008587 } else if (adj >= ProcessList.HOME_APP_ADJ) {
8588 if (currApp != null) {
8589 currApp.lru = 0;
8590 }
8591 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008592 } else if (adj >= ProcessList.SERVICE_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07008593 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
8594 } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
8595 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
8596 } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
8597 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
8598 } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
8599 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
8600 } else {
8601 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
8602 }
8603 }
8604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
8606 // Lazy instantiation of list
8607 List<ActivityManager.RunningAppProcessInfo> runList = null;
8608 synchronized (this) {
8609 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008610 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8611 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
8613 // Generate process state info for running application
8614 ActivityManager.RunningAppProcessInfo currApp =
8615 new ActivityManager.RunningAppProcessInfo(app.processName,
8616 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07008617 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07008618 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07008619 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07008620 }
Dianne Hackborn42499172010-10-15 18:45:07 -07008621 if (app.persistent) {
8622 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
8623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 int adj = app.curAdj;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008625 currApp.importance = oomAdjToImportance(adj, currApp);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008626 currApp.importanceReasonCode = app.adjTypeCode;
8627 if (app.adjSource instanceof ProcessRecord) {
8628 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008629 currApp.importanceReasonImportance = oomAdjToImportance(
8630 app.adjSourceOom, null);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008631 } else if (app.adjSource instanceof ActivityRecord) {
8632 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008633 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
8634 }
8635 if (app.adjTarget instanceof ComponentName) {
8636 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
8637 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008638 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 // + " lru=" + currApp.lru);
8640 if (runList == null) {
8641 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
8642 }
8643 runList.add(currApp);
8644 }
8645 }
8646 }
8647 return runList;
8648 }
8649
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008650 public List<ApplicationInfo> getRunningExternalApplications() {
8651 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
8652 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
8653 if (runningApps != null && runningApps.size() > 0) {
8654 Set<String> extList = new HashSet<String>();
8655 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
8656 if (app.pkgList != null) {
8657 for (String pkg : app.pkgList) {
8658 extList.add(pkg);
8659 }
8660 }
8661 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008662 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008663 for (String pkg : extList) {
8664 try {
8665 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
8666 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
8667 retList.add(info);
8668 }
8669 } catch (RemoteException e) {
8670 }
8671 }
8672 }
8673 return retList;
8674 }
8675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 @Override
8677 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008678 if (checkCallingPermission(android.Manifest.permission.DUMP)
8679 != PackageManager.PERMISSION_GRANTED) {
8680 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8681 + Binder.getCallingPid()
8682 + ", uid=" + Binder.getCallingUid()
8683 + " without permission "
8684 + android.Manifest.permission.DUMP);
8685 return;
8686 }
8687
8688 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008689 boolean dumpClient = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008690 String dumpPackage = null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008691
8692 int opti = 0;
8693 while (opti < args.length) {
8694 String opt = args[opti];
8695 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
8696 break;
8697 }
8698 opti++;
8699 if ("-a".equals(opt)) {
8700 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008701 } else if ("-c".equals(opt)) {
8702 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008703 } else if ("-h".equals(opt)) {
8704 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008705 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008706 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008707 pw.println(" a[ctivities]: activity stack state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008708 pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
8709 pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
8710 pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008711 pw.println(" o[om]: out of memory management");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008712 pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
Marco Nelissen18cb2872011-11-15 11:19:53 -08008713 pw.println(" provider [COMP_SPEC]: provider client-side state");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008714 pw.println(" s[ervices] [COMP_SPEC ...]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008715 pw.println(" service [COMP_SPEC]: service client-side state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008716 pw.println(" package [PACKAGE_NAME]: all state related to given package");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008717 pw.println(" all: dump all activities");
8718 pw.println(" top: dump the top activity");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008719 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008720 pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
8721 pw.println(" a partial substring in a component name, a");
8722 pw.println(" hex object identifier.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008723 pw.println(" -a: include all available server state.");
8724 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008726 } else {
8727 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008729 }
8730
8731 // Is the caller requesting to dump a particular piece of data?
8732 if (opti < args.length) {
8733 String cmd = args[opti];
8734 opti++;
8735 if ("activities".equals(cmd) || "a".equals(cmd)) {
8736 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008737 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008739 return;
8740 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008741 String[] newArgs;
8742 String name;
8743 if (opti >= args.length) {
8744 name = null;
8745 newArgs = EMPTY_STRING_ARRAY;
8746 } else {
8747 name = args[opti];
8748 opti++;
8749 newArgs = new String[args.length - opti];
8750 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8751 args.length - opti);
8752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008753 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008754 dumpBroadcastsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008755 }
8756 return;
8757 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008758 String[] newArgs;
8759 String name;
8760 if (opti >= args.length) {
8761 name = null;
8762 newArgs = EMPTY_STRING_ARRAY;
8763 } else {
8764 name = args[opti];
8765 opti++;
8766 newArgs = new String[args.length - opti];
8767 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8768 args.length - opti);
8769 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008770 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008771 dumpPendingIntentsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008772 }
8773 return;
8774 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008775 String[] newArgs;
8776 String name;
8777 if (opti >= args.length) {
8778 name = null;
8779 newArgs = EMPTY_STRING_ARRAY;
8780 } else {
8781 name = args[opti];
8782 opti++;
8783 newArgs = new String[args.length - opti];
8784 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8785 args.length - opti);
8786 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008787 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008788 dumpProcessesLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008789 }
8790 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008791 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
8792 synchronized (this) {
8793 dumpOomLocked(fd, pw, args, opti, true);
8794 }
8795 return;
Marco Nelissen18cb2872011-11-15 11:19:53 -08008796 } else if ("provider".equals(cmd)) {
8797 String[] newArgs;
8798 String name;
8799 if (opti >= args.length) {
8800 name = null;
8801 newArgs = EMPTY_STRING_ARRAY;
8802 } else {
8803 name = args[opti];
8804 opti++;
8805 newArgs = new String[args.length - opti];
8806 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8807 }
8808 if (!dumpProvider(fd, pw, name, newArgs, 0, dumpAll)) {
8809 pw.println("No providers match: " + name);
8810 pw.println("Use -h for help.");
8811 }
8812 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008813 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
8814 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008815 dumpProvidersLocked(fd, pw, args, opti, true, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008816 }
8817 return;
8818 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008819 String[] newArgs;
8820 String name;
8821 if (opti >= args.length) {
8822 name = null;
8823 newArgs = EMPTY_STRING_ARRAY;
8824 } else {
8825 name = args[opti];
8826 opti++;
8827 newArgs = new String[args.length - opti];
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008828 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8829 args.length - opti);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008830 }
8831 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
8832 pw.println("No services match: " + name);
8833 pw.println("Use -h for help.");
8834 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008835 return;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008836 } else if ("package".equals(cmd)) {
8837 String[] newArgs;
8838 if (opti >= args.length) {
8839 pw.println("package: no package name specified");
8840 pw.println("Use -h for help.");
8841 return;
8842 } else {
8843 dumpPackage = args[opti];
8844 opti++;
8845 newArgs = new String[args.length - opti];
8846 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8847 args.length - opti);
8848 args = newArgs;
8849 opti = 0;
8850 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008851 } else if ("services".equals(cmd) || "s".equals(cmd)) {
8852 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008853 dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008854 }
8855 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07008856 } else {
8857 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008858 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
8859 pw.println("Bad activity command, or no activities match: " + cmd);
8860 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008861 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008862 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008863 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008864 }
8865
8866 // No piece of data specified, dump everything.
8867 synchronized (this) {
8868 boolean needSep;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008869 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008870 if (needSep) {
8871 pw.println(" ");
8872 }
8873 if (dumpAll) {
8874 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008875 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008876 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008877 if (needSep) {
8878 pw.println(" ");
8879 }
8880 if (dumpAll) {
8881 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008882 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008883 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008884 if (needSep) {
8885 pw.println(" ");
8886 }
8887 if (dumpAll) {
8888 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008889 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008890 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008891 if (needSep) {
8892 pw.println(" ");
8893 }
8894 if (dumpAll) {
8895 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008896 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008897 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008898 if (needSep) {
8899 pw.println(" ");
8900 }
8901 if (dumpAll) {
8902 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008903 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008904 dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008905 }
8906 }
8907
8908 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008909 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008910 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
8911 pw.println(" Main stack:");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008912 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient,
8913 dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008914 pw.println(" ");
8915 pw.println(" Running activities (most recent first):");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008916 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false,
8917 dumpPackage);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008918 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008919 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008920 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008921 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008922 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008923 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008924 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008925 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008926 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008927 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008928 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008929 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08008930 if (mMainStack.mGoingToSleepActivities.size() > 0) {
8931 pw.println(" ");
8932 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008933 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008934 !dumpAll, false, dumpPackage);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08008935 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008936 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008937 pw.println(" ");
8938 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008939 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008940 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008943 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008944 if (mMainStack.mPausingActivity != null) {
8945 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
8946 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008947 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008948 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008949 if (dumpAll) {
8950 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
8951 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07008952 pw.println(" mDismissKeyguardOnNextActivity: "
8953 + mMainStack.mDismissKeyguardOnNextActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008955
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008956 if (mRecentTasks.size() > 0) {
8957 pw.println();
8958 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008959
8960 final int N = mRecentTasks.size();
8961 for (int i=0; i<N; i++) {
8962 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008963 if (dumpPackage != null) {
8964 if (tr.realActivity == null ||
8965 !dumpPackage.equals(tr.realActivity)) {
8966 continue;
8967 }
8968 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008969 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
8970 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008971 if (dumpAll) {
8972 mRecentTasks.get(i).dump(pw, " ");
8973 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008974 }
8975 }
8976
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008977 if (dumpAll) {
8978 pw.println(" ");
8979 pw.println(" mCurTask: " + mCurTask);
8980 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008981
8982 return true;
8983 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008984
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008985 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008986 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008987 boolean needSep = false;
8988 int numPers = 0;
8989
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008990 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
8991
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008992 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
8994 final int NA = procs.size();
8995 for (int ia=0; ia<NA; ia++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008996 ProcessRecord r = procs.valueAt(ia);
8997 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
8998 continue;
8999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 if (!needSep) {
9001 pw.println(" All known processes:");
9002 needSep = true;
9003 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009004 pw.print(r.persistent ? " *PERS*" : " *APP*");
9005 pw.print(" UID "); pw.print(procs.keyAt(ia));
9006 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009007 r.dump(pw, " ");
9008 if (r.persistent) {
9009 numPers++;
9010 }
9011 }
9012 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009013 }
9014
9015 if (mLruProcesses.size() > 0) {
9016 if (needSep) pw.println(" ");
9017 needSep = true;
Dianne Hackborn905577f2011-09-07 18:31:28 -07009018 pw.println(" Process LRU list (sorted by oom_adj):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07009019 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009020 "Proc", "PERS", false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009021 needSep = true;
9022 }
9023
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009024 if (dumpAll) {
9025 synchronized (mPidsSelfLocked) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009026 boolean printed = false;
9027 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9028 ProcessRecord r = mPidsSelfLocked.valueAt(i);
9029 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9030 continue;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009031 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009032 if (!printed) {
9033 if (needSep) pw.println(" ");
9034 needSep = true;
9035 pw.println(" PID mappings:");
9036 printed = true;
9037 }
9038 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9039 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 }
9041 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009042 }
9043
9044 if (mForegroundProcesses.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009045 synchronized (mPidsSelfLocked) {
9046 boolean printed = false;
9047 for (int i=0; i<mForegroundProcesses.size(); i++) {
9048 ProcessRecord r = mPidsSelfLocked.get(
9049 mForegroundProcesses.valueAt(i).pid);
9050 if (dumpPackage != null && (r == null
9051 || !dumpPackage.equals(r.info.packageName))) {
9052 continue;
9053 }
9054 if (!printed) {
9055 if (needSep) pw.println(" ");
9056 needSep = true;
9057 pw.println(" Foreground Processes:");
9058 printed = true;
9059 }
9060 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9061 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
9062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009064 }
9065
9066 if (mPersistentStartingProcesses.size() > 0) {
9067 if (needSep) pw.println(" ");
9068 needSep = true;
9069 pw.println(" Persisent processes that are starting:");
9070 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009071 "Starting Norm", "Restarting PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009074 if (mRemovedProcesses.size() > 0) {
9075 if (needSep) pw.println(" ");
9076 needSep = true;
9077 pw.println(" Processes that are being removed:");
9078 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009079 "Removed Norm", "Removed PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009080 }
9081
9082 if (mProcessesOnHold.size() > 0) {
9083 if (needSep) pw.println(" ");
9084 needSep = true;
9085 pw.println(" Processes that are on old until the system is ready:");
9086 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009087 "OnHold Norm", "OnHold PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009090 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009091
9092 if (mProcessCrashTimes.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009093 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009094 long now = SystemClock.uptimeMillis();
9095 for (Map.Entry<String, SparseArray<Long>> procs
9096 : mProcessCrashTimes.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009097 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009098 SparseArray<Long> uids = procs.getValue();
9099 final int N = uids.size();
9100 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009101 int puid = uids.keyAt(i);
9102 ProcessRecord r = mProcessNames.get(pname, puid);
9103 if (dumpPackage != null && (r == null
9104 || !dumpPackage.equals(r.info.packageName))) {
9105 continue;
9106 }
9107 if (!printed) {
9108 if (needSep) pw.println(" ");
9109 needSep = true;
9110 pw.println(" Time since processes crashed:");
9111 printed = true;
9112 }
9113 pw.print(" Process "); pw.print(pname);
9114 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009115 pw.print(": last crashed ");
9116 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009117 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009118 }
9119 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009122 if (mBadProcesses.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009123 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009124 for (Map.Entry<String, SparseArray<Long>> procs
9125 : mBadProcesses.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009126 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009127 SparseArray<Long> uids = procs.getValue();
9128 final int N = uids.size();
9129 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009130 int puid = uids.keyAt(i);
9131 ProcessRecord r = mProcessNames.get(pname, puid);
9132 if (dumpPackage != null && (r == null
9133 || !dumpPackage.equals(r.info.packageName))) {
9134 continue;
9135 }
9136 if (!printed) {
9137 if (needSep) pw.println(" ");
9138 needSep = true;
9139 pw.println(" Bad processes:");
9140 }
9141 pw.print(" Bad process "); pw.print(pname);
9142 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009143 pw.print(": crashed at time ");
9144 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 }
9146 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009149 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009150 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009151 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn50685602011-12-01 12:23:37 -08009152 if (dumpAll) {
9153 StringBuilder sb = new StringBuilder(128);
9154 sb.append(" mPreviousProcessVisibleTime: ");
9155 TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
9156 pw.println(sb);
9157 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07009158 if (mHeavyWeightProcess != null) {
9159 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
9160 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009161 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009162 if (dumpAll) {
9163 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07009164 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009165 boolean printed = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07009166 for (Map.Entry<String, Integer> entry
9167 : mCompatModePackages.getPackages().entrySet()) {
9168 String pkg = entry.getKey();
9169 int mode = entry.getValue();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009170 if (dumpPackage != null && !dumpPackage.equals(pkg)) {
9171 continue;
9172 }
9173 if (!printed) {
9174 pw.println(" mScreenCompatPackages:");
9175 printed = true;
9176 }
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07009177 pw.print(" "); pw.print(pkg); pw.print(": ");
9178 pw.print(mode); pw.println();
9179 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07009180 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009181 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009182 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9183 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9184 || mOrigWaitForDebugger) {
9185 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9186 + " mDebugTransient=" + mDebugTransient
9187 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9188 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07009189 if (mProfileApp != null || mProfileProc != null || mProfileFile != null
9190 || mProfileFd != null) {
9191 pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
9192 pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
9193 pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
9194 + mAutoStopProfiler);
9195 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009196 if (mAlwaysFinishActivities || mController != null) {
9197 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9198 + " mController=" + mController);
9199 }
9200 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009203 + " mProcessesReady=" + mProcessesReady
9204 + " mSystemReady=" + mSystemReady);
9205 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 + " mBooted=" + mBooted
9207 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009208 pw.print(" mLastPowerCheckRealtime=");
9209 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
9210 pw.println("");
9211 pw.print(" mLastPowerCheckUptime=");
9212 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
9213 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009214 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
9215 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07009216 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009217 pw.println(" mNumServiceProcs=" + mNumServiceProcs
9218 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009220
9221 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 }
9223
Dianne Hackborn287952c2010-09-22 22:34:31 -07009224 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009225 int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009226 if (mProcessesToGc.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009227 boolean printed = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009228 long now = SystemClock.uptimeMillis();
9229 for (int i=0; i<mProcessesToGc.size(); i++) {
9230 ProcessRecord proc = mProcessesToGc.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009231 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
9232 continue;
9233 }
9234 if (!printed) {
9235 if (needSep) pw.println(" ");
9236 needSep = true;
9237 pw.println(" Processes that are waiting to GC:");
9238 printed = true;
9239 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009240 pw.print(" Process "); pw.println(proc);
9241 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9242 pw.print(", last gced=");
9243 pw.print(now-proc.lastRequestedGc);
9244 pw.print(" ms ago, last lowMem=");
9245 pw.print(now-proc.lastLowMemory);
9246 pw.println(" ms ago");
9247
9248 }
9249 }
9250 return needSep;
9251 }
9252
9253 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9254 int opti, boolean dumpAll) {
9255 boolean needSep = false;
9256
9257 if (mLruProcesses.size() > 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009258 if (needSep) pw.println(" ");
9259 needSep = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009260 pw.println(" OOM levels:");
Dianne Hackborn7d608422011-08-07 16:24:18 -07009261 pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009262 pw.print(" PERSISTENT_PROC_ADJ: "); pw.println(ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009263 pw.print(" FOREGROUND_APP_ADJ: "); pw.println(ProcessList.FOREGROUND_APP_ADJ);
9264 pw.print(" VISIBLE_APP_ADJ: "); pw.println(ProcessList.VISIBLE_APP_ADJ);
9265 pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(ProcessList.PERCEPTIBLE_APP_ADJ);
9266 pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(ProcessList.HEAVY_WEIGHT_APP_ADJ);
9267 pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009268 pw.print(" SERVICE_ADJ: "); pw.println(ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009269 pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009270 pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009271 pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009272 pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009273 pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009274
9275 if (needSep) pw.println(" ");
9276 needSep = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009277 pw.println(" Process OOM control:");
Dianne Hackborn905577f2011-09-07 18:31:28 -07009278 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009279 "Proc", "PERS", true, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009280 needSep = true;
9281 }
9282
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009283 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009284
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009285 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07009286 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009287 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009288 if (mHeavyWeightProcess != null) {
9289 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
9290 }
9291
9292 return true;
9293 }
9294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 /**
9296 * There are three ways to call this:
9297 * - no service specified: dump all the services
9298 * - a flattened component name that matched an existing service was specified as the
9299 * first arg: dump that one service
9300 * - the first arg isn't the flattened component name of an existing service:
9301 * dump all services whose component contains the first arg as a substring
9302 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009303 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
9304 int opti, boolean dumpAll) {
9305 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009307 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07009308 synchronized (this) {
9309 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009310 services.add(r1);
9311 }
9312 }
9313 } else {
9314 ComponentName componentName = name != null
9315 ? ComponentName.unflattenFromString(name) : null;
9316 int objectId = 0;
9317 if (componentName == null) {
9318 // Not a '/' separated full component name; maybe an object ID?
9319 try {
9320 objectId = Integer.parseInt(name, 16);
9321 name = null;
9322 componentName = null;
9323 } catch (RuntimeException e) {
9324 }
9325 }
9326
9327 synchronized (this) {
9328 for (ServiceRecord r1 : mServices.values()) {
9329 if (componentName != null) {
9330 if (r1.name.equals(componentName)) {
9331 services.add(r1);
9332 }
9333 } else if (name != null) {
9334 if (r1.name.flattenToString().contains(name)) {
9335 services.add(r1);
9336 }
9337 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07009338 services.add(r1);
9339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 }
9341 }
9342 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009343
9344 if (services.size() <= 0) {
9345 return false;
9346 }
9347
9348 boolean needSep = false;
9349 for (int i=0; i<services.size(); i++) {
9350 if (needSep) {
9351 pw.println();
9352 }
9353 needSep = true;
9354 dumpService("", fd, pw, services.get(i), args, dumpAll);
9355 }
9356 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 }
9358
9359 /**
9360 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9361 * there is a thread associated with the service.
9362 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009363 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
9364 final ServiceRecord r, String[] args, boolean dumpAll) {
9365 String innerPrefix = prefix + " ";
9366 synchronized (this) {
9367 pw.print(prefix); pw.print("SERVICE ");
9368 pw.print(r.shortName); pw.print(" ");
9369 pw.print(Integer.toHexString(System.identityHashCode(r)));
9370 pw.print(" pid=");
9371 if (r.app != null) pw.println(r.app.pid);
9372 else pw.println("(not running)");
9373 if (dumpAll) {
9374 r.dump(pw, innerPrefix);
9375 }
9376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009377 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009378 pw.print(prefix); pw.println(" Client:");
9379 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009380 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009381 TransferPipe tp = new TransferPipe();
9382 try {
9383 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
9384 tp.setBufferPrefix(prefix + " ");
9385 tp.go(fd);
9386 } finally {
9387 tp.kill();
9388 }
9389 } catch (IOException e) {
9390 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009391 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009392 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009393 }
9394 }
9395 }
9396
Marco Nelissen18cb2872011-11-15 11:19:53 -08009397 /**
9398 * There are three ways to call this:
9399 * - no provider specified: dump all the providers
9400 * - a flattened component name that matched an existing provider was specified as the
9401 * first arg: dump that one provider
9402 * - the first arg isn't the flattened component name of an existing provider:
9403 * dump all providers whose component contains the first arg as a substring
9404 */
9405 protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
9406 int opti, boolean dumpAll) {
9407 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
9408
9409 if ("all".equals(name)) {
9410 synchronized (this) {
9411 for (ContentProviderRecord r1 : mProvidersByClass.values()) {
9412 providers.add(r1);
9413 }
9414 }
9415 } else {
9416 ComponentName componentName = name != null
9417 ? ComponentName.unflattenFromString(name) : null;
9418 int objectId = 0;
9419 if (componentName == null) {
9420 // Not a '/' separated full component name; maybe an object ID?
9421 try {
9422 objectId = Integer.parseInt(name, 16);
9423 name = null;
9424 componentName = null;
9425 } catch (RuntimeException e) {
9426 }
9427 }
9428
9429 synchronized (this) {
9430 for (ContentProviderRecord r1 : mProvidersByClass.values()) {
9431 if (componentName != null) {
9432 if (r1.name.equals(componentName)) {
9433 providers.add(r1);
9434 }
9435 } else if (name != null) {
9436 if (r1.name.flattenToString().contains(name)) {
9437 providers.add(r1);
9438 }
9439 } else if (System.identityHashCode(r1) == objectId) {
9440 providers.add(r1);
9441 }
9442 }
9443 }
9444 }
9445
9446 if (providers.size() <= 0) {
9447 return false;
9448 }
9449
9450 boolean needSep = false;
9451 for (int i=0; i<providers.size(); i++) {
9452 if (needSep) {
9453 pw.println();
9454 }
9455 needSep = true;
9456 dumpProvider("", fd, pw, providers.get(i), args, dumpAll);
9457 }
9458 return true;
9459 }
9460
9461 /**
9462 * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider if
9463 * there is a thread associated with the provider.
9464 */
9465 private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
9466 final ContentProviderRecord r, String[] args, boolean dumpAll) {
9467 String innerPrefix = prefix + " ";
9468 synchronized (this) {
9469 pw.print(prefix); pw.print("PROVIDER ");
9470 pw.print(r);
9471 pw.print(" pid=");
9472 if (r.proc != null) pw.println(r.proc.pid);
9473 else pw.println("(not running)");
9474 if (dumpAll) {
9475 r.dump(pw, innerPrefix);
9476 }
9477 }
9478 if (r.proc != null && r.proc.thread != null) {
9479 pw.println(" Client:");
9480 pw.flush();
9481 try {
9482 TransferPipe tp = new TransferPipe();
9483 try {
9484 r.proc.thread.dumpProvider(
9485 tp.getWriteFd().getFileDescriptor(), r.provider.asBinder(), args);
9486 tp.setBufferPrefix(" ");
9487 // Short timeout, since blocking here can
9488 // deadlock with the application.
9489 tp.go(fd, 2000);
9490 } finally {
9491 tp.kill();
9492 }
9493 } catch (IOException ex) {
9494 pw.println(" Failure while dumping the provider: " + ex);
9495 } catch (RemoteException ex) {
9496 pw.println(" Got a RemoteException while dumping the service");
9497 }
9498 }
9499 }
9500
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009501 static class ItemMatcher {
9502 ArrayList<ComponentName> components;
9503 ArrayList<String> strings;
9504 ArrayList<Integer> objects;
9505 boolean all;
9506
9507 ItemMatcher() {
9508 all = true;
9509 }
9510
9511 void build(String name) {
9512 ComponentName componentName = ComponentName.unflattenFromString(name);
9513 if (componentName != null) {
9514 if (components == null) {
9515 components = new ArrayList<ComponentName>();
9516 }
9517 components.add(componentName);
9518 all = false;
9519 } else {
9520 int objectId = 0;
9521 // Not a '/' separated full component name; maybe an object ID?
9522 try {
9523 objectId = Integer.parseInt(name, 16);
9524 if (objects == null) {
9525 objects = new ArrayList<Integer>();
9526 }
9527 objects.add(objectId);
9528 all = false;
9529 } catch (RuntimeException e) {
9530 // Not an integer; just do string match.
9531 if (strings == null) {
9532 strings = new ArrayList<String>();
9533 }
9534 strings.add(name);
9535 all = false;
9536 }
9537 }
9538 }
9539
9540 int build(String[] args, int opti) {
9541 for (; opti<args.length; opti++) {
9542 String name = args[opti];
9543 if ("--".equals(name)) {
9544 return opti+1;
9545 }
9546 build(name);
9547 }
9548 return opti;
9549 }
9550
9551 boolean match(Object object, ComponentName comp) {
9552 if (all) {
9553 return true;
9554 }
9555 if (components != null) {
9556 for (int i=0; i<components.size(); i++) {
9557 if (components.get(i).equals(comp)) {
9558 return true;
9559 }
9560 }
9561 }
9562 if (objects != null) {
9563 for (int i=0; i<objects.size(); i++) {
9564 if (System.identityHashCode(object) == objects.get(i)) {
9565 return true;
9566 }
9567 }
9568 }
9569 if (strings != null) {
9570 String flat = comp.flattenToString();
9571 for (int i=0; i<strings.size(); i++) {
9572 if (flat.contains(strings.get(i))) {
9573 return true;
9574 }
9575 }
9576 }
9577 return false;
9578 }
9579 }
9580
Dianne Hackborn625ac272010-09-17 18:29:22 -07009581 /**
9582 * There are three things that cmd can be:
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009583 * - a flattened component name that matches an existing activity
Dianne Hackborn625ac272010-09-17 18:29:22 -07009584 * - the cmd arg isn't the flattened component name of an existing activity:
9585 * dump all activity whose component contains the cmd as a substring
9586 * - A hex number of the ActivityRecord object instance.
9587 */
9588 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
9589 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07009590 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009591
9592 if ("all".equals(name)) {
9593 synchronized (this) {
9594 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07009595 activities.add(r1);
9596 }
9597 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07009598 } else if ("top".equals(name)) {
9599 synchronized (this) {
9600 final int N = mMainStack.mHistory.size();
9601 if (N > 0) {
9602 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
9603 }
9604 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009605 } else {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009606 ItemMatcher matcher = new ItemMatcher();
9607 matcher.build(name);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009608
9609 synchronized (this) {
9610 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009611 if (matcher.match(r1, r1.intent.getComponent())) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009612 activities.add(r1);
9613 }
9614 }
9615 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07009616 }
9617
9618 if (activities.size() <= 0) {
9619 return false;
9620 }
9621
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009622 String[] newArgs = new String[args.length - opti];
9623 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
9624
Dianne Hackborn30d71892010-12-11 10:37:55 -08009625 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009626 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08009627 for (int i=activities.size()-1; i>=0; i--) {
9628 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009629 if (needSep) {
9630 pw.println();
9631 }
9632 needSep = true;
9633 synchronized (this) {
9634 if (lastTask != r.task) {
9635 lastTask = r.task;
9636 pw.print("TASK "); pw.print(lastTask.affinity);
9637 pw.print(" id="); pw.println(lastTask.taskId);
9638 if (dumpAll) {
9639 lastTask.dump(pw, " ");
9640 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08009641 }
9642 }
9643 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07009644 }
9645 return true;
9646 }
9647
9648 /**
9649 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
9650 * there is a thread associated with the activity.
9651 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08009652 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009653 final ActivityRecord r, String[] args, boolean dumpAll) {
9654 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08009655 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009656 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
9657 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
9658 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08009659 if (r.app != null) pw.println(r.app.pid);
9660 else pw.println("(not running)");
9661 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009662 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07009663 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07009664 }
9665 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009666 // flush anything that is already in the PrintWriter since the thread is going
9667 // to write to the file descriptor directly
9668 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07009669 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009670 TransferPipe tp = new TransferPipe();
9671 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08009672 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
9673 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009674 tp.go(fd);
9675 } finally {
9676 tp.kill();
9677 }
9678 } catch (IOException e) {
9679 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07009680 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009681 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07009682 }
9683 }
9684 }
9685
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009686 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009687 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009688 boolean needSep = false;
9689
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009690 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009691 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 if (mRegisteredReceivers.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009693 boolean printed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009694 Iterator it = mRegisteredReceivers.values().iterator();
9695 while (it.hasNext()) {
9696 ReceiverList r = (ReceiverList)it.next();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009697 if (dumpPackage != null && (r.app == null ||
9698 !dumpPackage.equals(r.app.info.packageName))) {
9699 continue;
9700 }
9701 if (!printed) {
9702 pw.println(" Registered Receivers:");
9703 needSep = true;
9704 printed = true;
9705 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009706 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009707 r.dump(pw, " ");
9708 }
9709 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009710
9711 if (mReceiverResolver.dump(pw, needSep ?
9712 "\n Receiver Resolver Table:" : " Receiver Resolver Table:",
9713 " ", dumpPackage, false)) {
9714 needSep = true;
9715 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009716 }
Christopher Tatef46723b2012-01-26 14:19:24 -08009717
9718 for (BroadcastQueue q : mBroadcastQueues) {
9719 needSep = q.dumpLocked(fd, pw, args, opti, dumpAll, dumpPackage, needSep);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009722 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009723
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009724 if (mStickyBroadcasts != null && dumpPackage == null) {
9725 if (needSep) {
9726 pw.println();
9727 }
9728 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009729 pw.println(" Sticky broadcasts:");
9730 StringBuilder sb = new StringBuilder(128);
9731 for (Map.Entry<String, ArrayList<Intent>> ent
9732 : mStickyBroadcasts.entrySet()) {
9733 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009734 if (dumpAll) {
9735 pw.println(":");
9736 ArrayList<Intent> intents = ent.getValue();
9737 final int N = intents.size();
9738 for (int i=0; i<N; i++) {
9739 sb.setLength(0);
9740 sb.append(" Intent: ");
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009741 intents.get(i).toShortString(sb, false, true, false);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009742 pw.println(sb.toString());
9743 Bundle bundle = intents.get(i).getExtras();
9744 if (bundle != null) {
9745 pw.print(" ");
9746 pw.println(bundle.toString());
9747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009749 } else {
9750 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 }
9752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009753 needSep = true;
9754 }
9755
9756 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009757 pw.println();
Christopher Tatef46723b2012-01-26 14:19:24 -08009758 for (BroadcastQueue queue : mBroadcastQueues) {
9759 pw.println(" mBroadcastsScheduled [" + queue.mQueueName + "]="
9760 + queue.mBroadcastsScheduled);
9761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 pw.println(" mHandler:");
9763 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009764 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009766
9767 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 }
9769
Marco Nelissen18cb2872011-11-15 11:19:53 -08009770 /**
9771 * Prints a list of ServiceRecords (dumpsys activity services)
9772 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009773 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009774 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009775 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009776
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009777 ItemMatcher matcher = new ItemMatcher();
9778 matcher.build(args, opti);
9779
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009780 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
9781 if (mServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009782 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009783 long nowReal = SystemClock.elapsedRealtime();
9784 Iterator<ServiceRecord> it = mServices.values().iterator();
9785 needSep = false;
9786 while (it.hasNext()) {
9787 ServiceRecord r = it.next();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009788 if (!matcher.match(r, r.name)) {
9789 continue;
9790 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009791 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9792 continue;
9793 }
9794 if (!printed) {
9795 pw.println(" Active services:");
9796 printed = true;
9797 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009798 if (needSep) {
9799 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009800 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009801 pw.print(" * "); pw.println(r);
9802 if (dumpAll) {
9803 r.dump(pw, " ");
9804 needSep = true;
9805 } else {
9806 pw.print(" app="); pw.println(r.app);
9807 pw.print(" created=");
9808 TimeUtils.formatDuration(r.createTime, nowReal, pw);
9809 pw.print(" started="); pw.print(r.startRequested);
9810 pw.print(" connections="); pw.println(r.connections.size());
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009811 if (r.connections.size() > 0) {
9812 pw.println(" Connections:");
9813 for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
9814 for (int i=0; i<clist.size(); i++) {
9815 ConnectionRecord conn = clist.get(i);
9816 pw.print(" ");
9817 pw.print(conn.binding.intent.intent.getIntent().toShortString(
9818 false, false, false));
9819 pw.print(" -> ");
9820 ProcessRecord proc = conn.binding.client;
9821 pw.println(proc != null ? proc.toShortString() : "null");
9822 }
9823 }
9824 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009825 }
9826 if (dumpClient && r.app != null && r.app.thread != null) {
9827 pw.println(" Client:");
9828 pw.flush();
9829 try {
9830 TransferPipe tp = new TransferPipe();
9831 try {
9832 r.app.thread.dumpService(
9833 tp.getWriteFd().getFileDescriptor(), r, args);
9834 tp.setBufferPrefix(" ");
9835 // Short timeout, since blocking here can
9836 // deadlock with the application.
9837 tp.go(fd, 2000);
9838 } finally {
9839 tp.kill();
9840 }
9841 } catch (IOException e) {
9842 pw.println(" Failure while dumping the service: " + e);
9843 } catch (RemoteException e) {
9844 pw.println(" Got a RemoteException while dumping the service");
9845 }
9846 needSep = true;
9847 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009848 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009849 needSep = printed;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009852 if (mPendingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009853 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009854 for (int i=0; i<mPendingServices.size(); i++) {
9855 ServiceRecord r = mPendingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009856 if (!matcher.match(r, r.name)) {
9857 continue;
9858 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009859 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9860 continue;
9861 }
9862 if (!printed) {
9863 if (needSep) pw.println(" ");
9864 needSep = true;
9865 pw.println(" Pending services:");
9866 printed = true;
9867 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009868 pw.print(" * Pending "); pw.println(r);
9869 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009870 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009871 needSep = true;
9872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009874 if (mRestartingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009875 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009876 for (int i=0; i<mRestartingServices.size(); i++) {
9877 ServiceRecord r = mRestartingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009878 if (!matcher.match(r, r.name)) {
9879 continue;
9880 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009881 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9882 continue;
9883 }
9884 if (!printed) {
9885 if (needSep) pw.println(" ");
9886 needSep = true;
9887 pw.println(" Restarting services:");
9888 printed = true;
9889 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009890 pw.print(" * Restarting "); pw.println(r);
9891 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009893 needSep = true;
9894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009896 if (mStoppingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009897 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009898 for (int i=0; i<mStoppingServices.size(); i++) {
9899 ServiceRecord r = mStoppingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009900 if (!matcher.match(r, r.name)) {
9901 continue;
9902 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009903 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9904 continue;
9905 }
9906 if (!printed) {
9907 if (needSep) pw.println(" ");
9908 needSep = true;
9909 pw.println(" Stopping services:");
9910 printed = true;
9911 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009912 pw.print(" * Stopping "); pw.println(r);
9913 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009915 needSep = true;
9916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009918 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 if (mServiceConnections.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009920 boolean printed = false;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009921 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 = mServiceConnections.values().iterator();
9923 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009924 ArrayList<ConnectionRecord> r = it.next();
9925 for (int i=0; i<r.size(); i++) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009926 ConnectionRecord cr = r.get(i);
9927 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
9928 continue;
9929 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009930 if (dumpPackage != null && (cr.binding.client == null
9931 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
9932 continue;
9933 }
9934 if (!printed) {
9935 if (needSep) pw.println(" ");
9936 needSep = true;
9937 pw.println(" Connection bindings to services:");
9938 printed = true;
9939 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009940 pw.print(" * "); pw.println(cr);
9941 cr.dump(pw, " ");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009944 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009945 }
9946 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009947
9948 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 }
9950
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009951 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009952 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009953 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009954
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009955 ItemMatcher matcher = new ItemMatcher();
9956 matcher.build(args, opti);
9957
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009958 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
9959 if (mProvidersByClass.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009960 boolean printed = false;
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009961 Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009962 = mProvidersByClass.entrySet().iterator();
9963 while (it.hasNext()) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009964 Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009965 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009966 ComponentName comp = e.getKey();
9967 String cls = comp.getClassName();
9968 int end = cls.lastIndexOf('.');
9969 if (end > 0 && end < (cls.length()-2)) {
9970 cls = cls.substring(end+1);
9971 }
9972 if (!matcher.match(r, comp)) {
9973 continue;
9974 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009975 if (dumpPackage != null && !dumpPackage.equals(comp.getPackageName())) {
9976 continue;
9977 }
9978 if (!printed) {
9979 if (needSep) pw.println(" ");
9980 needSep = true;
9981 pw.println(" Published content providers (by class):");
9982 printed = true;
9983 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009984 pw.print(" * "); pw.print(cls); pw.print(" (");
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009985 pw.print(comp.flattenToShortString()); pw.println(")");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009986 if (dumpAll) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009987 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009988 } else {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009989 if (r.proc != null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009990 pw.print(" "); pw.println(r.proc);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009991 } else {
9992 pw.println();
9993 }
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009994 if (r.clients.size() > 0) {
9995 pw.println(" Clients:");
9996 for (ProcessRecord cproc : r.clients) {
9997 pw.print(" - "); pw.println(cproc);
9998 }
9999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010002 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010003
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010004 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010005 if (mProvidersByName.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010006 boolean printed = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010007 Iterator<Map.Entry<String, ContentProviderRecord>> it
10008 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010009 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010010 Map.Entry<String, ContentProviderRecord> e = it.next();
10011 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -070010012 if (!matcher.match(r, r.name)) {
10013 continue;
10014 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010015 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
10016 continue;
10017 }
10018 if (!printed) {
10019 if (needSep) pw.println(" ");
10020 needSep = true;
10021 pw.println(" Authority to provider mappings:");
10022 printed = true;
10023 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010024 pw.print(" "); pw.print(e.getKey()); pw.println(":");
10025 pw.print(" "); pw.println(r);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010026 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010028 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010029
10030 if (mLaunchingProviders.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010031 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010032 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010033 ContentProviderRecord r = mLaunchingProviders.get(i);
10034 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
10035 continue;
10036 }
10037 if (!printed) {
10038 if (needSep) pw.println(" ");
10039 needSep = true;
10040 pw.println(" Launching content providers:");
10041 printed = true;
10042 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010043 pw.print(" Launching #"); pw.print(i); pw.print(": ");
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010044 pw.println(r);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010045 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010046 }
10047
10048 if (mGrantedUriPermissions.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010049 if (needSep) pw.println();
10050 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010051 pw.println("Granted Uri Permissions:");
10052 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10053 int uid = mGrantedUriPermissions.keyAt(i);
10054 HashMap<Uri, UriPermission> perms
10055 = mGrantedUriPermissions.valueAt(i);
10056 pw.print(" * UID "); pw.print(uid);
10057 pw.println(" holds:");
10058 for (UriPermission perm : perms.values()) {
10059 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010060 if (dumpAll) {
10061 perm.dump(pw, " ");
10062 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010063 }
10064 }
10065 needSep = true;
10066 }
10067
10068 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010069 }
10070
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010071 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010072 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010073 boolean needSep = false;
10074
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010075 if (mIntentSenderRecords.size() > 0) {
10076 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010077 Iterator<WeakReference<PendingIntentRecord>> it
10078 = mIntentSenderRecords.values().iterator();
10079 while (it.hasNext()) {
10080 WeakReference<PendingIntentRecord> ref = it.next();
10081 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010082 if (dumpPackage != null && (rec == null
10083 || !dumpPackage.equals(rec.key.packageName))) {
10084 continue;
10085 }
10086 if (!printed) {
10087 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
10088 printed = true;
10089 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010090 needSep = true;
10091 if (rec != null) {
10092 pw.print(" * "); pw.println(rec);
10093 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010095 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010096 } else {
10097 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 }
10099 }
10100 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010101
10102 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010103 }
10104
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010105 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010106 String prefix, String label, boolean complete, boolean brief, boolean client,
10107 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010108 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010109 boolean needNL = false;
10110 final String innerPrefix = prefix + " ";
10111 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010113 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010114 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
10115 continue;
10116 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -070010117 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010118 if (needNL) {
10119 pw.println(" ");
10120 needNL = false;
10121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010122 if (lastTask != r.task) {
10123 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010124 pw.print(prefix);
10125 pw.print(full ? "* " : " ");
10126 pw.println(lastTask);
10127 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010128 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010129 } else if (complete) {
10130 // Complete + brief == give a summary. Isn't that obvious?!?
10131 if (lastTask.intent != null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010132 pw.print(prefix); pw.print(" ");
10133 pw.println(lastTask.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010134 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010136 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010137 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10138 pw.print(" #"); pw.print(i); pw.print(": ");
10139 pw.println(r);
10140 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010141 r.dump(pw, innerPrefix);
10142 } else if (complete) {
10143 // Complete + brief == give a summary. Isn't that obvious?!?
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010144 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010145 if (r.app != null) {
10146 pw.print(innerPrefix); pw.println(r.app);
10147 }
10148 }
10149 if (client && r.app != null && r.app.thread != null) {
10150 // flush anything that is already in the PrintWriter since the thread is going
10151 // to write to the file descriptor directly
10152 pw.flush();
10153 try {
10154 TransferPipe tp = new TransferPipe();
10155 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -080010156 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
10157 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010158 // Short timeout, since blocking here can
10159 // deadlock with the application.
10160 tp.go(fd, 2000);
10161 } finally {
10162 tp.kill();
10163 }
10164 } catch (IOException e) {
10165 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
10166 } catch (RemoteException e) {
10167 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
10168 }
10169 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 }
10172 }
10173
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010174 private static String buildOomTag(String prefix, String space, int val, int base) {
10175 if (val == base) {
10176 if (space == null) return prefix;
10177 return prefix + " ";
10178 }
10179 return prefix + "+" + Integer.toString(val-base);
10180 }
10181
10182 private static final int dumpProcessList(PrintWriter pw,
10183 ActivityManagerService service, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010184 String prefix, String normalLabel, String persistentLabel,
10185 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010187 final int N = list.size()-1;
10188 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010190 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
10191 continue;
10192 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070010193 pw.println(String.format("%s%s #%2d: %s",
10194 prefix, (r.persistent ? persistentLabel : normalLabel),
10195 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 if (r.persistent) {
10197 numPers++;
10198 }
10199 }
10200 return numPers;
10201 }
10202
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010203 private static final boolean dumpProcessOomList(PrintWriter pw,
Dianne Hackborn905577f2011-09-07 18:31:28 -070010204 ActivityManagerService service, List<ProcessRecord> origList,
Dianne Hackborn287952c2010-09-22 22:34:31 -070010205 String prefix, String normalLabel, String persistentLabel,
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010206 boolean inclDetails, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010207
Dianne Hackborn905577f2011-09-07 18:31:28 -070010208 ArrayList<Pair<ProcessRecord, Integer>> list
10209 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
10210 for (int i=0; i<origList.size(); i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010211 ProcessRecord r = origList.get(i);
10212 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
10213 continue;
10214 }
Dianne Hackborn905577f2011-09-07 18:31:28 -070010215 list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
10216 }
10217
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010218 if (list.size() <= 0) {
10219 return false;
10220 }
10221
Dianne Hackborn905577f2011-09-07 18:31:28 -070010222 Comparator<Pair<ProcessRecord, Integer>> comparator
10223 = new Comparator<Pair<ProcessRecord, Integer>>() {
10224 @Override
10225 public int compare(Pair<ProcessRecord, Integer> object1,
10226 Pair<ProcessRecord, Integer> object2) {
10227 if (object1.first.setAdj != object2.first.setAdj) {
10228 return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
10229 }
10230 if (object1.second.intValue() != object2.second.intValue()) {
10231 return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
10232 }
10233 return 0;
10234 }
10235 };
10236
10237 Collections.sort(list, comparator);
10238
Dianne Hackborn287952c2010-09-22 22:34:31 -070010239 final long curRealtime = SystemClock.elapsedRealtime();
10240 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
10241 final long curUptime = SystemClock.uptimeMillis();
10242 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
10243
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010244 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070010245 ProcessRecord r = list.get(i).first;
Dianne Hackborn287952c2010-09-22 22:34:31 -070010246 String oomAdj;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010247 if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070010248 oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010249 } else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
10250 oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -070010251 } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
10252 oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010253 } else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
10254 oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010255 } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
10256 oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010257 } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010258 oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010259 } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
10260 oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
10261 } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
10262 oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
10263 } else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
10264 oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
10265 } else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
10266 oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070010267 } else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
10268 oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -070010269 } else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
10270 oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010271 } else {
10272 oomAdj = Integer.toString(r.setAdj);
10273 }
10274 String schedGroup;
10275 switch (r.setSchedGroup) {
10276 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10277 schedGroup = "B";
10278 break;
10279 case Process.THREAD_GROUP_DEFAULT:
10280 schedGroup = "F";
10281 break;
10282 default:
10283 schedGroup = Integer.toString(r.setSchedGroup);
10284 break;
10285 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010286 String foreground;
10287 if (r.foregroundActivities) {
10288 foreground = "A";
10289 } else if (r.foregroundServices) {
10290 foreground = "S";
10291 } else {
10292 foreground = " ";
10293 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010294 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -070010295 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010296 (origList.size()-1)-list.get(i).second, oomAdj, schedGroup,
10297 foreground, r.trimMemoryLevel, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -070010298 if (r.adjSource != null || r.adjTarget != null) {
10299 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010300 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070010301 if (r.adjTarget instanceof ComponentName) {
10302 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10303 } else if (r.adjTarget != null) {
10304 pw.print(r.adjTarget.toString());
10305 } else {
10306 pw.print("{null}");
10307 }
10308 pw.print("<=");
10309 if (r.adjSource instanceof ProcessRecord) {
10310 pw.print("Proc{");
10311 pw.print(((ProcessRecord)r.adjSource).toShortString());
10312 pw.println("}");
10313 } else if (r.adjSource != null) {
10314 pw.println(r.adjSource.toString());
10315 } else {
10316 pw.println("{null}");
10317 }
10318 }
10319 if (inclDetails) {
10320 pw.print(prefix);
10321 pw.print(" ");
10322 pw.print("oom: max="); pw.print(r.maxAdj);
10323 pw.print(" hidden="); pw.print(r.hiddenAdj);
10324 pw.print(" curRaw="); pw.print(r.curRawAdj);
10325 pw.print(" setRaw="); pw.print(r.setRawAdj);
10326 pw.print(" cur="); pw.print(r.curAdj);
10327 pw.print(" set="); pw.println(r.setAdj);
10328 pw.print(prefix);
10329 pw.print(" ");
10330 pw.print("keeping="); pw.print(r.keeping);
10331 pw.print(" hidden="); pw.print(r.hidden);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010332 pw.print(" empty="); pw.print(r.empty);
10333 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010334
10335 if (!r.keeping) {
10336 if (r.lastWakeTime != 0) {
10337 long wtime;
10338 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
10339 synchronized (stats) {
10340 wtime = stats.getProcessWakeTime(r.info.uid,
10341 r.pid, curRealtime);
10342 }
10343 long timeUsed = wtime - r.lastWakeTime;
10344 pw.print(prefix);
10345 pw.print(" ");
10346 pw.print("keep awake over ");
10347 TimeUtils.formatDuration(realtimeSince, pw);
10348 pw.print(" used ");
10349 TimeUtils.formatDuration(timeUsed, pw);
10350 pw.print(" (");
10351 pw.print((timeUsed*100)/realtimeSince);
10352 pw.println("%)");
10353 }
10354 if (r.lastCpuTime != 0) {
10355 long timeUsed = r.curCpuTime - r.lastCpuTime;
10356 pw.print(prefix);
10357 pw.print(" ");
10358 pw.print("run cpu over ");
10359 TimeUtils.formatDuration(uptimeSince, pw);
10360 pw.print(" used ");
10361 TimeUtils.formatDuration(timeUsed, pw);
10362 pw.print(" (");
10363 pw.print((timeUsed*100)/uptimeSince);
10364 pw.println("%)");
10365 }
10366 }
10367 }
10368 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010369 return true;
Dianne Hackborn287952c2010-09-22 22:34:31 -070010370 }
10371
Dianne Hackbornb437e092011-08-05 17:50:29 -070010372 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010373 ArrayList<ProcessRecord> procs;
10374 synchronized (this) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010375 if (args != null && args.length > start
10376 && args[start].charAt(0) != '-') {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010377 procs = new ArrayList<ProcessRecord>();
10378 int pid = -1;
10379 try {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010380 pid = Integer.parseInt(args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010381 } catch (NumberFormatException e) {
10382
10383 }
10384 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10385 ProcessRecord proc = mLruProcesses.get(i);
10386 if (proc.pid == pid) {
10387 procs.add(proc);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010388 } else if (proc.processName.equals(args[start])) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010389 procs.add(proc);
10390 }
10391 }
10392 if (procs.size() <= 0) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010393 pw.println("No process found for: " + args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010394 return null;
10395 }
10396 } else {
10397 procs = new ArrayList<ProcessRecord>(mLruProcesses);
10398 }
10399 }
10400 return procs;
10401 }
10402
10403 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
10404 PrintWriter pw, String[] args) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010405 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010406 if (procs == null) {
10407 return;
10408 }
10409
10410 long uptime = SystemClock.uptimeMillis();
10411 long realtime = SystemClock.elapsedRealtime();
10412 pw.println("Applications Graphics Acceleration Info:");
10413 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10414
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010415 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
10416 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -070010417 if (r.thread != null) {
10418 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
10419 pw.flush();
10420 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010421 TransferPipe tp = new TransferPipe();
10422 try {
10423 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
10424 tp.go(fd);
10425 } finally {
10426 tp.kill();
10427 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010428 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010429 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010430 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -070010431 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010432 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -070010433 pw.flush();
10434 }
10435 }
10436 }
Chet Haase9c1e23b2011-03-24 10:51:31 -070010437 }
10438
Jeff Brown6754ba22011-12-14 20:20:01 -080010439 final void dumpDbInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
10440 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
10441 if (procs == null) {
10442 return;
10443 }
10444
10445 pw.println("Applications Database Info:");
10446
10447 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
10448 ProcessRecord r = procs.get(i);
10449 if (r.thread != null) {
10450 pw.println("\n** Database info for pid " + r.pid + " [" + r.processName + "] **");
10451 pw.flush();
10452 try {
10453 TransferPipe tp = new TransferPipe();
10454 try {
10455 r.thread.dumpDbInfo(tp.getWriteFd().getFileDescriptor(), args);
10456 tp.go(fd);
10457 } finally {
10458 tp.kill();
10459 }
10460 } catch (IOException e) {
10461 pw.println("Failure while dumping the app: " + r);
10462 pw.flush();
10463 } catch (RemoteException e) {
10464 pw.println("Got a RemoteException while dumping the app " + r);
10465 pw.flush();
10466 }
10467 }
10468 }
10469 }
10470
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010471 final static class MemItem {
10472 final String label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010473 final String shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010474 final long pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010475 final int id;
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010476 ArrayList<MemItem> subitems;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010477
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010478 public MemItem(String _label, String _shortLabel, long _pss, int _id) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010479 label = _label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010480 shortLabel = _shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010481 pss = _pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010482 id = _id;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010483 }
10484 }
10485
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010486 static final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
Dianne Hackbornb437e092011-08-05 17:50:29 -070010487 boolean sort) {
10488 if (sort) {
10489 Collections.sort(items, new Comparator<MemItem>() {
10490 @Override
10491 public int compare(MemItem lhs, MemItem rhs) {
10492 if (lhs.pss < rhs.pss) {
10493 return 1;
10494 } else if (lhs.pss > rhs.pss) {
10495 return -1;
10496 }
10497 return 0;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010498 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010499 });
10500 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010501
10502 for (int i=0; i<items.size(); i++) {
10503 MemItem mi = items.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010504 pw.print(prefix); pw.printf("%7d kB: ", mi.pss); pw.println(mi.label);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010505 if (mi.subitems != null) {
10506 dumpMemItems(pw, prefix + " ", mi.subitems, true);
10507 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010508 }
10509 }
10510
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010511 // These are in KB.
10512 static final long[] DUMP_MEM_BUCKETS = new long[] {
10513 5*1024, 7*1024, 10*1024, 15*1024, 20*1024, 30*1024, 40*1024, 80*1024,
10514 120*1024, 160*1024, 200*1024,
10515 250*1024, 300*1024, 350*1024, 400*1024, 500*1024, 600*1024, 800*1024,
10516 1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
10517 };
10518
Dianne Hackborn672342c2011-11-29 11:29:02 -080010519 static final void appendMemBucket(StringBuilder out, long memKB, String label,
10520 boolean stackLike) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010521 int start = label.lastIndexOf('.');
10522 if (start >= 0) start++;
10523 else start = 0;
10524 int end = label.length();
10525 for (int i=0; i<DUMP_MEM_BUCKETS.length; i++) {
10526 if (DUMP_MEM_BUCKETS[i] >= memKB) {
10527 long bucket = DUMP_MEM_BUCKETS[i]/1024;
10528 out.append(bucket);
Dianne Hackborn672342c2011-11-29 11:29:02 -080010529 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010530 out.append(label, start, end);
10531 return;
10532 }
10533 }
10534 out.append(memKB/1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -080010535 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010536 out.append(label, start, end);
10537 }
10538
10539 static final int[] DUMP_MEM_OOM_ADJ = new int[] {
10540 ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
10541 ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
10542 ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
10543 ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
10544 };
10545 static final String[] DUMP_MEM_OOM_LABEL = new String[] {
10546 "System", "Persistent", "Foreground",
10547 "Visible", "Perceptible", "Heavy Weight",
10548 "Backup", "A Services", "Home", "Previous",
10549 "B Services", "Background"
10550 };
10551
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010552 final void dumpApplicationMemoryUsage(FileDescriptor fd,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010553 PrintWriter pw, String prefix, String[] args, boolean brief,
Dianne Hackborn672342c2011-11-29 11:29:02 -080010554 PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010555 boolean dumpAll = false;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010556 boolean oomOnly = false;
Dianne Hackbornb437e092011-08-05 17:50:29 -070010557
10558 int opti = 0;
10559 while (opti < args.length) {
10560 String opt = args[opti];
10561 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10562 break;
10563 }
10564 opti++;
10565 if ("-a".equals(opt)) {
10566 dumpAll = true;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010567 } else if ("--oom".equals(opt)) {
10568 oomOnly = true;
Dianne Hackbornb437e092011-08-05 17:50:29 -070010569 } else if ("-h".equals(opt)) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010570 pw.println("meminfo dump options: [-a] [--oom] [process]");
Dianne Hackbornb437e092011-08-05 17:50:29 -070010571 pw.println(" -a: include all available information for each process.");
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010572 pw.println(" --oom: only show processes organized by oom adj.");
Dianne Hackbornb437e092011-08-05 17:50:29 -070010573 pw.println("If [process] is specified it can be the name or ");
10574 pw.println("pid of a specific process to dump.");
10575 return;
10576 } else {
10577 pw.println("Unknown argument: " + opt + "; use -h for help");
10578 }
10579 }
10580
10581 ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010582 if (procs == null) {
10583 return;
10584 }
10585
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010586 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 long uptime = SystemClock.uptimeMillis();
10588 long realtime = SystemClock.elapsedRealtime();
Dianne Hackbornb437e092011-08-05 17:50:29 -070010589
10590 if (procs.size() == 1 || isCheckinRequest) {
10591 dumpAll = true;
10592 }
10593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 if (isCheckinRequest) {
10595 // short checkin version
10596 pw.println(uptime + "," + realtime);
10597 pw.flush();
10598 } else {
10599 pw.println("Applications Memory Usage (kB):");
10600 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10601 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010602
Dianne Hackbornb437e092011-08-05 17:50:29 -070010603 String[] innerArgs = new String[args.length-opti];
10604 System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
10605
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010606 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
10607 long nativePss=0, dalvikPss=0, otherPss=0;
10608 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
10609
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010610 long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
10611 ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
10612 new ArrayList[DUMP_MEM_OOM_LABEL.length];
Dianne Hackbornb437e092011-08-05 17:50:29 -070010613
10614 long totalPss = 0;
10615
Dianne Hackborne17aeb32011-04-07 15:11:57 -070010616 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
10617 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010618 if (r.thread != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010619 if (!isCheckinRequest && dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10621 pw.flush();
10622 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010623 Debug.MemoryInfo mi = null;
Dianne Hackbornb437e092011-08-05 17:50:29 -070010624 if (dumpAll) {
10625 try {
10626 mi = r.thread.dumpMemInfo(fd, isCheckinRequest, dumpAll, innerArgs);
10627 } catch (RemoteException e) {
10628 if (!isCheckinRequest) {
10629 pw.println("Got RemoteException!");
10630 pw.flush();
10631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010633 } else {
10634 mi = new Debug.MemoryInfo();
10635 Debug.getMemoryInfo(r.pid, mi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010637
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010638 if (!isCheckinRequest && mi != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010639 long myTotalPss = mi.getTotalPss();
10640 totalPss += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010641 MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010642 r.processName, myTotalPss, 0);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010643 procMems.add(pssItem);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010644
10645 nativePss += mi.nativePss;
10646 dalvikPss += mi.dalvikPss;
10647 otherPss += mi.otherPss;
10648 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
10649 long mem = mi.getOtherPss(j);
10650 miscPss[j] += mem;
10651 otherPss -= mem;
10652 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010653
10654 for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010655 if (r.setAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
10656 || oomIndex == (oomPss.length-1)) {
Dianne Hackbornb437e092011-08-05 17:50:29 -070010657 oomPss[oomIndex] += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010658 if (oomProcs[oomIndex] == null) {
10659 oomProcs[oomIndex] = new ArrayList<MemItem>();
10660 }
10661 oomProcs[oomIndex].add(pssItem);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010662 break;
10663 }
10664 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 }
10667 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010668
10669 if (!isCheckinRequest && procs.size() > 1) {
10670 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
10671
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010672 catMems.add(new MemItem("Native", "Native", nativePss, -1));
10673 catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, -2));
10674 catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010675 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010676 String label = Debug.MemoryInfo.getOtherLabel(j);
10677 catMems.add(new MemItem(label, label, miscPss[j], j));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010678 }
10679
Dianne Hackbornb437e092011-08-05 17:50:29 -070010680 ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
10681 for (int j=0; j<oomPss.length; j++) {
10682 if (oomPss[j] != 0) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010683 String label = DUMP_MEM_OOM_LABEL[j];
10684 MemItem item = new MemItem(label, label, oomPss[j],
10685 DUMP_MEM_OOM_ADJ[j]);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010686 item.subitems = oomProcs[j];
10687 oomMems.add(item);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010688 }
10689 }
10690
Dianne Hackborn672342c2011-11-29 11:29:02 -080010691 if (outTag != null || outStack != null) {
10692 if (outTag != null) {
10693 appendMemBucket(outTag, totalPss, "total", false);
10694 }
10695 if (outStack != null) {
10696 appendMemBucket(outStack, totalPss, "total", true);
10697 }
10698 boolean firstLine = true;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010699 for (int i=0; i<oomMems.size(); i++) {
10700 MemItem miCat = oomMems.get(i);
10701 if (miCat.subitems == null || miCat.subitems.size() < 1) {
10702 continue;
10703 }
10704 if (miCat.id < ProcessList.SERVICE_ADJ
10705 || miCat.id == ProcessList.HOME_APP_ADJ
10706 || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010707 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10708 outTag.append(" / ");
10709 }
10710 if (outStack != null) {
10711 if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10712 if (firstLine) {
10713 outStack.append(":");
10714 firstLine = false;
10715 }
10716 outStack.append("\n\t at ");
10717 } else {
10718 outStack.append("$");
10719 }
10720 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010721 for (int j=0; j<miCat.subitems.size(); j++) {
10722 MemItem mi = miCat.subitems.get(j);
10723 if (j > 0) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010724 if (outTag != null) {
10725 outTag.append(" ");
10726 }
10727 if (outStack != null) {
10728 outStack.append("$");
10729 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010730 }
Dianne Hackborn672342c2011-11-29 11:29:02 -080010731 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10732 appendMemBucket(outTag, mi.pss, mi.shortLabel, false);
10733 }
10734 if (outStack != null) {
10735 appendMemBucket(outStack, mi.pss, mi.shortLabel, true);
10736 }
10737 }
10738 if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10739 outStack.append("(");
10740 for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
10741 if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
10742 outStack.append(DUMP_MEM_OOM_LABEL[k]);
10743 outStack.append(":");
10744 outStack.append(DUMP_MEM_OOM_ADJ[k]);
10745 }
10746 }
10747 outStack.append(")");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010748 }
10749 }
10750 }
10751 }
10752
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010753 if (!brief && !oomOnly) {
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010754 pw.println();
10755 pw.println("Total PSS by process:");
10756 dumpMemItems(pw, " ", procMems, true);
10757 pw.println();
10758 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010759 pw.println("Total PSS by OOM adjustment:");
10760 dumpMemItems(pw, " ", oomMems, false);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010761 if (!oomOnly) {
10762 PrintWriter out = categoryPw != null ? categoryPw : pw;
10763 out.println();
10764 out.println("Total PSS by category:");
10765 dumpMemItems(out, " ", catMems, true);
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010766 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010767 pw.println();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010768 pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 }
10771
10772 /**
10773 * Searches array of arguments for the specified string
10774 * @param args array of argument strings
10775 * @param value value to search for
10776 * @return true if the value is contained in the array
10777 */
10778 private static boolean scanArgs(String[] args, String value) {
10779 if (args != null) {
10780 for (String arg : args) {
10781 if (value.equals(arg)) {
10782 return true;
10783 }
10784 }
10785 }
10786 return false;
10787 }
10788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 private final void killServicesLocked(ProcessRecord app,
10790 boolean allowRestart) {
10791 // Report disconnected services.
10792 if (false) {
10793 // XXX we are letting the client link to the service for
10794 // death notifications.
10795 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010796 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010798 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010800 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 = r.connections.values().iterator();
10802 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010803 ArrayList<ConnectionRecord> cl = jt.next();
10804 for (int i=0; i<cl.size(); i++) {
10805 ConnectionRecord c = cl.get(i);
10806 if (c.binding.client != app) {
10807 try {
10808 //c.conn.connected(r.className, null);
10809 } catch (Exception e) {
10810 // todo: this should be asynchronous!
10811 Slog.w(TAG, "Exception thrown disconnected servce "
10812 + r.shortName
10813 + " from app " + app.processName, e);
10814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010815 }
10816 }
10817 }
10818 }
10819 }
10820 }
10821 }
10822
10823 // Clean up any connections this application has to other services.
10824 if (app.connections.size() > 0) {
10825 Iterator<ConnectionRecord> it = app.connections.iterator();
10826 while (it.hasNext()) {
10827 ConnectionRecord r = it.next();
10828 removeConnectionLocked(r, app, null);
10829 }
10830 }
10831 app.connections.clear();
10832
10833 if (app.services.size() != 0) {
10834 // Any services running in the application need to be placed
10835 // back in the pending list.
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 sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 synchronized (sr.stats.getBatteryStats()) {
10840 sr.stats.stopLaunchedLocked();
10841 }
10842 sr.app = null;
10843 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010844 if (mStoppingServices.remove(sr)) {
10845 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
10846 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010847
10848 boolean hasClients = sr.bindings.size() > 0;
10849 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010850 Iterator<IntentBindRecord> bindings
10851 = sr.bindings.values().iterator();
10852 while (bindings.hasNext()) {
10853 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010854 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 + ": shouldUnbind=" + b.hasBound);
10856 b.binder = null;
10857 b.requested = b.received = b.hasBound = false;
10858 }
10859 }
10860
Dianne Hackborn070783f2010-12-29 16:46:28 -080010861 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
10862 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010863 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010865 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010866 sr.crashCount, sr.shortName, app.pid);
10867 bringDownServiceLocked(sr, true);
10868 } else if (!allowRestart) {
10869 bringDownServiceLocked(sr, true);
10870 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010871 boolean canceled = scheduleServiceRestartLocked(sr, true);
10872
10873 // Should the service remain running? Note that in the
10874 // extreme case of so many attempts to deliver a command
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010875 // that it failed we also will stop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010876 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10877 if (sr.pendingStarts.size() == 0) {
10878 sr.startRequested = false;
10879 if (!hasClients) {
10880 // Whoops, no reason to restart!
10881 bringDownServiceLocked(sr, true);
10882 }
10883 }
10884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010885 }
10886 }
10887
10888 if (!allowRestart) {
10889 app.services.clear();
10890 }
10891 }
10892
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010893 // Make sure we have no more records on the stopping list.
10894 int i = mStoppingServices.size();
10895 while (i > 0) {
10896 i--;
10897 ServiceRecord sr = mStoppingServices.get(i);
10898 if (sr.app == app) {
10899 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010900 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010901 }
10902 }
10903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 app.executingServices.clear();
10905 }
10906
10907 private final void removeDyingProviderLocked(ProcessRecord proc,
10908 ContentProviderRecord cpr) {
10909 synchronized (cpr) {
10910 cpr.launchingApp = null;
10911 cpr.notifyAll();
10912 }
10913
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010914 mProvidersByClass.remove(cpr.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 String names[] = cpr.info.authority.split(";");
10916 for (int j = 0; j < names.length; j++) {
10917 mProvidersByName.remove(names[j]);
10918 }
10919
10920 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10921 while (cit.hasNext()) {
10922 ProcessRecord capp = cit.next();
10923 if (!capp.persistent && capp.thread != null
10924 && capp.pid != 0
10925 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010926 Slog.i(TAG, "Kill " + capp.processName
10927 + " (pid " + capp.pid + "): provider " + cpr.info.name
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010928 + " in dying process " + (proc != null ? proc.processName : "??"));
Dianne Hackborn8633e682010-04-22 16:03:41 -070010929 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010930 capp.processName, capp.setAdj, "dying provider "
10931 + cpr.name.toShortString());
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010932 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 }
10934 }
10935
10936 mLaunchingProviders.remove(cpr);
10937 }
10938
10939 /**
10940 * Main code for cleaning up a process when it has gone away. This is
10941 * called both as a result of the process dying, or directly when stopping
10942 * a process when running in single process mode.
10943 */
10944 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010945 boolean restarting, boolean allowRestart, int index) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010947 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 }
10949
Dianne Hackborn36124872009-10-08 16:22:03 -070010950 mProcessesToGc.remove(app);
10951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 // Dismiss any open dialogs.
10953 if (app.crashDialog != null) {
10954 app.crashDialog.dismiss();
10955 app.crashDialog = null;
10956 }
10957 if (app.anrDialog != null) {
10958 app.anrDialog.dismiss();
10959 app.anrDialog = null;
10960 }
10961 if (app.waitDialog != null) {
10962 app.waitDialog.dismiss();
10963 app.waitDialog = null;
10964 }
10965
10966 app.crashing = false;
10967 app.notResponding = false;
10968
10969 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -070010970 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010971 app.thread = null;
10972 app.forcingToForeground = null;
10973 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010974 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070010975 app.hasShownUi = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010976 app.hasAboveClient = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010978 killServicesLocked(app, allowRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979
10980 boolean restart = false;
10981
10982 int NL = mLaunchingProviders.size();
10983
10984 // Remove published content providers.
10985 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010986 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010988 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 cpr.provider = null;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010990 cpr.proc = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010991
10992 // See if someone is waiting for this provider... in which
10993 // case we don't remove it, but just let it restart.
10994 int i = 0;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010995 if (!app.bad && allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 for (; i<NL; i++) {
10997 if (mLaunchingProviders.get(i) == cpr) {
10998 restart = true;
10999 break;
11000 }
11001 }
11002 } else {
11003 i = NL;
11004 }
11005
11006 if (i >= NL) {
11007 removeDyingProviderLocked(app, cpr);
11008 NL = mLaunchingProviders.size();
11009 }
11010 }
11011 app.pubProviders.clear();
11012 }
11013
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011014 // Take care of any launching providers waiting for this process.
11015 if (checkAppInLaunchingProvidersLocked(app, false)) {
11016 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 // Unregister from connected content providers.
11020 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070011021 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 while (it.hasNext()) {
11023 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
11024 cpr.clients.remove(app);
11025 }
11026 app.conProviders.clear();
11027 }
11028
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011029 // At this point there may be remaining entries in mLaunchingProviders
11030 // where we were the only one waiting, so they are no longer of use.
11031 // Look for these and clean up if found.
11032 // XXX Commented out for now. Trying to figure out a way to reproduce
11033 // the actual situation to identify what is actually going on.
11034 if (false) {
11035 for (int i=0; i<NL; i++) {
11036 ContentProviderRecord cpr = (ContentProviderRecord)
11037 mLaunchingProviders.get(i);
11038 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
11039 synchronized (cpr) {
11040 cpr.launchingApp = null;
11041 cpr.notifyAll();
11042 }
11043 }
11044 }
11045 }
11046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 skipCurrentReceiverLocked(app);
11048
11049 // Unregister any receivers.
11050 if (app.receivers.size() > 0) {
11051 Iterator<ReceiverList> it = app.receivers.iterator();
11052 while (it.hasNext()) {
11053 removeReceiverLocked(it.next());
11054 }
11055 app.receivers.clear();
11056 }
11057
Christopher Tate181fafa2009-05-14 11:12:14 -070011058 // If the app is undergoing backup, tell the backup manager about it
11059 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070011061 try {
11062 IBackupManager bm = IBackupManager.Stub.asInterface(
11063 ServiceManager.getService(Context.BACKUP_SERVICE));
11064 bm.agentDisconnected(app.info.packageName);
11065 } catch (RemoteException e) {
11066 // can't happen; backup manager is local
11067 }
11068 }
11069
Jeff Sharkey287bd832011-05-28 19:36:26 -070011070 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070011071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 // If the caller is restarting this app, then leave it in its
11073 // current lists and let the caller take care of it.
11074 if (restarting) {
11075 return;
11076 }
11077
11078 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011079 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 "Removing non-persistent process during cleanup: " + app);
11081 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070011082 if (mHeavyWeightProcess == app) {
11083 mHeavyWeightProcess = null;
11084 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
11085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086 } else if (!app.removed) {
11087 // This app is persistent, so we need to keep its record around.
11088 // If it is not already on the pending app list, add it there
11089 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 if (mPersistentStartingProcesses.indexOf(app) < 0) {
11091 mPersistentStartingProcesses.add(app);
11092 restart = true;
11093 }
11094 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011095 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
11096 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 mProcessesOnHold.remove(app);
11098
The Android Open Source Project4df24232009-03-05 14:34:35 -080011099 if (app == mHomeProcess) {
11100 mHomeProcess = null;
11101 }
Dianne Hackbornf35fe232011-11-01 19:25:20 -070011102 if (app == mPreviousProcess) {
11103 mPreviousProcess = null;
11104 }
11105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 if (restart) {
11107 // We have components that still need to be running in the
11108 // process, so re-launch it.
11109 mProcessNames.put(app.processName, app.info.uid, app);
11110 startProcessLocked(app, "restart", app.processName);
11111 } else if (app.pid > 0 && app.pid != MY_PID) {
11112 // Goodbye!
11113 synchronized (mPidsSelfLocked) {
11114 mPidsSelfLocked.remove(app.pid);
11115 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
11116 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070011117 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 }
11119 }
11120
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011121 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
11122 // Look through the content providers we are waiting to have launched,
11123 // and if any run in this process then either schedule a restart of
11124 // the process or kill the client waiting for it if this process has
11125 // gone bad.
11126 int NL = mLaunchingProviders.size();
11127 boolean restart = false;
11128 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011129 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011130 if (cpr.launchingApp == app) {
11131 if (!alwaysBad && !app.bad) {
11132 restart = true;
11133 } else {
11134 removeDyingProviderLocked(app, cpr);
11135 NL = mLaunchingProviders.size();
11136 }
11137 }
11138 }
11139 return restart;
11140 }
11141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 // =========================================================
11143 // SERVICES
11144 // =========================================================
11145
11146 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11147 ActivityManager.RunningServiceInfo info =
11148 new ActivityManager.RunningServiceInfo();
11149 info.service = r.name;
11150 if (r.app != null) {
11151 info.pid = r.app.pid;
11152 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011153 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 info.process = r.processName;
11155 info.foreground = r.isForeground;
11156 info.activeSince = r.createTime;
11157 info.started = r.startRequested;
11158 info.clientCount = r.connections.size();
11159 info.crashCount = r.crashCount;
11160 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011161 if (r.isForeground) {
11162 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11163 }
11164 if (r.startRequested) {
11165 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11166 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011167 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011168 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11169 }
11170 if (r.app != null && r.app.persistent) {
11171 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11172 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011173
11174 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
11175 for (int i=0; i<connl.size(); i++) {
11176 ConnectionRecord conn = connl.get(i);
11177 if (conn.clientLabel != 0) {
11178 info.clientPackage = conn.binding.client.info.packageName;
11179 info.clientLabel = conn.clientLabel;
11180 return info;
11181 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011182 }
11183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 return info;
11185 }
11186
11187 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11188 int flags) {
11189 synchronized (this) {
11190 ArrayList<ActivityManager.RunningServiceInfo> res
11191 = new ArrayList<ActivityManager.RunningServiceInfo>();
11192
11193 if (mServices.size() > 0) {
11194 Iterator<ServiceRecord> it = mServices.values().iterator();
11195 while (it.hasNext() && res.size() < maxNum) {
11196 res.add(makeRunningServiceInfoLocked(it.next()));
11197 }
11198 }
11199
11200 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11201 ServiceRecord r = mRestartingServices.get(i);
11202 ActivityManager.RunningServiceInfo info =
11203 makeRunningServiceInfoLocked(r);
11204 info.restarting = r.nextRestartTime;
11205 res.add(info);
11206 }
11207
11208 return res;
11209 }
11210 }
11211
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011212 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11213 synchronized (this) {
11214 ServiceRecord r = mServices.get(name);
11215 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011216 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
11217 for (int i=0; i<conn.size(); i++) {
11218 if (conn.get(i).clientIntent != null) {
11219 return conn.get(i).clientIntent;
11220 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011221 }
11222 }
11223 }
11224 }
11225 return null;
11226 }
11227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 private final ServiceRecord findServiceLocked(ComponentName name,
11229 IBinder token) {
11230 ServiceRecord r = mServices.get(name);
11231 return r == token ? r : null;
11232 }
11233
11234 private final class ServiceLookupResult {
11235 final ServiceRecord record;
11236 final String permission;
11237
11238 ServiceLookupResult(ServiceRecord _record, String _permission) {
11239 record = _record;
11240 permission = _permission;
11241 }
11242 };
11243
11244 private ServiceLookupResult findServiceLocked(Intent service,
11245 String resolvedType) {
11246 ServiceRecord r = null;
11247 if (service.getComponent() != null) {
11248 r = mServices.get(service.getComponent());
11249 }
11250 if (r == null) {
11251 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11252 r = mServicesByIntent.get(filter);
11253 }
11254
11255 if (r == null) {
11256 try {
11257 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011258 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 service, resolvedType, 0);
11260 ServiceInfo sInfo =
11261 rInfo != null ? rInfo.serviceInfo : null;
11262 if (sInfo == null) {
11263 return null;
11264 }
11265
11266 ComponentName name = new ComponentName(
11267 sInfo.applicationInfo.packageName, sInfo.name);
11268 r = mServices.get(name);
11269 } catch (RemoteException ex) {
11270 // pm is in same process, this will never happen.
11271 }
11272 }
11273 if (r != null) {
11274 int callingPid = Binder.getCallingPid();
11275 int callingUid = Binder.getCallingUid();
11276 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011277 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011279 if (!r.exported) {
11280 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
11281 + " from pid=" + callingPid
11282 + ", uid=" + callingUid
11283 + " that is not exported from uid " + r.appInfo.uid);
11284 return new ServiceLookupResult(null, "not exported from uid "
11285 + r.appInfo.uid);
11286 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011287 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 + " from pid=" + callingPid
11289 + ", uid=" + callingUid
11290 + " requires " + r.permission);
11291 return new ServiceLookupResult(null, r.permission);
11292 }
11293 return new ServiceLookupResult(r, null);
11294 }
11295 return null;
11296 }
11297
11298 private class ServiceRestarter implements Runnable {
11299 private ServiceRecord mService;
11300
11301 void setService(ServiceRecord service) {
11302 mService = service;
11303 }
11304
11305 public void run() {
11306 synchronized(ActivityManagerService.this) {
11307 performServiceRestartLocked(mService);
11308 }
11309 }
11310 }
11311
11312 private ServiceLookupResult retrieveServiceLocked(Intent service,
11313 String resolvedType, int callingPid, int callingUid) {
11314 ServiceRecord r = null;
11315 if (service.getComponent() != null) {
11316 r = mServices.get(service.getComponent());
11317 }
11318 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11319 r = mServicesByIntent.get(filter);
11320 if (r == null) {
11321 try {
11322 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011323 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011324 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 ServiceInfo sInfo =
11326 rInfo != null ? rInfo.serviceInfo : null;
11327 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011328 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 ": not found");
11330 return null;
11331 }
11332
11333 ComponentName name = new ComponentName(
11334 sInfo.applicationInfo.packageName, sInfo.name);
11335 r = mServices.get(name);
11336 if (r == null) {
11337 filter = new Intent.FilterComparison(service.cloneFilter());
11338 ServiceRestarter res = new ServiceRestarter();
11339 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11340 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11341 synchronized (stats) {
11342 ss = stats.getServiceStatsLocked(
11343 sInfo.applicationInfo.uid, sInfo.packageName,
11344 sInfo.name);
11345 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011346 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 res.setService(r);
11348 mServices.put(name, r);
11349 mServicesByIntent.put(filter, r);
11350
11351 // Make sure this component isn't in the pending list.
11352 int N = mPendingServices.size();
11353 for (int i=0; i<N; i++) {
11354 ServiceRecord pr = mPendingServices.get(i);
11355 if (pr.name.equals(name)) {
11356 mPendingServices.remove(i);
11357 i--;
11358 N--;
11359 }
11360 }
11361 }
11362 } catch (RemoteException ex) {
11363 // pm is in same process, this will never happen.
11364 }
11365 }
11366 if (r != null) {
11367 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011368 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011370 if (!r.exported) {
11371 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
11372 + " from pid=" + callingPid
11373 + ", uid=" + callingUid
11374 + " that is not exported from uid " + r.appInfo.uid);
11375 return new ServiceLookupResult(null, "not exported from uid "
11376 + r.appInfo.uid);
11377 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011378 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011379 + " from pid=" + callingPid
11380 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011381 + " requires " + r.permission);
11382 return new ServiceLookupResult(null, r.permission);
11383 }
11384 return new ServiceLookupResult(r, null);
11385 }
11386 return null;
11387 }
11388
Dianne Hackborn287952c2010-09-22 22:34:31 -070011389 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
11390 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
11391 + why + " of " + r + " in app " + r.app);
11392 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
11393 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 long now = SystemClock.uptimeMillis();
11395 if (r.executeNesting == 0 && r.app != null) {
11396 if (r.app.executingServices.size() == 0) {
11397 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11398 msg.obj = r.app;
11399 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11400 }
11401 r.app.executingServices.add(r);
11402 }
11403 r.executeNesting++;
11404 r.executingStart = now;
11405 }
11406
11407 private final void sendServiceArgsLocked(ServiceRecord r,
11408 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011409 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 if (N == 0) {
11411 return;
11412 }
11413
Dianne Hackborn39792d22010-08-19 18:01:52 -070011414 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011415 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -070011416 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011417 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
11418 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -080011419 if (si.intent == null && N > 1) {
11420 // If somehow we got a dummy null intent in the middle,
11421 // then skip it. DO NOT skip a null intent when it is
11422 // the only one in the list -- this is to support the
11423 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011424 continue;
11425 }
Dianne Hackborn39792d22010-08-19 18:01:52 -070011426 si.deliveredTime = SystemClock.uptimeMillis();
11427 r.deliveredStarts.add(si);
11428 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -080011429 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070011430 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -070011431 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -070011432 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011433 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 if (!oomAdjusted) {
11435 oomAdjusted = true;
11436 updateOomAdjLocked(r.app);
11437 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011438 int flags = 0;
11439 if (si.deliveryCount > 0) {
11440 flags |= Service.START_FLAG_RETRY;
11441 }
11442 if (si.doneExecutingCount > 0) {
11443 flags |= Service.START_FLAG_REDELIVERY;
11444 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011445 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011446 } catch (RemoteException e) {
11447 // Remote process gone... we'll let the normal cleanup take
11448 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011449 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011450 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011452 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 break;
11454 }
11455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 }
11457
11458 private final boolean requestServiceBindingLocked(ServiceRecord r,
11459 IntentBindRecord i, boolean rebind) {
11460 if (r.app == null || r.app.thread == null) {
11461 // If service is not currently running, can't yet bind.
11462 return false;
11463 }
11464 if ((!i.requested || rebind) && i.apps.size() > 0) {
11465 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011466 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11468 if (!rebind) {
11469 i.requested = true;
11470 }
11471 i.hasBound = true;
11472 i.doRebind = false;
11473 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011474 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475 return false;
11476 }
11477 }
11478 return true;
11479 }
11480
11481 private final void requestServiceBindingsLocked(ServiceRecord r) {
11482 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11483 while (bindings.hasNext()) {
11484 IntentBindRecord i = bindings.next();
11485 if (!requestServiceBindingLocked(r, i, false)) {
11486 break;
11487 }
11488 }
11489 }
11490
11491 private final void realStartServiceLocked(ServiceRecord r,
11492 ProcessRecord app) throws RemoteException {
11493 if (app.thread == null) {
11494 throw new RemoteException();
11495 }
11496
11497 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011498 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499
11500 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011501 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011502 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503
11504 boolean created = false;
11505 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011506 mStringBuilder.setLength(0);
Dianne Hackborn90c52de2011-09-23 12:57:44 -070011507 r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011508 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011510 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 synchronized (r.stats.getBatteryStats()) {
11512 r.stats.startLaunchedLocked();
11513 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011514 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011515 app.thread.scheduleCreateService(r, r.serviceInfo,
11516 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011517 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 created = true;
11519 } finally {
11520 if (!created) {
11521 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011522 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011523 }
11524 }
11525
11526 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011527
11528 // If the service is in the started state, and there are no
11529 // pending arguments, then fake up one so its onStartCommand() will
11530 // be called.
11531 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011532 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
11533 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011534 }
11535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 sendServiceArgsLocked(r, true);
11537 }
11538
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011539 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11540 boolean allowCancel) {
11541 boolean canceled = false;
11542
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011543 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011544 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011545 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011546
Dianne Hackborn070783f2010-12-29 16:46:28 -080011547 if ((r.serviceInfo.applicationInfo.flags
11548 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
11549 minDuration /= 4;
11550 }
11551
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011552 // Any delivered but not yet finished starts should be put back
11553 // on the pending list.
11554 final int N = r.deliveredStarts.size();
11555 if (N > 0) {
11556 for (int i=N-1; i>=0; i--) {
11557 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -070011558 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011559 if (si.intent == null) {
11560 // We'll generate this again if needed.
11561 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11562 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11563 r.pendingStarts.add(0, si);
11564 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11565 dur *= 2;
11566 if (minDuration < dur) minDuration = dur;
11567 if (resetTime < dur) resetTime = dur;
11568 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011569 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011570 + r.name);
11571 canceled = true;
11572 }
11573 }
11574 r.deliveredStarts.clear();
11575 }
11576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 r.totalRestartCount++;
11578 if (r.restartDelay == 0) {
11579 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011580 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011581 } else {
11582 // If it has been a "reasonably long time" since the service
11583 // was started, then reset our restart duration back to
11584 // the beginning, so we don't infinitely increase the duration
11585 // on a service that just occasionally gets killed (which is
11586 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011587 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011589 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -080011591 if ((r.serviceInfo.applicationInfo.flags
11592 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
11593 // Services in peristent processes will restart much more
11594 // quickly, since they are pretty important. (Think SystemUI).
11595 r.restartDelay += minDuration/2;
11596 } else {
11597 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
11598 if (r.restartDelay < minDuration) {
11599 r.restartDelay = minDuration;
11600 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 }
11603 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011604
11605 r.nextRestartTime = now + r.restartDelay;
11606
11607 // Make sure that we don't end up restarting a bunch of services
11608 // all at the same time.
11609 boolean repeat;
11610 do {
11611 repeat = false;
11612 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11613 ServiceRecord r2 = mRestartingServices.get(i);
11614 if (r2 != r && r.nextRestartTime
11615 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11616 && r.nextRestartTime
11617 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11618 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11619 r.restartDelay = r.nextRestartTime - now;
11620 repeat = true;
11621 break;
11622 }
11623 }
11624 } while (repeat);
11625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011626 if (!mRestartingServices.contains(r)) {
11627 mRestartingServices.add(r);
11628 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011629
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011630 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011633 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011635 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011637 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 r.shortName, r.restartDelay);
11639
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011640 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 }
11642
11643 final void performServiceRestartLocked(ServiceRecord r) {
11644 if (!mRestartingServices.contains(r)) {
11645 return;
11646 }
11647 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11648 }
11649
11650 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11651 if (r.restartDelay == 0) {
11652 return false;
11653 }
11654 r.resetRestartCounter();
11655 mRestartingServices.remove(r);
11656 mHandler.removeCallbacks(r.restarter);
11657 return true;
11658 }
11659
11660 private final boolean bringUpServiceLocked(ServiceRecord r,
11661 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011662 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 //r.dump(" ");
11664
Dianne Hackborn36124872009-10-08 16:22:03 -070011665 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 sendServiceArgsLocked(r, false);
11667 return true;
11668 }
11669
11670 if (!whileRestarting && r.restartDelay > 0) {
11671 // If waiting for a restart, then do nothing.
11672 return true;
11673 }
11674
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011675 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011677 // We are now bringing the service up, so no longer in the
11678 // restarting state.
11679 mRestartingServices.remove(r);
11680
Dianne Hackborne7f97212011-02-24 14:40:20 -080011681 // Service is now being launched, its package can't be stopped.
11682 try {
11683 AppGlobals.getPackageManager().setPackageStoppedState(
11684 r.packageName, false);
11685 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011686 } catch (IllegalArgumentException e) {
11687 Slog.w(TAG, "Failed trying to unstop package "
11688 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011689 }
11690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 final String appName = r.processName;
11692 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11693 if (app != null && app.thread != null) {
11694 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011695 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 realStartServiceLocked(r, app);
11697 return true;
11698 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011699 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 }
11701
11702 // If a dead object exception was thrown -- fall through to
11703 // restart the application.
11704 }
11705
Dianne Hackborn36124872009-10-08 16:22:03 -070011706 // Not running -- get it started, and enqueue this service record
11707 // to be executed when the app comes up.
11708 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11709 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011710 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011711 + r.appInfo.packageName + "/"
11712 + r.appInfo.uid + " for service "
11713 + r.intent.getIntent() + ": process is bad");
11714 bringDownServiceLocked(r, true);
11715 return false;
11716 }
11717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011719 mPendingServices.add(r);
11720 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 return true;
11723 }
11724
11725 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011726 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011727 //r.dump(" ");
11728
11729 // Does it still need to run?
11730 if (!force && r.startRequested) {
11731 return;
11732 }
11733 if (r.connections.size() > 0) {
11734 if (!force) {
11735 // XXX should probably keep a count of the number of auto-create
11736 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011737 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011739 ArrayList<ConnectionRecord> cr = it.next();
11740 for (int i=0; i<cr.size(); i++) {
11741 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
11742 return;
11743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011744 }
11745 }
11746 }
11747
11748 // Report to all of the connections that the service is no longer
11749 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011750 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011752 ArrayList<ConnectionRecord> c = it.next();
11753 for (int i=0; i<c.size(); i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011754 ConnectionRecord cr = c.get(i);
11755 // There is still a connection to the service that is
11756 // being brought down. Mark it as dead.
11757 cr.serviceDead = true;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011758 try {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011759 cr.conn.connected(r.name, null);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011760 } catch (Exception e) {
11761 Slog.w(TAG, "Failure disconnecting service " + r.name +
11762 " to connection " + c.get(i).conn.asBinder() +
11763 " (in " + c.get(i).binding.client.processName + ")", e);
11764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 }
11766 }
11767 }
11768
11769 // Tell the service that it has been unbound.
11770 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11771 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11772 while (it.hasNext()) {
11773 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011774 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 + ": hasBound=" + ibr.hasBound);
11776 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11777 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011778 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 updateOomAdjLocked(r.app);
11780 ibr.hasBound = false;
11781 r.app.thread.scheduleUnbindService(r,
11782 ibr.intent.getIntent());
11783 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011784 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 + r.shortName, e);
11786 serviceDoneExecutingLocked(r, true);
11787 }
11788 }
11789 }
11790 }
11791
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011792 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011793 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 System.identityHashCode(r), r.shortName,
11795 (r.app != null) ? r.app.pid : -1);
11796
11797 mServices.remove(r.name);
11798 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799 r.totalRestartCount = 0;
11800 unscheduleServiceRestartLocked(r);
11801
11802 // Also make sure it is not on the pending list.
11803 int N = mPendingServices.size();
11804 for (int i=0; i<N; i++) {
11805 if (mPendingServices.get(i) == r) {
11806 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011807 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 i--;
11809 N--;
11810 }
11811 }
11812
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011813 r.cancelNotification();
11814 r.isForeground = false;
11815 r.foregroundId = 0;
11816 r.foregroundNoti = null;
11817
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011818 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070011819 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011820 r.pendingStarts.clear();
11821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 if (r.app != null) {
11823 synchronized (r.stats.getBatteryStats()) {
11824 r.stats.stopLaunchedLocked();
11825 }
11826 r.app.services.remove(r);
11827 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011828 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011829 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 mStoppingServices.add(r);
11831 updateOomAdjLocked(r.app);
11832 r.app.thread.scheduleStopService(r);
11833 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011834 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 + r.shortName, e);
11836 serviceDoneExecutingLocked(r, true);
11837 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011838 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011840 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011841 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 }
11843 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011844 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011845 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080011847
11848 if (r.bindings.size() > 0) {
11849 r.bindings.clear();
11850 }
11851
11852 if (r.restarter instanceof ServiceRestarter) {
11853 ((ServiceRestarter)r.restarter).setService(null);
11854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011855 }
11856
11857 ComponentName startServiceLocked(IApplicationThread caller,
11858 Intent service, String resolvedType,
11859 int callingPid, int callingUid) {
11860 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011861 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011862 + " type=" + resolvedType + " args=" + service.getExtras());
11863
11864 if (caller != null) {
11865 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11866 if (callerApp == null) {
11867 throw new SecurityException(
11868 "Unable to find app for caller " + caller
11869 + " (pid=" + Binder.getCallingPid()
11870 + ") when starting service " + service);
11871 }
11872 }
11873
11874 ServiceLookupResult res =
11875 retrieveServiceLocked(service, resolvedType,
11876 callingPid, callingUid);
11877 if (res == null) {
11878 return null;
11879 }
11880 if (res.record == null) {
11881 return new ComponentName("!", res.permission != null
11882 ? res.permission : "private to package");
11883 }
11884 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070011885 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
11886 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011888 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 }
11890 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011891 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011892 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070011893 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 r.lastActivity = SystemClock.uptimeMillis();
11895 synchronized (r.stats.getBatteryStats()) {
11896 r.stats.startRunningLocked();
11897 }
11898 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11899 return new ComponentName("!", "Service process is bad");
11900 }
11901 return r.name;
11902 }
11903 }
11904
11905 public ComponentName startService(IApplicationThread caller, Intent service,
11906 String resolvedType) {
11907 // Refuse possible leaked file descriptors
11908 if (service != null && service.hasFileDescriptors() == true) {
11909 throw new IllegalArgumentException("File descriptors passed in Intent");
11910 }
11911
11912 synchronized(this) {
11913 final int callingPid = Binder.getCallingPid();
11914 final int callingUid = Binder.getCallingUid();
11915 final long origId = Binder.clearCallingIdentity();
11916 ComponentName res = startServiceLocked(caller, service,
11917 resolvedType, callingPid, callingUid);
11918 Binder.restoreCallingIdentity(origId);
11919 return res;
11920 }
11921 }
11922
11923 ComponentName startServiceInPackage(int uid,
11924 Intent service, String resolvedType) {
11925 synchronized(this) {
11926 final long origId = Binder.clearCallingIdentity();
11927 ComponentName res = startServiceLocked(null, service,
11928 resolvedType, -1, uid);
11929 Binder.restoreCallingIdentity(origId);
11930 return res;
11931 }
11932 }
11933
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011934 private void stopServiceLocked(ServiceRecord service) {
11935 synchronized (service.stats.getBatteryStats()) {
11936 service.stats.stopRunningLocked();
11937 }
11938 service.startRequested = false;
11939 service.callStart = false;
11940 bringDownServiceLocked(service, false);
11941 }
11942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943 public int stopService(IApplicationThread caller, Intent service,
11944 String resolvedType) {
11945 // Refuse possible leaked file descriptors
11946 if (service != null && service.hasFileDescriptors() == true) {
11947 throw new IllegalArgumentException("File descriptors passed in Intent");
11948 }
11949
11950 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011951 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 + " type=" + resolvedType);
11953
11954 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11955 if (caller != null && callerApp == null) {
11956 throw new SecurityException(
11957 "Unable to find app for caller " + caller
11958 + " (pid=" + Binder.getCallingPid()
11959 + ") when stopping service " + service);
11960 }
11961
11962 // If this service is active, make sure it is stopped.
11963 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11964 if (r != null) {
11965 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011966 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011967 try {
11968 stopServiceLocked(r.record);
11969 } finally {
11970 Binder.restoreCallingIdentity(origId);
11971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972 return 1;
11973 }
11974 return -1;
11975 }
11976 }
11977
11978 return 0;
11979 }
11980
11981 public IBinder peekService(Intent service, String resolvedType) {
11982 // Refuse possible leaked file descriptors
11983 if (service != null && service.hasFileDescriptors() == true) {
11984 throw new IllegalArgumentException("File descriptors passed in Intent");
11985 }
11986
11987 IBinder ret = null;
11988
11989 synchronized(this) {
11990 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11991
11992 if (r != null) {
11993 // r.record is null if findServiceLocked() failed the caller permission check
11994 if (r.record == null) {
11995 throw new SecurityException(
11996 "Permission Denial: Accessing service " + r.record.name
11997 + " from pid=" + Binder.getCallingPid()
11998 + ", uid=" + Binder.getCallingUid()
11999 + " requires " + r.permission);
12000 }
12001 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
12002 if (ib != null) {
12003 ret = ib.binder;
12004 }
12005 }
12006 }
12007
12008 return ret;
12009 }
12010
12011 public boolean stopServiceToken(ComponentName className, IBinder token,
12012 int startId) {
12013 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012014 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012015 + " " + token + " startId=" + startId);
12016 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012017 if (r != null) {
12018 if (startId >= 0) {
12019 // Asked to only stop if done with all work. Note that
12020 // to avoid leaks, we will take this as dropping all
12021 // start items up to and including this one.
12022 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12023 if (si != null) {
12024 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070012025 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
12026 cur.removeUriPermissionsLocked();
12027 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012028 break;
12029 }
12030 }
12031 }
12032
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012033 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012034 return false;
12035 }
12036
12037 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012038 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012039 + " is last, but have " + r.deliveredStarts.size()
12040 + " remaining args");
12041 }
12042 }
12043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012044 synchronized (r.stats.getBatteryStats()) {
12045 r.stats.stopRunningLocked();
12046 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012047 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048 }
12049 final long origId = Binder.clearCallingIdentity();
12050 bringDownServiceLocked(r, false);
12051 Binder.restoreCallingIdentity(origId);
12052 return true;
12053 }
12054 }
12055 return false;
12056 }
12057
12058 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012059 int id, Notification notification, boolean removeNotification) {
12060 final long origId = Binder.clearCallingIdentity();
12061 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012062 synchronized(this) {
12063 ServiceRecord r = findServiceLocked(className, token);
12064 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012065 if (id != 0) {
12066 if (notification == null) {
12067 throw new IllegalArgumentException("null notification");
12068 }
12069 if (r.foregroundId != id) {
12070 r.cancelNotification();
12071 r.foregroundId = id;
12072 }
12073 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
12074 r.foregroundNoti = notification;
12075 r.isForeground = true;
12076 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012077 if (r.app != null) {
12078 updateServiceForegroundLocked(r.app, true);
12079 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012080 } else {
12081 if (r.isForeground) {
12082 r.isForeground = false;
12083 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070012084 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012085 updateServiceForegroundLocked(r.app, true);
12086 }
12087 }
12088 if (removeNotification) {
12089 r.cancelNotification();
12090 r.foregroundId = 0;
12091 r.foregroundNoti = null;
12092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012093 }
12094 }
12095 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012096 } finally {
12097 Binder.restoreCallingIdentity(origId);
12098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012099 }
12100
12101 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
12102 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070012103 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 if (sr.isForeground) {
12105 anyForeground = true;
12106 break;
12107 }
12108 }
12109 if (anyForeground != proc.foregroundServices) {
12110 proc.foregroundServices = anyForeground;
12111 if (oomAdj) {
12112 updateOomAdjLocked();
12113 }
12114 }
12115 }
12116
12117 public int bindService(IApplicationThread caller, IBinder token,
12118 Intent service, String resolvedType,
12119 IServiceConnection connection, int flags) {
12120 // Refuse possible leaked file descriptors
12121 if (service != null && service.hasFileDescriptors() == true) {
12122 throw new IllegalArgumentException("File descriptors passed in Intent");
12123 }
12124
12125 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012126 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012127 + " type=" + resolvedType + " conn=" + connection.asBinder()
12128 + " flags=0x" + Integer.toHexString(flags));
12129 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12130 if (callerApp == null) {
12131 throw new SecurityException(
12132 "Unable to find app for caller " + caller
12133 + " (pid=" + Binder.getCallingPid()
12134 + ") when binding service " + service);
12135 }
12136
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012137 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012138 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070012139 activity = mMainStack.isInStackLocked(token);
12140 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012141 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 return 0;
12143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 }
12145
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012146 int clientLabel = 0;
12147 PendingIntent clientIntent = null;
12148
12149 if (callerApp.info.uid == Process.SYSTEM_UID) {
12150 // Hacky kind of thing -- allow system stuff to tell us
12151 // what they are, so we can report this elsewhere for
12152 // others to know why certain services are running.
12153 try {
12154 clientIntent = (PendingIntent)service.getParcelableExtra(
12155 Intent.EXTRA_CLIENT_INTENT);
12156 } catch (RuntimeException e) {
12157 }
12158 if (clientIntent != null) {
12159 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
12160 if (clientLabel != 0) {
12161 // There are no useful extras in the intent, trash them.
12162 // System code calling with this stuff just needs to know
12163 // this will happen.
12164 service = service.cloneFilter();
12165 }
12166 }
12167 }
12168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 ServiceLookupResult res =
12170 retrieveServiceLocked(service, resolvedType,
12171 Binder.getCallingPid(), Binder.getCallingUid());
12172 if (res == null) {
12173 return 0;
12174 }
12175 if (res.record == null) {
12176 return -1;
12177 }
12178 ServiceRecord s = res.record;
12179
12180 final long origId = Binder.clearCallingIdentity();
12181
12182 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012183 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012184 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 }
12186
12187 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12188 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012189 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012190
12191 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012192 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
12193 if (clist == null) {
12194 clist = new ArrayList<ConnectionRecord>();
12195 s.connections.put(binder, clist);
12196 }
12197 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012198 b.connections.add(c);
12199 if (activity != null) {
12200 if (activity.connections == null) {
12201 activity.connections = new HashSet<ConnectionRecord>();
12202 }
12203 activity.connections.add(c);
12204 }
12205 b.client.connections.add(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012206 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
12207 b.client.hasAboveClient = true;
12208 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012209 clist = mServiceConnections.get(binder);
12210 if (clist == null) {
12211 clist = new ArrayList<ConnectionRecord>();
12212 mServiceConnections.put(binder, clist);
12213 }
12214 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215
12216 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12217 s.lastActivity = SystemClock.uptimeMillis();
12218 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12219 return 0;
12220 }
12221 }
12222
12223 if (s.app != null) {
12224 // This could have made the service more important.
12225 updateOomAdjLocked(s.app);
12226 }
12227
Joe Onorato8a9b2202010-02-26 18:56:32 -080012228 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229 + ": received=" + b.intent.received
12230 + " apps=" + b.intent.apps.size()
12231 + " doRebind=" + b.intent.doRebind);
12232
12233 if (s.app != null && b.intent.received) {
12234 // Service is already running, so we can immediately
12235 // publish the connection.
12236 try {
12237 c.conn.connected(s.name, b.intent.binder);
12238 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012239 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012240 + " to connection " + c.conn.asBinder()
12241 + " (in " + c.binding.client.processName + ")", e);
12242 }
12243
12244 // If this is the first app connected back to this binding,
12245 // and the service had previously asked to be told when
12246 // rebound, then do so.
12247 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12248 requestServiceBindingLocked(s, b.intent, true);
12249 }
12250 } else if (!b.intent.requested) {
12251 requestServiceBindingLocked(s, b.intent, false);
12252 }
12253
12254 Binder.restoreCallingIdentity(origId);
12255 }
12256
12257 return 1;
12258 }
12259
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012260 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012261 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 IBinder binder = c.conn.asBinder();
12263 AppBindRecord b = c.binding;
12264 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012265 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
12266 if (clist != null) {
12267 clist.remove(c);
12268 if (clist.size() == 0) {
12269 s.connections.remove(binder);
12270 }
12271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 b.connections.remove(c);
12273 if (c.activity != null && c.activity != skipAct) {
12274 if (c.activity.connections != null) {
12275 c.activity.connections.remove(c);
12276 }
12277 }
12278 if (b.client != skipApp) {
12279 b.client.connections.remove(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012280 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
12281 b.client.updateHasAboveClientLocked();
12282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012283 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012284 clist = mServiceConnections.get(binder);
12285 if (clist != null) {
12286 clist.remove(c);
12287 if (clist.size() == 0) {
12288 mServiceConnections.remove(binder);
12289 }
12290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012291
12292 if (b.connections.size() == 0) {
12293 b.intent.apps.remove(b.client);
12294 }
12295
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012296 if (!c.serviceDead) {
12297 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
12298 + ": shouldUnbind=" + b.intent.hasBound);
12299 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12300 && b.intent.hasBound) {
12301 try {
12302 bumpServiceExecutingLocked(s, "unbind");
12303 updateOomAdjLocked(s.app);
12304 b.intent.hasBound = false;
12305 // Assume the client doesn't want to know about a rebind;
12306 // we will deal with that later if it asks for one.
12307 b.intent.doRebind = false;
12308 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12309 } catch (Exception e) {
12310 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
12311 serviceDoneExecutingLocked(s, true);
12312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012313 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012314
12315 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12316 bringDownServiceLocked(s, false);
12317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 }
12319 }
12320
12321 public boolean unbindService(IServiceConnection connection) {
12322 synchronized (this) {
12323 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012324 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012325 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
12326 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012327 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012328 + connection.asBinder());
12329 return false;
12330 }
12331
12332 final long origId = Binder.clearCallingIdentity();
12333
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012334 while (clist.size() > 0) {
12335 ConnectionRecord r = clist.get(0);
12336 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012337
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012338 if (r.binding.service.app != null) {
12339 // This could have made the service less important.
12340 updateOomAdjLocked(r.binding.service.app);
12341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342 }
12343
12344 Binder.restoreCallingIdentity(origId);
12345 }
12346
12347 return true;
12348 }
12349
12350 public void publishService(IBinder token, Intent intent, IBinder service) {
12351 // Refuse possible leaked file descriptors
12352 if (intent != null && intent.hasFileDescriptors() == true) {
12353 throw new IllegalArgumentException("File descriptors passed in Intent");
12354 }
12355
12356 synchronized(this) {
12357 if (!(token instanceof ServiceRecord)) {
12358 throw new IllegalArgumentException("Invalid service token");
12359 }
12360 ServiceRecord r = (ServiceRecord)token;
12361
12362 final long origId = Binder.clearCallingIdentity();
12363
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012364 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 + " " + intent + ": " + service);
12366 if (r != null) {
12367 Intent.FilterComparison filter
12368 = new Intent.FilterComparison(intent);
12369 IntentBindRecord b = r.bindings.get(filter);
12370 if (b != null && !b.received) {
12371 b.binder = service;
12372 b.requested = true;
12373 b.received = true;
12374 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012375 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012376 = r.connections.values().iterator();
12377 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012378 ArrayList<ConnectionRecord> clist = it.next();
12379 for (int i=0; i<clist.size(); i++) {
12380 ConnectionRecord c = clist.get(i);
12381 if (!filter.equals(c.binding.intent.intent)) {
12382 if (DEBUG_SERVICE) Slog.v(
12383 TAG, "Not publishing to: " + c);
12384 if (DEBUG_SERVICE) Slog.v(
12385 TAG, "Bound intent: " + c.binding.intent.intent);
12386 if (DEBUG_SERVICE) Slog.v(
12387 TAG, "Published intent: " + intent);
12388 continue;
12389 }
12390 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
12391 try {
12392 c.conn.connected(r.name, service);
12393 } catch (Exception e) {
12394 Slog.w(TAG, "Failure sending service " + r.name +
12395 " to connection " + c.conn.asBinder() +
12396 " (in " + c.binding.client.processName + ")", e);
12397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012398 }
12399 }
12400 }
12401 }
12402
12403 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12404
12405 Binder.restoreCallingIdentity(origId);
12406 }
12407 }
12408 }
12409
12410 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12411 // Refuse possible leaked file descriptors
12412 if (intent != null && intent.hasFileDescriptors() == true) {
12413 throw new IllegalArgumentException("File descriptors passed in Intent");
12414 }
12415
12416 synchronized(this) {
12417 if (!(token instanceof ServiceRecord)) {
12418 throw new IllegalArgumentException("Invalid service token");
12419 }
12420 ServiceRecord r = (ServiceRecord)token;
12421
12422 final long origId = Binder.clearCallingIdentity();
12423
12424 if (r != null) {
12425 Intent.FilterComparison filter
12426 = new Intent.FilterComparison(intent);
12427 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012428 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429 + " at " + b + ": apps="
12430 + (b != null ? b.apps.size() : 0));
Per Edelberg78f9fff2010-08-30 20:01:35 +020012431
12432 boolean inStopping = mStoppingServices.contains(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433 if (b != null) {
Per Edelberg78f9fff2010-08-30 20:01:35 +020012434 if (b.apps.size() > 0 && !inStopping) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012435 // Applications have already bound since the last
12436 // unbind, so just rebind right here.
12437 requestServiceBindingLocked(r, b, true);
12438 } else {
12439 // Note to tell the service the next time there is
12440 // a new client.
12441 b.doRebind = true;
12442 }
12443 }
12444
Per Edelberg78f9fff2010-08-30 20:01:35 +020012445 serviceDoneExecutingLocked(r, inStopping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446
12447 Binder.restoreCallingIdentity(origId);
12448 }
12449 }
12450 }
12451
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012452 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012453 synchronized(this) {
12454 if (!(token instanceof ServiceRecord)) {
12455 throw new IllegalArgumentException("Invalid service token");
12456 }
12457 ServiceRecord r = (ServiceRecord)token;
12458 boolean inStopping = mStoppingServices.contains(token);
12459 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012460 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012461 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012462 + " with incorrect token: given " + token
12463 + ", expected " + r);
12464 return;
12465 }
12466
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012467 if (type == 1) {
12468 // This is a call from a service start... take care of
12469 // book-keeping.
12470 r.callStart = true;
12471 switch (res) {
12472 case Service.START_STICKY_COMPATIBILITY:
12473 case Service.START_STICKY: {
12474 // We are done with the associated start arguments.
12475 r.findDeliveredStart(startId, true);
12476 // Don't stop if killed.
12477 r.stopIfKilled = false;
12478 break;
12479 }
12480 case Service.START_NOT_STICKY: {
12481 // We are done with the associated start arguments.
12482 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012483 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012484 // There is no more work, and this service
12485 // doesn't want to hang around if killed.
12486 r.stopIfKilled = true;
12487 }
12488 break;
12489 }
12490 case Service.START_REDELIVER_INTENT: {
12491 // We'll keep this item until they explicitly
12492 // call stop for it, but keep track of the fact
12493 // that it was delivered.
12494 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12495 if (si != null) {
12496 si.deliveryCount = 0;
12497 si.doneExecutingCount++;
12498 // Don't stop if killed.
12499 r.stopIfKilled = true;
12500 }
12501 break;
12502 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012503 case Service.START_TASK_REMOVED_COMPLETE: {
12504 // Special processing for onTaskRemoved(). Don't
12505 // impact normal onStartCommand() processing.
12506 r.findDeliveredStart(startId, true);
12507 break;
12508 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012509 default:
12510 throw new IllegalArgumentException(
12511 "Unknown service start result: " + res);
12512 }
12513 if (res == Service.START_STICKY_COMPATIBILITY) {
12514 r.callStart = false;
12515 }
12516 }
12517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012518 final long origId = Binder.clearCallingIdentity();
12519 serviceDoneExecutingLocked(r, inStopping);
12520 Binder.restoreCallingIdentity(origId);
12521 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012522 Slog.w(TAG, "Done executing unknown service from pid "
12523 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012524 }
12525 }
12526 }
12527
12528 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012529 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
12530 + ": nesting=" + r.executeNesting
12531 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012532 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533 r.executeNesting--;
12534 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012535 if (DEBUG_SERVICE) Slog.v(TAG,
12536 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012537 r.app.executingServices.remove(r);
12538 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012539 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
12540 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12542 }
12543 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012544 if (DEBUG_SERVICE) Slog.v(TAG,
12545 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012546 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020012547 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 }
12549 updateOomAdjLocked(r.app);
12550 }
12551 }
12552
12553 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012554 String anrMessage = null;
12555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012556 synchronized(this) {
12557 if (proc.executingServices.size() == 0 || proc.thread == null) {
12558 return;
12559 }
12560 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12561 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12562 ServiceRecord timeout = null;
12563 long nextTime = 0;
12564 while (it.hasNext()) {
12565 ServiceRecord sr = it.next();
12566 if (sr.executingStart < maxTime) {
12567 timeout = sr;
12568 break;
12569 }
12570 if (sr.executingStart > nextTime) {
12571 nextTime = sr.executingStart;
12572 }
12573 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012574 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012575 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012576 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 } else {
12578 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12579 msg.obj = proc;
12580 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12581 }
12582 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012583
12584 if (anrMessage != null) {
12585 appNotResponding(proc, null, null, anrMessage);
12586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012587 }
12588
12589 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012590 // BACKUP AND RESTORE
12591 // =========================================================
12592
12593 // Cause the target app to be launched if necessary and its backup agent
12594 // instantiated. The backup agent will invoke backupAgentCreated() on the
12595 // activity manager to announce its creation.
12596 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012597 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012598 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12599
12600 synchronized(this) {
12601 // !!! TODO: currently no check here that we're already bound
12602 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12603 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12604 synchronized (stats) {
12605 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12606 }
12607
Dianne Hackborne7f97212011-02-24 14:40:20 -080012608 // Backup agent is now in use, its package can't be stopped.
12609 try {
12610 AppGlobals.getPackageManager().setPackageStoppedState(
12611 app.packageName, false);
12612 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012613 } catch (IllegalArgumentException e) {
12614 Slog.w(TAG, "Failed trying to unstop package "
12615 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012616 }
12617
Christopher Tate181fafa2009-05-14 11:12:14 -070012618 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070012619 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
12620 ? new ComponentName(app.packageName, app.backupAgentName)
12621 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070012622 // startProcessLocked() returns existing proc's record if it's already running
12623 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012624 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012625 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012626 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012627 return false;
12628 }
12629
12630 r.app = proc;
12631 mBackupTarget = r;
12632 mBackupAppName = app.packageName;
12633
Christopher Tate6fa95972009-06-05 18:43:55 -070012634 // Try not to kill the process during backup
12635 updateOomAdjLocked(proc);
12636
Christopher Tate181fafa2009-05-14 11:12:14 -070012637 // If the process is already attached, schedule the creation of the backup agent now.
12638 // If it is not yet live, this will be done when it attaches to the framework.
12639 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012640 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012641 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012642 proc.thread.scheduleCreateBackupAgent(app,
12643 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012644 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012645 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012646 }
12647 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012648 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012649 }
12650 // Invariants: at this point, the target app process exists and the application
12651 // is either already running or in the process of coming up. mBackupTarget and
12652 // mBackupAppName describe the app, so that when it binds back to the AM we
12653 // know that it's scheduled for a backup-agent operation.
12654 }
12655
12656 return true;
12657 }
12658
12659 // A backup agent has just come up
12660 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012661 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012662 + " = " + agent);
12663
12664 synchronized(this) {
12665 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012666 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012667 return;
12668 }
Dianne Hackborn06740692010-09-22 22:46:21 -070012669 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012670
Dianne Hackborn06740692010-09-22 22:46:21 -070012671 long oldIdent = Binder.clearCallingIdentity();
12672 try {
12673 IBackupManager bm = IBackupManager.Stub.asInterface(
12674 ServiceManager.getService(Context.BACKUP_SERVICE));
12675 bm.agentConnected(agentPackageName, agent);
12676 } catch (RemoteException e) {
12677 // can't happen; the backup manager service is local
12678 } catch (Exception e) {
12679 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
12680 e.printStackTrace();
12681 } finally {
12682 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012683 }
12684 }
12685
12686 // done with this agent
12687 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012688 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012689 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012690 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012691 return;
12692 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012693
12694 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012695 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012696 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012697 return;
12698 }
12699
Christopher Tate181fafa2009-05-14 11:12:14 -070012700 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012701 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012702 return;
12703 }
12704
Christopher Tate6fa95972009-06-05 18:43:55 -070012705 ProcessRecord proc = mBackupTarget.app;
12706 mBackupTarget = null;
12707 mBackupAppName = null;
12708
12709 // Not backing this app up any more; reset its OOM adjustment
12710 updateOomAdjLocked(proc);
12711
Christopher Tatec7b31e32009-06-10 15:49:30 -070012712 // If the app crashed during backup, 'thread' will be null here
12713 if (proc.thread != null) {
12714 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012715 proc.thread.scheduleDestroyBackupAgent(appInfo,
12716 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070012717 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012718 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012719 e.printStackTrace();
12720 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012721 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012722 }
12723 }
12724 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012725 // BROADCASTS
12726 // =========================================================
12727
Josh Bartel7f208742010-02-25 11:01:44 -060012728 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012729 List cur) {
12730 final ContentResolver resolver = mContext.getContentResolver();
12731 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12732 if (list == null) {
12733 return cur;
12734 }
12735 int N = list.size();
12736 for (int i=0; i<N; i++) {
12737 Intent intent = list.get(i);
12738 if (filter.match(resolver, intent, true, TAG) >= 0) {
12739 if (cur == null) {
12740 cur = new ArrayList<Intent>();
12741 }
12742 cur.add(intent);
12743 }
12744 }
12745 return cur;
12746 }
12747
Christopher Tatef46723b2012-01-26 14:19:24 -080012748 boolean isPendingBroadcastProcessLocked(int pid) {
12749 return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
12750 || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid);
12751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012752
Christopher Tatef46723b2012-01-26 14:19:24 -080012753 void skipPendingBroadcastLocked(int pid) {
12754 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
12755 for (BroadcastQueue queue : mBroadcastQueues) {
12756 queue.skipPendingBroadcastLocked(pid);
12757 }
12758 }
12759
12760 // The app just attached; send any pending broadcasts that it should receive
12761 boolean sendPendingBroadcastsLocked(ProcessRecord app) {
12762 boolean didSomething = false;
12763 for (BroadcastQueue queue : mBroadcastQueues) {
12764 didSomething |= queue.sendPendingBroadcastsLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 }
Christopher Tatef46723b2012-01-26 14:19:24 -080012766 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012767 }
12768
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012769 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 IIntentReceiver receiver, IntentFilter filter, String permission) {
12771 synchronized(this) {
12772 ProcessRecord callerApp = null;
12773 if (caller != null) {
12774 callerApp = getRecordForAppLocked(caller);
12775 if (callerApp == null) {
12776 throw new SecurityException(
12777 "Unable to find app for caller " + caller
12778 + " (pid=" + Binder.getCallingPid()
12779 + ") when registering receiver " + receiver);
12780 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012781 if (callerApp.info.uid != Process.SYSTEM_UID &&
12782 !callerApp.pkgList.contains(callerPackage)) {
12783 throw new SecurityException("Given caller package " + callerPackage
12784 + " is not running in process " + callerApp);
12785 }
12786 } else {
12787 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012788 }
12789
12790 List allSticky = null;
12791
12792 // Look for any matching sticky broadcasts...
12793 Iterator actions = filter.actionsIterator();
12794 if (actions != null) {
12795 while (actions.hasNext()) {
12796 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012797 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012798 }
12799 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012800 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012801 }
12802
12803 // The first sticky in the list is returned directly back to
12804 // the client.
12805 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12806
Joe Onorato8a9b2202010-02-26 18:56:32 -080012807 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 + ": " + sticky);
12809
12810 if (receiver == null) {
12811 return sticky;
12812 }
12813
12814 ReceiverList rl
12815 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12816 if (rl == null) {
12817 rl = new ReceiverList(this, callerApp,
12818 Binder.getCallingPid(),
12819 Binder.getCallingUid(), receiver);
12820 if (rl.app != null) {
12821 rl.app.receivers.add(rl);
12822 } else {
12823 try {
12824 receiver.asBinder().linkToDeath(rl, 0);
12825 } catch (RemoteException e) {
12826 return sticky;
12827 }
12828 rl.linkedToDeath = true;
12829 }
12830 mRegisteredReceivers.put(receiver.asBinder(), rl);
12831 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012832 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012833 rl.add(bf);
12834 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012835 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 }
12837 mReceiverResolver.addFilter(bf);
12838
12839 // Enqueue broadcasts for all existing stickies that match
12840 // this filter.
12841 if (allSticky != null) {
12842 ArrayList receivers = new ArrayList();
12843 receivers.add(bf);
12844
12845 int N = allSticky.size();
12846 for (int i=0; i<N; i++) {
12847 Intent intent = (Intent)allSticky.get(i);
Christopher Tatef46723b2012-01-26 14:19:24 -080012848 BroadcastQueue queue = broadcastQueueForIntent(intent);
12849 BroadcastRecord r = new BroadcastRecord(queue, intent, null,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012850 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012851 false, true, true);
Christopher Tatef46723b2012-01-26 14:19:24 -080012852 queue.enqueueParallelBroadcastLocked(r);
12853 queue.scheduleBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854 }
12855 }
12856
12857 return sticky;
12858 }
12859 }
12860
12861 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012862 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863
Christopher Tatef46723b2012-01-26 14:19:24 -080012864 final long origId = Binder.clearCallingIdentity();
12865 try {
12866 boolean doTrim = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012867
Christopher Tatef46723b2012-01-26 14:19:24 -080012868 synchronized(this) {
12869 ReceiverList rl
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
Christopher Tatef46723b2012-01-26 14:19:24 -080012871 if (rl != null) {
12872 if (rl.curBroadcast != null) {
12873 BroadcastRecord r = rl.curBroadcast;
12874 final boolean doNext = finishReceiverLocked(
12875 receiver.asBinder(), r.resultCode, r.resultData,
12876 r.resultExtras, r.resultAbort, true);
12877 if (doNext) {
12878 doTrim = true;
12879 r.queue.processNextBroadcast(false);
12880 }
12881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012882
Christopher Tatef46723b2012-01-26 14:19:24 -080012883 if (rl.app != null) {
12884 rl.app.receivers.remove(rl);
12885 }
12886 removeReceiverLocked(rl);
12887 if (rl.linkedToDeath) {
12888 rl.linkedToDeath = false;
12889 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012891 }
12892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012893
Christopher Tatef46723b2012-01-26 14:19:24 -080012894 // If we actually concluded any broadcasts, we might now be able
12895 // to trim the recipients' apps from our working set
12896 if (doTrim) {
12897 trimApplications();
12898 return;
12899 }
12900
12901 } finally {
12902 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 }
12905
12906 void removeReceiverLocked(ReceiverList rl) {
12907 mRegisteredReceivers.remove(rl.receiver.asBinder());
12908 int N = rl.size();
12909 for (int i=0; i<N; i++) {
12910 mReceiverResolver.removeFilter(rl.get(i));
12911 }
12912 }
12913
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012914 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12915 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12916 ProcessRecord r = mLruProcesses.get(i);
12917 if (r.thread != null) {
12918 try {
12919 r.thread.dispatchPackageBroadcast(cmd, packages);
12920 } catch (RemoteException ex) {
12921 }
12922 }
12923 }
12924 }
12925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012926 private final int broadcastIntentLocked(ProcessRecord callerApp,
12927 String callerPackage, Intent intent, String resolvedType,
12928 IIntentReceiver resultTo, int resultCode, String resultData,
12929 Bundle map, String requiredPermission,
12930 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12931 intent = new Intent(intent);
12932
Dianne Hackborne7f97212011-02-24 14:40:20 -080012933 // By default broadcasts do not go to stopped apps.
12934 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
12935
Joe Onorato8a9b2202010-02-26 18:56:32 -080012936 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012937 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12938 + " ordered=" + ordered);
12939 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012940 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012941 }
12942
12943 // Handle special intents: if this broadcast is from the package
12944 // manager about a package being removed, we need to remove all of
12945 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012946 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012947 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012948 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12949 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012950 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012951 || uidRemoved) {
12952 if (checkComponentPermission(
12953 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012954 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 == PackageManager.PERMISSION_GRANTED) {
12956 if (uidRemoved) {
12957 final Bundle intentExtras = intent.getExtras();
12958 final int uid = intentExtras != null
12959 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12960 if (uid >= 0) {
12961 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12962 synchronized (bs) {
12963 bs.removeUidStatsLocked(uid);
12964 }
12965 }
12966 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012967 // If resources are unvailble just force stop all
12968 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012969 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012970 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12971 if (list != null && (list.length > 0)) {
12972 for (String pkg : list) {
Christopher Tate3dacd842011-08-19 14:56:15 -070012973 forceStopPackageLocked(pkg, -1, false, true, true, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012974 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012975 sendPackageBroadcastLocked(
12976 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012977 }
12978 } else {
12979 Uri data = intent.getData();
12980 String ssp;
12981 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12982 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12983 forceStopPackageLocked(ssp,
Christopher Tate3dacd842011-08-19 14:56:15 -070012984 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012985 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012986 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012987 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12988 new String[] {ssp});
12989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012990 }
12991 }
12992 }
12993 } else {
12994 String msg = "Permission Denial: " + intent.getAction()
12995 + " broadcast from " + callerPackage + " (pid=" + callingPid
12996 + ", uid=" + callingUid + ")"
12997 + " requires "
12998 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012999 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013000 throw new SecurityException(msg);
13001 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013002
13003 // Special case for adding a package: by default turn on compatibility
13004 // mode.
13005 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070013006 Uri data = intent.getData();
13007 String ssp;
13008 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
13009 mCompatModePackages.handlePackageAddedLocked(ssp,
13010 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013012 }
13013
13014 /*
13015 * If this is the time zone changed action, queue up a message that will reset the timezone
13016 * of all currently running processes. This message will get queued up before the broadcast
13017 * happens.
13018 */
13019 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
13020 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
13021 }
13022
Robert Greenwalt03595d02010-11-02 14:08:23 -070013023 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
13024 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
13025 }
13026
Robert Greenwalt434203a2010-10-11 16:00:27 -070013027 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
13028 ProxyProperties proxy = intent.getParcelableExtra("proxy");
13029 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
13030 }
13031
Dianne Hackborn854060af2009-07-09 18:14:31 -070013032 /*
13033 * Prevent non-system code (defined here to be non-persistent
13034 * processes) from sending protected broadcasts.
13035 */
13036 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
13037 || callingUid == Process.SHELL_UID || callingUid == 0) {
13038 // Always okay.
13039 } else if (callerApp == null || !callerApp.persistent) {
13040 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013041 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070013042 intent.getAction())) {
13043 String msg = "Permission Denial: not allowed to send broadcast "
13044 + intent.getAction() + " from pid="
13045 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013046 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070013047 throw new SecurityException(msg);
13048 }
13049 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013050 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070013051 return BROADCAST_SUCCESS;
13052 }
13053 }
13054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013055 // Add to the sticky list if requested.
13056 if (sticky) {
13057 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
13058 callingPid, callingUid)
13059 != PackageManager.PERMISSION_GRANTED) {
13060 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
13061 + callingPid + ", uid=" + callingUid
13062 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013063 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013064 throw new SecurityException(msg);
13065 }
13066 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013067 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013068 + " and enforce permission " + requiredPermission);
13069 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
13070 }
13071 if (intent.getComponent() != null) {
13072 throw new SecurityException(
13073 "Sticky broadcasts can't target a specific component");
13074 }
13075 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13076 if (list == null) {
13077 list = new ArrayList<Intent>();
13078 mStickyBroadcasts.put(intent.getAction(), list);
13079 }
13080 int N = list.size();
13081 int i;
13082 for (i=0; i<N; i++) {
13083 if (intent.filterEquals(list.get(i))) {
13084 // This sticky already exists, replace it.
13085 list.set(i, new Intent(intent));
13086 break;
13087 }
13088 }
13089 if (i >= N) {
13090 list.add(new Intent(intent));
13091 }
13092 }
13093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013094 // Figure out who all will receive this broadcast.
13095 List receivers = null;
13096 List<BroadcastFilter> registeredReceivers = null;
13097 try {
13098 if (intent.getComponent() != null) {
13099 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013100 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070013101 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102 if (ai != null) {
13103 receivers = new ArrayList();
13104 ResolveInfo ri = new ResolveInfo();
13105 ri.activityInfo = ai;
13106 receivers.add(ri);
13107 }
13108 } else {
13109 // Need to resolve the intent to interested receivers...
13110 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
13111 == 0) {
13112 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013113 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013114 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 }
Mihai Preda074edef2009-05-18 17:13:31 +020013116 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013117 }
13118 } catch (RemoteException ex) {
13119 // pm is in same process, this will never happen.
13120 }
13121
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013122 final boolean replacePending =
13123 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
13124
Joe Onorato8a9b2202010-02-26 18:56:32 -080013125 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013126 + " replacePending=" + replacePending);
13127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013128 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
13129 if (!ordered && NR > 0) {
13130 // If we are not serializing this broadcast, then send the
13131 // registered receivers separately so they don't wait for the
13132 // components to be launched.
Christopher Tatef46723b2012-01-26 14:19:24 -080013133 final BroadcastQueue queue = broadcastQueueForIntent(intent);
13134 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013135 callerPackage, callingPid, callingUid, requiredPermission,
13136 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013137 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013138 if (DEBUG_BROADCAST) Slog.v(
Christopher Tatef46723b2012-01-26 14:19:24 -080013139 TAG, "Enqueueing parallel broadcast " + r);
13140 final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013141 if (!replaced) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013142 queue.enqueueParallelBroadcastLocked(r);
13143 queue.scheduleBroadcastsLocked();
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013145 registeredReceivers = null;
13146 NR = 0;
13147 }
13148
13149 // Merge into one list.
13150 int ir = 0;
13151 if (receivers != null) {
13152 // A special case for PACKAGE_ADDED: do not allow the package
13153 // being added to see this broadcast. This prevents them from
13154 // using this as a back door to get run as soon as they are
13155 // installed. Maybe in the future we want to have a special install
13156 // broadcast or such for apps, but we'd like to deliberately make
13157 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013158 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013159 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
13160 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
13161 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013162 Uri data = intent.getData();
13163 if (data != null) {
13164 String pkgName = data.getSchemeSpecificPart();
13165 if (pkgName != null) {
13166 skipPackages = new String[] { pkgName };
13167 }
13168 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070013169 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013170 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070013171 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013172 if (skipPackages != null && (skipPackages.length > 0)) {
13173 for (String skipPackage : skipPackages) {
13174 if (skipPackage != null) {
13175 int NT = receivers.size();
13176 for (int it=0; it<NT; it++) {
13177 ResolveInfo curt = (ResolveInfo)receivers.get(it);
13178 if (curt.activityInfo.packageName.equals(skipPackage)) {
13179 receivers.remove(it);
13180 it--;
13181 NT--;
13182 }
13183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013184 }
13185 }
13186 }
13187
13188 int NT = receivers != null ? receivers.size() : 0;
13189 int it = 0;
13190 ResolveInfo curt = null;
13191 BroadcastFilter curr = null;
13192 while (it < NT && ir < NR) {
13193 if (curt == null) {
13194 curt = (ResolveInfo)receivers.get(it);
13195 }
13196 if (curr == null) {
13197 curr = registeredReceivers.get(ir);
13198 }
13199 if (curr.getPriority() >= curt.priority) {
13200 // Insert this broadcast record into the final list.
13201 receivers.add(it, curr);
13202 ir++;
13203 curr = null;
13204 it++;
13205 NT++;
13206 } else {
13207 // Skip to the next ResolveInfo in the final list.
13208 it++;
13209 curt = null;
13210 }
13211 }
13212 }
13213 while (ir < NR) {
13214 if (receivers == null) {
13215 receivers = new ArrayList();
13216 }
13217 receivers.add(registeredReceivers.get(ir));
13218 ir++;
13219 }
13220
13221 if ((receivers != null && receivers.size() > 0)
13222 || resultTo != null) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013223 BroadcastQueue queue = broadcastQueueForIntent(intent);
13224 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013225 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013226 receivers, resultTo, resultCode, resultData, map, ordered,
13227 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013228 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013229 TAG, "Enqueueing ordered broadcast " + r
Christopher Tatef46723b2012-01-26 14:19:24 -080013230 + ": prev had " + queue.mOrderedBroadcasts.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013231 if (DEBUG_BROADCAST) {
13232 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013233 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013234 }
Christopher Tatef46723b2012-01-26 14:19:24 -080013235 boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013236 if (!replaced) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013237 queue.enqueueOrderedBroadcastLocked(r);
13238 queue.scheduleBroadcastsLocked();
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 }
13241
13242 return BROADCAST_SUCCESS;
13243 }
13244
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013245 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013246 // Refuse possible leaked file descriptors
13247 if (intent != null && intent.hasFileDescriptors() == true) {
13248 throw new IllegalArgumentException("File descriptors passed in Intent");
13249 }
13250
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013251 int flags = intent.getFlags();
13252
13253 if (!mProcessesReady) {
13254 // if the caller really truly claims to know what they're doing, go
13255 // ahead and allow the broadcast without launching any receivers
13256 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
13257 intent = new Intent(intent);
13258 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
13259 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
13260 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
13261 + " before boot completion");
13262 throw new IllegalStateException("Cannot broadcast before boot completed");
13263 }
13264 }
13265
13266 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
13267 throw new IllegalArgumentException(
13268 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13269 }
13270
13271 return intent;
13272 }
13273
13274 public final int broadcastIntent(IApplicationThread caller,
13275 Intent intent, String resolvedType, IIntentReceiver resultTo,
13276 int resultCode, String resultData, Bundle map,
13277 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013278 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013279 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013281 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13282 final int callingPid = Binder.getCallingPid();
13283 final int callingUid = Binder.getCallingUid();
13284 final long origId = Binder.clearCallingIdentity();
13285 int res = broadcastIntentLocked(callerApp,
13286 callerApp != null ? callerApp.info.packageName : null,
13287 intent, resolvedType, resultTo,
13288 resultCode, resultData, map, requiredPermission, serialized,
13289 sticky, callingPid, callingUid);
13290 Binder.restoreCallingIdentity(origId);
13291 return res;
13292 }
13293 }
13294
13295 int broadcastIntentInPackage(String packageName, int uid,
13296 Intent intent, String resolvedType, IIntentReceiver resultTo,
13297 int resultCode, String resultData, Bundle map,
13298 String requiredPermission, boolean serialized, boolean sticky) {
13299 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013300 intent = verifyBroadcastLocked(intent);
13301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302 final long origId = Binder.clearCallingIdentity();
13303 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13304 resultTo, resultCode, resultData, map, requiredPermission,
13305 serialized, sticky, -1, uid);
13306 Binder.restoreCallingIdentity(origId);
13307 return res;
13308 }
13309 }
13310
13311 public final void unbroadcastIntent(IApplicationThread caller,
13312 Intent intent) {
13313 // Refuse possible leaked file descriptors
13314 if (intent != null && intent.hasFileDescriptors() == true) {
13315 throw new IllegalArgumentException("File descriptors passed in Intent");
13316 }
13317
13318 synchronized(this) {
13319 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13320 != PackageManager.PERMISSION_GRANTED) {
13321 String msg = "Permission Denial: unbroadcastIntent() from pid="
13322 + Binder.getCallingPid()
13323 + ", uid=" + Binder.getCallingUid()
13324 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013325 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013326 throw new SecurityException(msg);
13327 }
13328 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13329 if (list != null) {
13330 int N = list.size();
13331 int i;
13332 for (i=0; i<N; i++) {
13333 if (intent.filterEquals(list.get(i))) {
13334 list.remove(i);
13335 break;
13336 }
13337 }
13338 }
13339 }
13340 }
13341
13342 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13343 String resultData, Bundle resultExtras, boolean resultAbort,
13344 boolean explicit) {
Christopher Tatef46723b2012-01-26 14:19:24 -080013345 final BroadcastRecord r = broadcastRecordForReceiverLocked(receiver);
13346 if (r == null) {
13347 Slog.w(TAG, "finishReceiver called but not found on queue");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013348 return false;
13349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013350
Christopher Tatef46723b2012-01-26 14:19:24 -080013351 return r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort,
13352 explicit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013353 }
13354
13355 public void finishReceiver(IBinder who, int resultCode, String resultData,
13356 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013357 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358
13359 // Refuse possible leaked file descriptors
13360 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13361 throw new IllegalArgumentException("File descriptors passed in Bundle");
13362 }
13363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013364 final long origId = Binder.clearCallingIdentity();
Christopher Tatef46723b2012-01-26 14:19:24 -080013365 try {
13366 boolean doNext = false;
13367 BroadcastRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368
Christopher Tatef46723b2012-01-26 14:19:24 -080013369 synchronized(this) {
13370 r = broadcastRecordForReceiverLocked(who);
13371 if (r != null) {
13372 doNext = r.queue.finishReceiverLocked(r, resultCode,
13373 resultData, resultExtras, resultAbort, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013375 }
Jeff Brown4d94a762010-09-23 11:33:28 -070013376
Christopher Tatef46723b2012-01-26 14:19:24 -080013377 if (doNext) {
13378 r.queue.processNextBroadcast(false);
13379 }
13380 trimApplications();
13381 } finally {
13382 Binder.restoreCallingIdentity(origId);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013384 }
13385
13386 private final void processCurBroadcastLocked(BroadcastRecord r,
13387 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013388 if (DEBUG_BROADCAST) Slog.v(TAG,
13389 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013390 if (app.thread == null) {
13391 throw new RemoteException();
13392 }
13393 r.receiver = app.thread.asBinder();
13394 r.curApp = app;
13395 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013396 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397
13398 // Tell the application to launch this receiver.
13399 r.intent.setComponent(r.curComponent);
13400
13401 boolean started = false;
13402 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013403 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404 "Delivering to component " + r.curComponent
13405 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013406 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040013408 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013409 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013410 if (DEBUG_BROADCAST) Slog.v(TAG,
13411 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013412 started = true;
13413 } finally {
13414 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013415 if (DEBUG_BROADCAST) Slog.v(TAG,
13416 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013417 r.receiver = null;
13418 r.curApp = null;
13419 app.curReceiver = null;
13420 }
13421 }
13422
13423 }
13424
Jeff Brown4d94a762010-09-23 11:33:28 -070013425 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013426 Intent intent, int resultCode, String data, Bundle extras,
13427 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070013428 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013429 if (app != null && app.thread != null) {
13430 // If we have an app thread, do the call through that so it is
13431 // correctly ordered with other one-way calls.
13432 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013433 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013434 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013435 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 }
13437 }
13438
Jeff Brown4d94a762010-09-23 11:33:28 -070013439 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440 BroadcastFilter filter, boolean ordered) {
13441 boolean skip = false;
13442 if (filter.requiredPermission != null) {
13443 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013444 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013445 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013446 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 + r.intent.toString()
13448 + " from " + r.callerPackage + " (pid="
13449 + r.callingPid + ", uid=" + r.callingUid + ")"
13450 + " requires " + filter.requiredPermission
13451 + " due to registered receiver " + filter);
13452 skip = true;
13453 }
13454 }
13455 if (r.requiredPermission != null) {
13456 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013457 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013458 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013459 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013460 + r.intent.toString()
13461 + " to " + filter.receiverList.app
13462 + " (pid=" + filter.receiverList.pid
13463 + ", uid=" + filter.receiverList.uid + ")"
13464 + " requires " + r.requiredPermission
13465 + " due to sender " + r.callerPackage
13466 + " (uid " + r.callingUid + ")");
13467 skip = true;
13468 }
13469 }
13470
13471 if (!skip) {
13472 // If this is not being sent as an ordered broadcast, then we
13473 // don't want to touch the fields that keep track of the current
13474 // state of ordered broadcasts.
13475 if (ordered) {
13476 r.receiver = filter.receiverList.receiver.asBinder();
13477 r.curFilter = filter;
13478 filter.receiverList.curBroadcast = r;
13479 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013480 if (filter.receiverList.app != null) {
13481 // Bump hosting application to no longer be in background
13482 // scheduling class. Note that we can't do that if there
13483 // isn't an app... but we can only be in that case for
13484 // things that directly call the IActivityManager API, which
13485 // are already core system stuff so don't matter for this.
13486 r.curApp = filter.receiverList.app;
13487 filter.receiverList.app.curReceiver = r;
13488 updateOomAdjLocked();
13489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013490 }
13491 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013492 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013493 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013494 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013495 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013496 }
Jeff Brown4d94a762010-09-23 11:33:28 -070013497 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013498 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013499 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013500 if (ordered) {
13501 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13502 }
13503 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013504 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013505 if (ordered) {
13506 r.receiver = null;
13507 r.curFilter = null;
13508 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013509 if (filter.receiverList.app != null) {
13510 filter.receiverList.app.curReceiver = null;
13511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013512 }
13513 }
13514 }
13515 }
13516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013517
13518 // =========================================================
13519 // INSTRUMENTATION
13520 // =========================================================
13521
13522 public boolean startInstrumentation(ComponentName className,
13523 String profileFile, int flags, Bundle arguments,
13524 IInstrumentationWatcher watcher) {
13525 // Refuse possible leaked file descriptors
13526 if (arguments != null && arguments.hasFileDescriptors()) {
13527 throw new IllegalArgumentException("File descriptors passed in Bundle");
13528 }
13529
13530 synchronized(this) {
13531 InstrumentationInfo ii = null;
13532 ApplicationInfo ai = null;
13533 try {
13534 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013535 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013536 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013537 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 } catch (PackageManager.NameNotFoundException e) {
13539 }
13540 if (ii == null) {
13541 reportStartInstrumentationFailure(watcher, className,
13542 "Unable to find instrumentation info for: " + className);
13543 return false;
13544 }
13545 if (ai == null) {
13546 reportStartInstrumentationFailure(watcher, className,
13547 "Unable to find instrumentation target package: " + ii.targetPackage);
13548 return false;
13549 }
13550
13551 int match = mContext.getPackageManager().checkSignatures(
13552 ii.targetPackage, ii.packageName);
13553 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13554 String msg = "Permission Denial: starting instrumentation "
13555 + className + " from pid="
13556 + Binder.getCallingPid()
13557 + ", uid=" + Binder.getCallingPid()
13558 + " not allowed because package " + ii.packageName
13559 + " does not have a signature matching the target "
13560 + ii.targetPackage;
13561 reportStartInstrumentationFailure(watcher, className, msg);
13562 throw new SecurityException(msg);
13563 }
13564
13565 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -070013566 // Instrumentation can kill and relaunch even persistent processes
13567 forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 ProcessRecord app = addAppLocked(ai);
13569 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013570 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013571 app.instrumentationProfileFile = profileFile;
13572 app.instrumentationArguments = arguments;
13573 app.instrumentationWatcher = watcher;
13574 app.instrumentationResultClass = className;
13575 Binder.restoreCallingIdentity(origId);
13576 }
13577
13578 return true;
13579 }
13580
13581 /**
13582 * Report errors that occur while attempting to start Instrumentation. Always writes the
13583 * error to the logs, but if somebody is watching, send the report there too. This enables
13584 * the "am" command to report errors with more information.
13585 *
13586 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13587 * @param cn The component name of the instrumentation.
13588 * @param report The error report.
13589 */
13590 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13591 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013592 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013593 try {
13594 if (watcher != null) {
13595 Bundle results = new Bundle();
13596 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13597 results.putString("Error", report);
13598 watcher.instrumentationStatus(cn, -1, results);
13599 }
13600 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013601 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 }
13603 }
13604
13605 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13606 if (app.instrumentationWatcher != null) {
13607 try {
13608 // NOTE: IInstrumentationWatcher *must* be oneway here
13609 app.instrumentationWatcher.instrumentationFinished(
13610 app.instrumentationClass,
13611 resultCode,
13612 results);
13613 } catch (RemoteException e) {
13614 }
13615 }
13616 app.instrumentationWatcher = null;
13617 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013618 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013619 app.instrumentationProfileFile = null;
13620 app.instrumentationArguments = null;
13621
Christopher Tate3dacd842011-08-19 14:56:15 -070013622 forceStopPackageLocked(app.processName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623 }
13624
13625 public void finishInstrumentation(IApplicationThread target,
13626 int resultCode, Bundle results) {
13627 // Refuse possible leaked file descriptors
13628 if (results != null && results.hasFileDescriptors()) {
13629 throw new IllegalArgumentException("File descriptors passed in Intent");
13630 }
13631
13632 synchronized(this) {
13633 ProcessRecord app = getRecordForAppLocked(target);
13634 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013635 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013636 return;
13637 }
13638 final long origId = Binder.clearCallingIdentity();
13639 finishInstrumentationLocked(app, resultCode, results);
13640 Binder.restoreCallingIdentity(origId);
13641 }
13642 }
13643
13644 // =========================================================
13645 // CONFIGURATION
13646 // =========================================================
13647
13648 public ConfigurationInfo getDeviceConfigurationInfo() {
13649 ConfigurationInfo config = new ConfigurationInfo();
13650 synchronized (this) {
13651 config.reqTouchScreen = mConfiguration.touchscreen;
13652 config.reqKeyboardType = mConfiguration.keyboard;
13653 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013654 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13655 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013656 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13657 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013658 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13659 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013660 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13661 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013662 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013663 }
13664 return config;
13665 }
13666
13667 public Configuration getConfiguration() {
13668 Configuration ci;
13669 synchronized(this) {
13670 ci = new Configuration(mConfiguration);
13671 }
13672 return ci;
13673 }
13674
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013675 public void updatePersistentConfiguration(Configuration values) {
13676 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13677 "updateConfiguration()");
13678 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
13679 "updateConfiguration()");
13680 if (values == null) {
13681 throw new NullPointerException("Configuration must not be null");
13682 }
13683
13684 synchronized(this) {
13685 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn813075a62011-11-14 17:45:19 -080013686 updateConfigurationLocked(values, null, true, false);
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013687 Binder.restoreCallingIdentity(origId);
13688 }
13689 }
13690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013691 public void updateConfiguration(Configuration values) {
13692 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13693 "updateConfiguration()");
13694
13695 synchronized(this) {
13696 if (values == null && mWindowManager != null) {
13697 // sentinel: fetch the current configuration from the window manager
13698 values = mWindowManager.computeNewConfiguration();
13699 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013700
13701 if (mWindowManager != null) {
13702 mProcessList.applyDisplaySize(mWindowManager);
13703 }
13704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013705 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013706 if (values != null) {
13707 Settings.System.clearConfiguration(values);
13708 }
Dianne Hackborn813075a62011-11-14 17:45:19 -080013709 updateConfigurationLocked(values, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013710 Binder.restoreCallingIdentity(origId);
13711 }
13712 }
13713
13714 /**
13715 * Do either or both things: (1) change the current configuration, and (2)
13716 * make sure the given activity is running with the (now) current
13717 * configuration. Returns true if the activity has been left running, or
13718 * false if <var>starting</var> is being destroyed to match the new
13719 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013720 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013721 */
13722 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn813075a62011-11-14 17:45:19 -080013723 ActivityRecord starting, boolean persistent, boolean initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013724 int changes = 0;
13725
13726 boolean kept = true;
13727
13728 if (values != null) {
13729 Configuration newConfig = new Configuration(mConfiguration);
13730 changes = newConfig.updateFrom(values);
13731 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013732 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013733 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 }
13735
Doug Zongker2bec3d42009-12-04 12:52:44 -080013736 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013737
Dianne Hackborn813075a62011-11-14 17:45:19 -080013738 if (values.locale != null && !initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013739 saveLocaleLocked(values.locale,
13740 !values.locale.equals(mConfiguration.locale),
13741 values.userSetLocale);
13742 }
13743
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013744 mConfigurationSeq++;
13745 if (mConfigurationSeq <= 0) {
13746 mConfigurationSeq = 1;
13747 }
13748 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013749 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013750 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013751
13752 final Configuration configCopy = new Configuration(mConfiguration);
13753
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013754 AttributeCache ac = AttributeCache.instance();
13755 if (ac != null) {
Dianne Hackborn813075a62011-11-14 17:45:19 -080013756 ac.updateConfiguration(configCopy);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013758
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013759 // Make sure all resources in our process are updated
13760 // right now, so that anyone who is going to retrieve
13761 // resource values after we return will be sure to get
13762 // the new ones. This is especially important during
13763 // boot, where the first config change needs to guarantee
13764 // all resources have that config before following boot
13765 // code is executed.
Dianne Hackborn813075a62011-11-14 17:45:19 -080013766 mSystemThread.applyConfigurationToResources(configCopy);
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013767
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013768 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013769 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013770 msg.obj = new Configuration(configCopy);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013771 mHandler.sendMessage(msg);
13772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013773
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013774 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13775 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013776 try {
13777 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013778 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013779 + app.processName + " new config " + mConfiguration);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013780 app.thread.scheduleConfigurationChanged(configCopy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013781 }
13782 } catch (Exception e) {
13783 }
13784 }
13785 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013786 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13787 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013788 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13789 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013790 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13791 broadcastIntentLocked(null, null,
13792 new Intent(Intent.ACTION_LOCALE_CHANGED),
13793 null, null, 0, null, null,
13794 null, false, false, MY_PID, Process.SYSTEM_UID);
13795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013796 }
13797 }
13798
13799 if (changes != 0 && starting == null) {
13800 // If the configuration changed, and the caller is not already
13801 // in the process of starting an activity, then find the top
13802 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013803 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013804 }
13805
13806 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013807 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080013808 // And we need to make sure at this point that all other activities
13809 // are made visible with the correct configuration.
13810 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013811 }
13812
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013813 if (values != null && mWindowManager != null) {
13814 mWindowManager.setNewConfiguration(mConfiguration);
13815 }
13816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013817 return kept;
13818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013819
13820 /**
13821 * Save the locale. You must be inside a synchronized (this) block.
13822 */
13823 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13824 if(isDiff) {
13825 SystemProperties.set("user.language", l.getLanguage());
13826 SystemProperties.set("user.region", l.getCountry());
13827 }
13828
13829 if(isPersist) {
13830 SystemProperties.set("persist.sys.language", l.getLanguage());
13831 SystemProperties.set("persist.sys.country", l.getCountry());
13832 SystemProperties.set("persist.sys.localevar", l.getVariant());
13833 }
13834 }
13835
13836 // =========================================================
13837 // LIFETIME MANAGEMENT
13838 // =========================================================
13839
Christopher Tatef46723b2012-01-26 14:19:24 -080013840 // Returns which broadcast queue the app is the current [or imminent] receiver
13841 // on, or 'null' if the app is not an active broadcast recipient.
13842 private BroadcastQueue isReceivingBroadcast(ProcessRecord app) {
13843 BroadcastRecord r = app.curReceiver;
13844 if (r != null) {
13845 return r.queue;
13846 }
13847
13848 // It's not the current receiver, but it might be starting up to become one
13849 synchronized (this) {
13850 for (BroadcastQueue queue : mBroadcastQueues) {
13851 r = queue.mPendingBroadcast;
13852 if (r != null && r.curApp == app) {
13853 // found it; report which queue it's in
13854 return queue;
13855 }
13856 }
13857 }
13858
13859 return null;
13860 }
13861
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013862 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013863 ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013864 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013865 // This adjustment has already been computed. If we are calling
13866 // from the top, we may have already computed our adjustment with
13867 // an earlier hidden adjustment that isn't really for us... if
13868 // so, use the new hidden adjustment.
13869 if (!recursed && app.hidden) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013870 app.curAdj = app.curRawAdj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013871 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013872 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 }
13874
13875 if (app.thread == null) {
13876 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013877 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013878 return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013879 }
13880
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013881 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
13882 app.adjSource = null;
13883 app.adjTarget = null;
13884 app.empty = false;
13885 app.hidden = false;
13886
13887 final int activitiesSize = app.activities.size();
13888
Dianne Hackborn7d608422011-08-07 16:24:18 -070013889 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013890 // The max adjustment doesn't allow this app to be anything
13891 // below foreground, so it is not worth doing work for it.
13892 app.adjType = "fixed";
13893 app.adjSeq = mAdjSeq;
13894 app.curRawAdj = app.maxAdj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013895 app.foregroundActivities = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013896 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013897 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013898 // System process can do UI, and when they do we want to have
13899 // them trim their memory after the user leaves the UI. To
13900 // facilitate this, here we need to determine whether or not it
13901 // is currently showing UI.
13902 app.systemNoUi = true;
13903 if (app == TOP_APP) {
13904 app.systemNoUi = false;
13905 } else if (activitiesSize > 0) {
13906 for (int j = 0; j < activitiesSize; j++) {
13907 final ActivityRecord r = app.activities.get(j);
13908 if (r.visible) {
13909 app.systemNoUi = false;
13910 break;
13911 }
13912 }
13913 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013914 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013915 }
13916
13917 final boolean hadForegroundActivities = app.foregroundActivities;
13918
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013919 app.foregroundActivities = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013920 app.keeping = false;
13921 app.systemNoUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013922
The Android Open Source Project4df24232009-03-05 14:34:35 -080013923 // Determine the importance of the process, starting with most
13924 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013925 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013926 int schedGroup;
Christopher Tatef46723b2012-01-26 14:19:24 -080013927 BroadcastQueue queue;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013928 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013929 // The last app on the list is the foreground app.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013930 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013931 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013932 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013933 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013934 } else if (app.instrumentationClass != null) {
13935 // Don't want to kill running instrumentation.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013936 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013937 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013938 app.adjType = "instrumentation";
Christopher Tatef46723b2012-01-26 14:19:24 -080013939 } else if ((queue = isReceivingBroadcast(app)) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013940 // An app that is currently receiving a broadcast also
Christopher Tatef46723b2012-01-26 14:19:24 -080013941 // counts as being in the foreground for OOM killer purposes.
13942 // It's placed in a sched group based on the nature of the
13943 // broadcast as reflected by which queue it's active in.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013944 adj = ProcessList.FOREGROUND_APP_ADJ;
Christopher Tatef46723b2012-01-26 14:19:24 -080013945 schedGroup = (queue == mFgBroadcastQueue)
13946 ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013947 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013948 } else if (app.executingServices.size() > 0) {
13949 // An app that is currently executing a service callback also
13950 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013951 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013952 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013953 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013954 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013955 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013956 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013957 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013958 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013959 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013960 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013961 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013962 // A very not-needed process. If this is lower in the lru list,
13963 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013964 adj = hiddenAdj;
13965 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013966 app.hidden = true;
13967 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013968 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013969 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013970
13971 // Examine all activities if not already foreground.
13972 if (!app.foregroundActivities && activitiesSize > 0) {
13973 for (int j = 0; j < activitiesSize; j++) {
13974 final ActivityRecord r = app.activities.get(j);
13975 if (r.visible) {
13976 // App has a visible activity; only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013977 if (adj > ProcessList.VISIBLE_APP_ADJ) {
13978 adj = ProcessList.VISIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013979 app.adjType = "visible";
13980 }
13981 schedGroup = Process.THREAD_GROUP_DEFAULT;
13982 app.hidden = false;
13983 app.foregroundActivities = true;
13984 break;
13985 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
13986 || r.state == ActivityState.STOPPING) {
13987 // Only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013988 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
13989 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013990 app.adjType = "stopping";
13991 }
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -080013992 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013993 app.foregroundActivities = true;
13994 }
13995 }
13996 }
13997
Dianne Hackborn7d608422011-08-07 16:24:18 -070013998 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013999 if (app.foregroundServices) {
14000 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014001 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014002 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014003 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014004 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014005 } else if (app.forcingToForeground != null) {
14006 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014007 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014008 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014009 app.adjType = "force-foreground";
14010 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014011 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014012 }
14013 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014014
Dianne Hackborn7d608422011-08-07 16:24:18 -070014015 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014016 // We don't want to kill the current heavy-weight process.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014017 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014018 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014019 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014020 app.adjType = "heavy";
14021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014022
Dianne Hackborn7d608422011-08-07 16:24:18 -070014023 if (adj > ProcessList.HOME_APP_ADJ && app == mHomeProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014024 // This process is hosting what we currently consider to be the
14025 // home app, so we don't want to let it go into the background.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014026 adj = ProcessList.HOME_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014027 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014028 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080014029 app.adjType = "home";
14030 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014031
Dianne Hackbornf35fe232011-11-01 19:25:20 -070014032 if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
14033 && app.activities.size() > 0) {
14034 // This was the previous process that showed UI to the user.
14035 // We want to try to keep it around more aggressively, to give
14036 // a good experience around switching between two apps.
14037 adj = ProcessList.PREVIOUS_APP_ADJ;
14038 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
14039 app.hidden = false;
14040 app.adjType = "previous";
14041 }
14042
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014043 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
14044 + " reason=" + app.adjType);
14045
The Android Open Source Project4df24232009-03-05 14:34:35 -080014046 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014047 // there are applications dependent on our services or providers, but
14048 // this gives us a baseline and makes sure we don't get into an
14049 // infinite recursion.
14050 app.adjSeq = mAdjSeq;
14051 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014052
Christopher Tate6fa95972009-06-05 18:43:55 -070014053 if (mBackupTarget != null && app == mBackupTarget.app) {
14054 // If possible we want to avoid killing apps while they're being backed up
Dianne Hackborn7d608422011-08-07 16:24:18 -070014055 if (adj > ProcessList.BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014056 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014057 adj = ProcessList.BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014058 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014059 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014060 }
14061 }
14062
Dianne Hackborn7d608422011-08-07 16:24:18 -070014063 if (app.services.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014064 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014065 final long now = SystemClock.uptimeMillis();
14066 // This process is more important if the top activity is
14067 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014068 Iterator<ServiceRecord> jt = app.services.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014069 while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014070 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014071 if (s.startRequested) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014072 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014073 // If this process has shown some UI, let it immediately
14074 // go to the LRU list because it may be pretty heavy with
14075 // UI stuff. We'll tag it with a label just to help
14076 // debug and understand what is going on.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014077 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014078 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014079 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014080 } else {
14081 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14082 // This service has seen some activity within
14083 // recent memory, so we will keep its process ahead
14084 // of the background processes.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014085 if (adj > ProcessList.SERVICE_ADJ) {
14086 adj = ProcessList.SERVICE_ADJ;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014087 app.adjType = "started-services";
14088 app.hidden = false;
14089 }
14090 }
14091 // If we have let the service slide into the background
14092 // state, still have some text describing what it is doing
14093 // even though the service no longer has an impact.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014094 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070014095 app.adjType = "started-bg-services";
14096 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014097 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014098 // Don't kill this process because it is doing work; it
14099 // has said it is doing work.
14100 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014101 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014102 if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014103 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014104 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014105 = s.connections.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014106 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014107 ArrayList<ConnectionRecord> clist = kt.next();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014108 for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014109 // XXX should compute this based on the max of
14110 // all connected clients.
14111 ConnectionRecord cr = clist.get(i);
14112 if (cr.binding.client == app) {
14113 // Binding to ourself is not interesting.
14114 continue;
14115 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014116 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014117 ProcessRecord client = cr.binding.client;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014118 int clientAdj = adj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014119 int myHiddenAdj = hiddenAdj;
14120 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014121 if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014122 myHiddenAdj = client.hiddenAdj;
14123 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014124 myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014125 }
14126 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014127 clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014128 client, myHiddenAdj, TOP_APP, true, doingAll);
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014129 String adjType = null;
14130 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
14131 // Not doing bind OOM management, so treat
14132 // this guy more like a started service.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014133 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014134 // If this process has shown some UI, let it immediately
14135 // go to the LRU list because it may be pretty heavy with
14136 // UI stuff. We'll tag it with a label just to help
14137 // debug and understand what is going on.
14138 if (adj > clientAdj) {
14139 adjType = "bound-bg-ui-services";
14140 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014141 app.hidden = false;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014142 clientAdj = adj;
14143 } else {
14144 if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14145 // This service has not seen activity within
14146 // recent memory, so allow it to drop to the
14147 // LRU list if there is no other reason to keep
14148 // it around. We'll also tag it with a label just
14149 // to help debug and undertand what is going on.
14150 if (adj > clientAdj) {
14151 adjType = "bound-bg-services";
14152 }
14153 clientAdj = adj;
14154 }
14155 }
14156 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014157 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014158 // If this process has recently shown UI, and
14159 // the process that is binding to it is less
14160 // important than being visible, then we don't
14161 // care about the binding as much as we care
14162 // about letting this process get into the LRU
14163 // list to be killed and restarted if needed for
14164 // memory.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014165 if (app.hasShownUi && app != mHomeProcess
14166 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014167 adjType = "bound-bg-ui-services";
14168 } else {
14169 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
14170 |Context.BIND_IMPORTANT)) != 0) {
14171 adj = clientAdj;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070014172 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
14173 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
14174 && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
14175 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
14176 } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014177 adj = clientAdj;
14178 } else {
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070014179 app.pendingUiClean = true;
14180 if (adj > ProcessList.VISIBLE_APP_ADJ) {
14181 adj = ProcessList.VISIBLE_APP_ADJ;
14182 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014183 }
14184 if (!client.hidden) {
14185 app.hidden = false;
14186 }
14187 if (client.keeping) {
14188 app.keeping = true;
14189 }
14190 adjType = "service";
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014191 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014192 }
14193 if (adjType != null) {
14194 app.adjType = adjType;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014195 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14196 .REASON_SERVICE_IN_USE;
14197 app.adjSource = cr.binding.client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014198 app.adjSourceOom = clientAdj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070014199 app.adjTarget = s.name;
14200 }
14201 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14202 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14203 schedGroup = Process.THREAD_GROUP_DEFAULT;
14204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014205 }
14206 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014207 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
14208 ActivityRecord a = cr.activity;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014209 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014210 (a.visible || a.state == ActivityState.RESUMED
14211 || a.state == ActivityState.PAUSING)) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014212 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014213 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14214 schedGroup = Process.THREAD_GROUP_DEFAULT;
14215 }
14216 app.hidden = false;
14217 app.adjType = "service";
14218 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14219 .REASON_SERVICE_IN_USE;
14220 app.adjSource = a;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014221 app.adjSourceOom = adj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014222 app.adjTarget = s.name;
14223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014225 }
14226 }
14227 }
14228 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014229
Dianne Hackborn287952c2010-09-22 22:34:31 -070014230 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014231 // would like to avoid killing it unless it would prevent the current
14232 // application from running. By default we put the process in
14233 // with the rest of the background processes; as we scan through
14234 // its services we may bump it up from there.
14235 if (adj > hiddenAdj) {
14236 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014237 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014238 app.adjType = "bg-services";
14239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014240 }
14241
Dianne Hackborn7d608422011-08-07 16:24:18 -070014242 if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014243 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014244 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014245 while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014246 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014247 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014248 if (cpr.clients.size() != 0) {
14249 Iterator<ProcessRecord> kt = cpr.clients.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014250 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014251 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014252 if (client == app) {
14253 // Being our own client is not interesting.
14254 continue;
14255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014256 int myHiddenAdj = hiddenAdj;
14257 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014258 if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014259 myHiddenAdj = client.hiddenAdj;
14260 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014261 myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014262 }
14263 }
14264 int clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014265 client, myHiddenAdj, TOP_APP, true, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014266 if (adj > clientAdj) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014267 if (app.hasShownUi && app != mHomeProcess
14268 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014269 app.adjType = "bg-ui-provider";
14270 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014271 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
14272 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014273 app.adjType = "provider";
14274 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014275 if (!client.hidden) {
14276 app.hidden = false;
14277 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014278 if (client.keeping) {
14279 app.keeping = true;
14280 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014281 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14282 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014283 app.adjSource = client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014284 app.adjSourceOom = clientAdj;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014285 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014286 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014287 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14288 schedGroup = Process.THREAD_GROUP_DEFAULT;
14289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014290 }
14291 }
14292 // If the provider has external (non-framework) process
14293 // dependencies, ensure that its adjustment is at least
14294 // FOREGROUND_APP_ADJ.
14295 if (cpr.externals != 0) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014296 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
14297 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014298 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014299 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014300 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014301 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014302 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014303 }
14304 }
14305 }
14306 }
14307
14308 app.curRawAdj = adj;
14309
Joe Onorato8a9b2202010-02-26 18:56:32 -080014310 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014311 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14312 if (adj > app.maxAdj) {
14313 adj = app.maxAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014314 if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014315 schedGroup = Process.THREAD_GROUP_DEFAULT;
14316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014317 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014318 if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014319 app.keeping = true;
14320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014321
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014322 if (app.hasAboveClient) {
14323 // If this process has bound to any services with BIND_ABOVE_CLIENT,
14324 // then we need to drop its adjustment to be lower than the service's
14325 // in order to honor the request. We want to drop it by one adjustment
14326 // level... but there is special meaning applied to various levels so
14327 // we will skip some of them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014328 if (adj < ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014329 // System process will not get dropped, ever
Dianne Hackborn7d608422011-08-07 16:24:18 -070014330 } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
14331 adj = ProcessList.VISIBLE_APP_ADJ;
14332 } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
14333 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
14334 } else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14335 adj = ProcessList.HIDDEN_APP_MIN_ADJ;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014336 } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014337 adj++;
14338 }
14339 }
14340
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014341 if (adj == ProcessList.SERVICE_ADJ) {
14342 if (doingAll) {
14343 app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
14344 mNewNumServiceProcs++;
14345 }
14346 if (app.serviceb) {
14347 adj = ProcessList.SERVICE_B_ADJ;
14348 }
14349 } else {
14350 app.serviceb = false;
14351 }
14352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014353 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014354 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014355
14356 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070014357 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
14358 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014359 }
14360
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014361 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014362 }
14363
14364 /**
14365 * Ask a given process to GC right now.
14366 */
14367 final void performAppGcLocked(ProcessRecord app) {
14368 try {
14369 app.lastRequestedGc = SystemClock.uptimeMillis();
14370 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014371 if (app.reportLowMemory) {
14372 app.reportLowMemory = false;
14373 app.thread.scheduleLowMemory();
14374 } else {
14375 app.thread.processInBackground();
14376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014377 }
14378 } catch (Exception e) {
14379 // whatever.
14380 }
14381 }
14382
14383 /**
14384 * Returns true if things are idle enough to perform GCs.
14385 */
Josh Bartel7f208742010-02-25 11:01:44 -060014386 private final boolean canGcNowLocked() {
Christopher Tatef46723b2012-01-26 14:19:24 -080014387 boolean processingBroadcasts = false;
14388 for (BroadcastQueue q : mBroadcastQueues) {
14389 if (q.mParallelBroadcasts.size() != 0 || q.mOrderedBroadcasts.size() != 0) {
14390 processingBroadcasts = true;
14391 }
14392 }
14393 return !processingBroadcasts
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014394 && (mSleeping || (mMainStack.mResumedActivity != null &&
14395 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014396 }
14397
14398 /**
14399 * Perform GCs on all processes that are waiting for it, but only
14400 * if things are idle.
14401 */
14402 final void performAppGcsLocked() {
14403 final int N = mProcessesToGc.size();
14404 if (N <= 0) {
14405 return;
14406 }
Josh Bartel7f208742010-02-25 11:01:44 -060014407 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014408 while (mProcessesToGc.size() > 0) {
14409 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014410 if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014411 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14412 <= SystemClock.uptimeMillis()) {
14413 // To avoid spamming the system, we will GC processes one
14414 // at a time, waiting a few seconds between each.
14415 performAppGcLocked(proc);
14416 scheduleAppGcsLocked();
14417 return;
14418 } else {
14419 // It hasn't been long enough since we last GCed this
14420 // process... put it in the list to wait for its time.
14421 addProcessToGcListLocked(proc);
14422 break;
14423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014424 }
14425 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014426
14427 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014428 }
14429 }
14430
14431 /**
14432 * If all looks good, perform GCs on all processes waiting for them.
14433 */
14434 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014435 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014436 performAppGcsLocked();
14437 return;
14438 }
14439 // Still not idle, wait some more.
14440 scheduleAppGcsLocked();
14441 }
14442
14443 /**
14444 * Schedule the execution of all pending app GCs.
14445 */
14446 final void scheduleAppGcsLocked() {
14447 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014448
14449 if (mProcessesToGc.size() > 0) {
14450 // Schedule a GC for the time to the next process.
14451 ProcessRecord proc = mProcessesToGc.get(0);
14452 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14453
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014454 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014455 long now = SystemClock.uptimeMillis();
14456 if (when < (now+GC_TIMEOUT)) {
14457 when = now + GC_TIMEOUT;
14458 }
14459 mHandler.sendMessageAtTime(msg, when);
14460 }
14461 }
14462
14463 /**
14464 * Add a process to the array of processes waiting to be GCed. Keeps the
14465 * list in sorted order by the last GC time. The process can't already be
14466 * on the list.
14467 */
14468 final void addProcessToGcListLocked(ProcessRecord proc) {
14469 boolean added = false;
14470 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14471 if (mProcessesToGc.get(i).lastRequestedGc <
14472 proc.lastRequestedGc) {
14473 added = true;
14474 mProcessesToGc.add(i+1, proc);
14475 break;
14476 }
14477 }
14478 if (!added) {
14479 mProcessesToGc.add(0, proc);
14480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014481 }
14482
14483 /**
14484 * Set up to ask a process to GC itself. This will either do it
14485 * immediately, or put it on the list of processes to gc the next
14486 * time things are idle.
14487 */
14488 final void scheduleAppGcLocked(ProcessRecord app) {
14489 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014490 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014491 return;
14492 }
14493 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014494 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014495 scheduleAppGcsLocked();
14496 }
14497 }
14498
Dianne Hackborn287952c2010-09-22 22:34:31 -070014499 final void checkExcessivePowerUsageLocked(boolean doKills) {
14500 updateCpuStatsNow();
14501
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014502 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014503 boolean doWakeKills = doKills;
14504 boolean doCpuKills = doKills;
14505 if (mLastPowerCheckRealtime == 0) {
14506 doWakeKills = false;
14507 }
14508 if (mLastPowerCheckUptime == 0) {
14509 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014510 }
14511 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014512 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014513 }
14514 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014515 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
14516 final long curUptime = SystemClock.uptimeMillis();
14517 final long uptimeSince = curUptime - mLastPowerCheckUptime;
14518 mLastPowerCheckRealtime = curRealtime;
14519 mLastPowerCheckUptime = curUptime;
14520 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
14521 doWakeKills = false;
14522 }
14523 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
14524 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014525 }
14526 int i = mLruProcesses.size();
14527 while (i > 0) {
14528 i--;
14529 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014530 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014531 long wtime;
14532 synchronized (stats) {
14533 wtime = stats.getProcessWakeTime(app.info.uid,
14534 app.pid, curRealtime);
14535 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014536 long wtimeUsed = wtime - app.lastWakeTime;
14537 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
14538 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014539 StringBuilder sb = new StringBuilder(128);
14540 sb.append("Wake for ");
14541 app.toShortString(sb);
14542 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014543 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014544 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014545 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014546 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014547 sb.append((wtimeUsed*100)/realtimeSince);
14548 sb.append("%)");
14549 Slog.i(TAG, sb.toString());
14550 sb.setLength(0);
14551 sb.append("CPU for ");
14552 app.toShortString(sb);
14553 sb.append(": over ");
14554 TimeUtils.formatDuration(uptimeSince, sb);
14555 sb.append(" used ");
14556 TimeUtils.formatDuration(cputimeUsed, sb);
14557 sb.append(" (");
14558 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014559 sb.append("%)");
14560 Slog.i(TAG, sb.toString());
14561 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014562 // If a process has held a wake lock for more
14563 // than 50% of the time during this period,
14564 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070014565 if (doWakeKills && realtimeSince > 0
14566 && ((wtimeUsed*100)/realtimeSince) >= 50) {
14567 synchronized (stats) {
14568 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
14569 realtimeSince, wtimeUsed);
14570 }
14571 Slog.w(TAG, "Excessive wake lock in " + app.processName
14572 + " (pid " + app.pid + "): held " + wtimeUsed
14573 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014574 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14575 app.processName, app.setAdj, "excessive wake lock");
14576 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014577 } else if (doCpuKills && uptimeSince > 0
14578 && ((cputimeUsed*100)/uptimeSince) >= 50) {
14579 synchronized (stats) {
14580 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
14581 uptimeSince, cputimeUsed);
14582 }
14583 Slog.w(TAG, "Excessive CPU in " + app.processName
14584 + " (pid " + app.pid + "): used " + cputimeUsed
14585 + " during " + uptimeSince);
14586 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14587 app.processName, app.setAdj, "excessive cpu");
14588 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014589 } else {
14590 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014591 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014592 }
14593 }
14594 }
14595 }
14596
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014597 private final boolean updateOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014598 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014599 app.hiddenAdj = hiddenAdj;
14600
14601 if (app.thread == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014602 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014603 }
14604
Dianne Hackborn287952c2010-09-22 22:34:31 -070014605 final boolean wasKeeping = app.keeping;
14606
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014607 boolean success = true;
14608
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014609 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014610
Jeff Brown10e89712011-07-08 18:52:57 -070014611 if (app.curRawAdj != app.setRawAdj) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070014612 if (false) {
14613 // Removing for now. Forcing GCs is not so useful anymore
14614 // with Dalvik, and the new memory level hint facility is
14615 // better for what we need to do these days.
14616 if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
14617 && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
14618 // If this app is transitioning from foreground to
14619 // non-foreground, have it do a gc.
14620 scheduleAppGcLocked(app);
14621 } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14622 && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14623 // Likewise do a gc when an app is moving in to the
14624 // background (such as a service stopping).
14625 scheduleAppGcLocked(app);
14626 }
Jeff Brown10e89712011-07-08 18:52:57 -070014627 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014628
Jeff Brown10e89712011-07-08 18:52:57 -070014629 if (wasKeeping && !app.keeping) {
14630 // This app is no longer something we want to keep. Note
14631 // its current wake lock time to later know to kill it if
14632 // it is not behaving well.
14633 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
14634 synchronized (stats) {
14635 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
14636 app.pid, SystemClock.elapsedRealtime());
14637 }
14638 app.lastCpuTime = app.curCpuTime;
14639 }
14640
14641 app.setRawAdj = app.curRawAdj;
14642 }
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014643
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014644 if (app.curAdj != app.setAdj) {
14645 if (Process.setOomAdj(app.pid, app.curAdj)) {
Dianne Hackbornbbb09ac2011-11-30 11:31:29 -080014646 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014647 TAG, "Set " + app.pid + " " + app.processName +
14648 " adj " + app.curAdj + ": " + app.adjType);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014649 app.setAdj = app.curAdj;
Jeff Brown10e89712011-07-08 18:52:57 -070014650 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014651 success = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014652 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
Jeff Brown10e89712011-07-08 18:52:57 -070014653 }
14654 }
14655 if (app.setSchedGroup != app.curSchedGroup) {
14656 app.setSchedGroup = app.curSchedGroup;
14657 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
14658 "Setting process group of " + app.processName
14659 + " to " + app.curSchedGroup);
14660 if (app.waitingToKill != null &&
14661 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
14662 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
14663 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14664 app.processName, app.setAdj, app.waitingToKill);
14665 Process.killProcessQuiet(app.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014666 success = false;
Jeff Brown10e89712011-07-08 18:52:57 -070014667 } else {
14668 if (true) {
14669 long oldId = Binder.clearCallingIdentity();
14670 try {
14671 Process.setProcessGroup(app.pid, app.curSchedGroup);
14672 } catch (Exception e) {
14673 Slog.w(TAG, "Failed setting process group of " + app.pid
14674 + " to " + app.curSchedGroup);
14675 e.printStackTrace();
14676 } finally {
14677 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014678 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014679 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070014680 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014681 try {
Jeff Brown10e89712011-07-08 18:52:57 -070014682 app.thread.setSchedulingGroup(app.curSchedGroup);
14683 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014684 }
14685 }
14686 }
14687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014688 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014689 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014690 }
14691
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014692 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014693 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014694 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014695 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014696 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014697 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014698 }
14699 }
14700 return resumedActivity;
14701 }
14702
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014703 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014704 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014705 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14706 int curAdj = app.curAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014707 final boolean wasHidden = curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14708 && curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014709
14710 mAdjSeq++;
14711
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014712 boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014713 final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14714 && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014715 if (nowHidden != wasHidden) {
14716 // Changed to/from hidden state, so apps after it in the LRU
14717 // list may also be changed.
14718 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014719 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014720 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014721 }
14722
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014723 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014724 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014725 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14726
14727 if (false) {
14728 RuntimeException e = new RuntimeException();
14729 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014730 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014731 }
14732
14733 mAdjSeq++;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014734 mNewNumServiceProcs = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014735
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014736 // Let's determine how many processes we have running vs.
14737 // how many slots we have for background processes; we may want
14738 // to put multiple processes in a slot of there are enough of
14739 // them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014740 int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014741 int factor = (mLruProcesses.size()-4)/numSlots;
14742 if (factor < 1) factor = 1;
14743 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014744 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014745
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014746 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014747 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014748 int i = mLruProcesses.size();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014749 int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014750 while (i > 0) {
14751 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014752 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014753 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014754 updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
14755 if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014756 && app.curAdj == curHiddenAdj) {
14757 step++;
14758 if (step >= factor) {
14759 step = 0;
14760 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014761 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014762 }
14763 if (!app.killedBackground) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014764 if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014765 numHidden++;
14766 if (numHidden > mProcessLimit) {
14767 Slog.i(TAG, "No longer want " + app.processName
14768 + " (pid " + app.pid + "): hidden #" + numHidden);
14769 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14770 app.processName, app.setAdj, "too many background");
14771 app.killedBackground = true;
14772 Process.killProcessQuiet(app.pid);
Dianne Hackborn8633e682010-04-22 16:03:41 -070014773 }
14774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014775 }
14776 }
14777
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014778 mNumServiceProcs = mNewNumServiceProcs;
14779
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014780 // Now determine the memory trimming level of background processes.
14781 // Unfortunately we need to start at the back of the list to do this
14782 // properly. We only do this if the number of background apps we
14783 // are managing to keep around is less than half the maximum we desire;
14784 // if we are keeping a good number around, we'll let them use whatever
14785 // memory they want.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014786 if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014787 final int N = mLruProcesses.size();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014788 factor = numHidden/3;
14789 int minFactor = 2;
14790 if (mHomeProcess != null) minFactor++;
14791 if (mPreviousProcess != null) minFactor++;
14792 if (factor < minFactor) factor = minFactor;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014793 step = 0;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014794 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014795 for (i=0; i<N; i++) {
14796 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014797 if (app.curAdj >= ProcessList.HOME_APP_ADJ
14798 && app.curAdj != ProcessList.SERVICE_B_ADJ
14799 && !app.killedBackground) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014800 if (app.trimMemoryLevel < curLevel && app.thread != null) {
14801 try {
14802 app.thread.scheduleTrimMemory(curLevel);
14803 } catch (RemoteException e) {
14804 }
Dianne Hackborn77eaaf02011-12-05 18:05:31 -080014805 if (false) {
14806 // For now we won't do this; our memory trimming seems
14807 // to be good enough at this point that destroying
14808 // activities causes more harm than good.
14809 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
14810 && app != mHomeProcess && app != mPreviousProcess) {
14811 // For these apps we will also finish their activities
14812 // to help them free memory.
14813 mMainStack.destroyActivitiesLocked(app, false, "trim");
14814 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014815 }
14816 }
14817 app.trimMemoryLevel = curLevel;
14818 step++;
14819 if (step >= factor) {
14820 switch (curLevel) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014821 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
14822 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014823 break;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014824 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
14825 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014826 break;
14827 }
14828 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014829 } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014830 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014831 && app.thread != null) {
14832 try {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014833 app.thread.scheduleTrimMemory(
14834 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014835 } catch (RemoteException e) {
14836 }
14837 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014838 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014839 } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014840 && app.pendingUiClean) {
14841 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14842 && app.thread != null) {
14843 try {
14844 app.thread.scheduleTrimMemory(
14845 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14846 } catch (RemoteException e) {
14847 }
14848 }
14849 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14850 app.pendingUiClean = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014851 } else {
14852 app.trimMemoryLevel = 0;
14853 }
14854 }
14855 } else {
14856 final int N = mLruProcesses.size();
14857 for (i=0; i<N; i++) {
14858 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014859 if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014860 && app.pendingUiClean) {
14861 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14862 && app.thread != null) {
14863 try {
14864 app.thread.scheduleTrimMemory(
14865 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14866 } catch (RemoteException e) {
14867 }
14868 }
14869 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14870 app.pendingUiClean = false;
14871 } else {
14872 app.trimMemoryLevel = 0;
14873 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014874 }
14875 }
14876
14877 if (mAlwaysFinishActivities) {
Dianne Hackborn28695e02011-11-02 21:59:51 -070014878 mMainStack.destroyActivitiesLocked(null, false, "always-finish");
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014880 }
14881
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014882 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014883 synchronized (this) {
14884 int i;
14885
14886 // First remove any unused application processes whose package
14887 // has been removed.
14888 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14889 final ProcessRecord app = mRemovedProcesses.get(i);
14890 if (app.activities.size() == 0
14891 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014892 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014893 TAG, "Exiting empty application process "
14894 + app.processName + " ("
14895 + (app.thread != null ? app.thread.asBinder() : null)
14896 + ")\n");
14897 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070014898 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14899 app.processName, app.setAdj, "empty");
14900 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014901 } else {
14902 try {
14903 app.thread.scheduleExit();
14904 } catch (Exception e) {
14905 // Ignore exceptions.
14906 }
14907 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014908 cleanUpApplicationRecordLocked(app, false, true, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014909 mRemovedProcesses.remove(i);
14910
14911 if (app.persistent) {
14912 if (app.persistent) {
14913 addAppLocked(app.info);
14914 }
14915 }
14916 }
14917 }
14918
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014919 // Now update the oom adj for all processes.
14920 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014921 }
14922 }
14923
14924 /** This method sends the specified signal to each of the persistent apps */
14925 public void signalPersistentProcesses(int sig) throws RemoteException {
14926 if (sig != Process.SIGNAL_USR1) {
14927 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14928 }
14929
14930 synchronized (this) {
14931 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14932 != PackageManager.PERMISSION_GRANTED) {
14933 throw new SecurityException("Requires permission "
14934 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14935 }
14936
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014937 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14938 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014939 if (r.thread != null && r.persistent) {
14940 Process.sendSignal(r.pid, sig);
14941 }
14942 }
14943 }
14944 }
14945
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014946 private void stopProfilerLocked(ProcessRecord proc, String path, int profileType) {
14947 if (proc == null || proc == mProfileProc) {
14948 proc = mProfileProc;
14949 path = mProfileFile;
14950 profileType = mProfileType;
14951 clearProfilerLocked();
14952 }
14953 if (proc == null) {
14954 return;
14955 }
14956 try {
14957 proc.thread.profilerControl(false, path, null, profileType);
14958 } catch (RemoteException e) {
14959 throw new IllegalStateException("Process disappeared");
14960 }
14961 }
14962
14963 private void clearProfilerLocked() {
14964 if (mProfileFd != null) {
14965 try {
14966 mProfileFd.close();
14967 } catch (IOException e) {
14968 }
14969 }
14970 mProfileApp = null;
14971 mProfileProc = null;
14972 mProfileFile = null;
14973 mProfileType = 0;
14974 mAutoStopProfiler = false;
14975 }
14976
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014977 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070014978 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014979
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014980 try {
14981 synchronized (this) {
14982 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14983 // its own permission.
14984 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14985 != PackageManager.PERMISSION_GRANTED) {
14986 throw new SecurityException("Requires permission "
14987 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014988 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014989
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014990 if (start && fd == null) {
14991 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014992 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014993
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014994 ProcessRecord proc = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014995 if (process != null) {
14996 try {
14997 int pid = Integer.parseInt(process);
14998 synchronized (mPidsSelfLocked) {
14999 proc = mPidsSelfLocked.get(pid);
15000 }
15001 } catch (NumberFormatException e) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015002 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015003
15004 if (proc == null) {
15005 HashMap<String, SparseArray<ProcessRecord>> all
15006 = mProcessNames.getMap();
15007 SparseArray<ProcessRecord> procs = all.get(process);
15008 if (procs != null && procs.size() > 0) {
15009 proc = procs.valueAt(0);
15010 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015011 }
15012 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015013
15014 if (start && (proc == null || proc.thread == null)) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015015 throw new IllegalArgumentException("Unknown process: " + process);
15016 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015017
15018 if (start) {
15019 stopProfilerLocked(null, null, 0);
15020 setProfileApp(proc.info, proc.processName, path, fd, false);
15021 mProfileProc = proc;
15022 mProfileType = profileType;
15023 try {
15024 fd = fd.dup();
15025 } catch (IOException e) {
15026 fd = null;
15027 }
15028 proc.thread.profilerControl(start, path, fd, profileType);
15029 fd = null;
15030 mProfileFd = null;
15031 } else {
15032 stopProfilerLocked(proc, path, profileType);
15033 if (fd != null) {
15034 try {
15035 fd.close();
15036 } catch (IOException e) {
15037 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015038 }
15039 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070015040
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015041 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015042 }
15043 } catch (RemoteException e) {
15044 throw new IllegalStateException("Process disappeared");
15045 } finally {
15046 if (fd != null) {
15047 try {
15048 fd.close();
15049 } catch (IOException e) {
15050 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015051 }
15052 }
15053 }
Andy McFadden824c5102010-07-09 16:26:57 -070015054
15055 public boolean dumpHeap(String process, boolean managed,
15056 String path, ParcelFileDescriptor fd) throws RemoteException {
15057
15058 try {
15059 synchronized (this) {
15060 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
15061 // its own permission (same as profileControl).
15062 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
15063 != PackageManager.PERMISSION_GRANTED) {
15064 throw new SecurityException("Requires permission "
15065 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
15066 }
15067
15068 if (fd == null) {
15069 throw new IllegalArgumentException("null fd");
15070 }
15071
15072 ProcessRecord proc = null;
15073 try {
15074 int pid = Integer.parseInt(process);
15075 synchronized (mPidsSelfLocked) {
15076 proc = mPidsSelfLocked.get(pid);
15077 }
15078 } catch (NumberFormatException e) {
15079 }
15080
15081 if (proc == null) {
15082 HashMap<String, SparseArray<ProcessRecord>> all
15083 = mProcessNames.getMap();
15084 SparseArray<ProcessRecord> procs = all.get(process);
15085 if (procs != null && procs.size() > 0) {
15086 proc = procs.valueAt(0);
15087 }
15088 }
15089
15090 if (proc == null || proc.thread == null) {
15091 throw new IllegalArgumentException("Unknown process: " + process);
15092 }
15093
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080015094 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
15095 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070015096 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
15097 throw new SecurityException("Process not debuggable: " + proc);
15098 }
15099 }
15100
15101 proc.thread.dumpHeap(managed, path, fd);
15102 fd = null;
15103 return true;
15104 }
15105 } catch (RemoteException e) {
15106 throw new IllegalStateException("Process disappeared");
15107 } finally {
15108 if (fd != null) {
15109 try {
15110 fd.close();
15111 } catch (IOException e) {
15112 }
15113 }
15114 }
15115 }
15116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015117 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
15118 public void monitor() {
15119 synchronized (this) { }
15120 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080015121
15122 public void onCoreSettingsChange(Bundle settings) {
15123 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
15124 ProcessRecord processRecord = mLruProcesses.get(i);
15125 try {
15126 if (processRecord.thread != null) {
15127 processRecord.thread.setCoreSettings(settings);
15128 }
15129 } catch (RemoteException re) {
15130 /* ignore */
15131 }
15132 }
15133 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070015134
15135 // Multi-user methods
15136
15137 public boolean switchUser(int userid) {
15138 // TODO
15139 return true;
15140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015141}