blob: 1ec8a22d20b50c31a2100544a3f95f59613aa4e8 [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 Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
79import android.net.Uri;
80import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080081import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070083import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080086import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.FileUtils;
88import android.os.Handler;
89import android.os.IBinder;
90import android.os.IPermissionController;
91import android.os.Looper;
92import android.os.Message;
93import android.os.Parcel;
94import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070096import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.RemoteException;
98import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070099import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.SystemClock;
101import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.Config;
104import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800105import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800106import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.PrintWriterPrinter;
108import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700109import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.view.Gravity;
111import android.view.LayoutInflater;
112import android.view.View;
113import android.view.WindowManager;
114import android.view.WindowManagerPolicy;
115
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700116import java.io.BufferedInputStream;
117import java.io.BufferedOutputStream;
118import java.io.DataInputStream;
119import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.File;
121import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700122import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200125import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800126import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.PrintWriter;
128import java.lang.IllegalStateException;
129import java.lang.ref.WeakReference;
130import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700131import java.util.Collections;
132import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.HashMap;
134import java.util.HashSet;
135import java.util.Iterator;
136import java.util.List;
137import java.util.Locale;
138import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700139import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700140import java.util.concurrent.atomic.AtomicBoolean;
141import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700143public final class ActivityManagerService extends ActivityManagerNative
144 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final String TAG = "ActivityManager";
146 static final boolean DEBUG = false;
147 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
148 static final boolean DEBUG_SWITCH = localLOGV || false;
149 static final boolean DEBUG_TASKS = localLOGV || false;
150 static final boolean DEBUG_PAUSE = localLOGV || false;
151 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
152 static final boolean DEBUG_TRANSITION = localLOGV || false;
153 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700154 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700156 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_VISBILITY = localLOGV || false;
158 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700159 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800160 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700162 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700163 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700164 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700165 static final boolean DEBUG_POWER = localLOGV || false;
166 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 static final boolean VALIDATE_TOKENS = false;
168 static final boolean SHOW_ACTIVITY_START_TIME = true;
169
170 // Control over CPU and battery monitoring.
171 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
172 static final boolean MONITOR_CPU_USAGE = true;
173 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
174 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
175 static final boolean MONITOR_THREAD_CPU_USAGE = false;
176
Dianne Hackborn1655be42009-05-08 14:29:01 -0700177 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700178 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 private static final String SYSTEM_SECURE = "ro.secure";
181
182 // This is the maximum number of application processes we would like
183 // to have running. Due to the asynchronous nature of things, we can
184 // temporarily go beyond this limit.
185 static final int MAX_PROCESSES = 2;
186
187 // Set to false to leave processes running indefinitely, relying on
188 // the kernel killing them as resources are required.
189 static final boolean ENFORCE_PROCESS_LIMIT = false;
190
191 // This is the maximum number of activities that we would like to have
192 // running at a given time.
193 static final int MAX_ACTIVITIES = 20;
194
195 // Maximum number of recent tasks that we can remember.
196 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700197
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700198 // Amount of time after a call to stopAppSwitches() during which we will
199 // prevent further untrusted switches from happening.
200 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
Dianne Hackborn287952c2010-09-22 22:34:31 -0700212 // The rate at which we check for apps using excessive power -- 15 mins.
213 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
214
215 // The minimum sample duration we will allow before deciding we have
216 // enough data on wake locks to start killing things.
217 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
218
219 // The minimum sample duration we will allow before deciding we have
220 // enough data on CPU usage to start killing things.
221 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // How long we allow a receiver to run before giving up on it.
224 static final int BROADCAST_TIMEOUT = 10*1000;
225
226 // How long we wait for a service to finish executing.
227 static final int SERVICE_TIMEOUT = 20*1000;
228
229 // How long a service needs to be running until restarting its process
230 // is no longer considered to be a relaunch of the service.
231 static final int SERVICE_RESTART_DURATION = 5*1000;
232
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700233 // How long a service needs to be running until it will start back at
234 // SERVICE_RESTART_DURATION after being killed.
235 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
236
237 // Multiplying factor to increase restart duration time by, for each time
238 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
239 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
240
241 // The minimum amount of time between restarting services that we allow.
242 // That is, when multiple services are restarting, we won't allow each
243 // to restart less than this amount of time from the last one.
244 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Maximum amount of time for there to be no activity on a service before
247 // we consider it non-essential and allow its process to go on the
248 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700249 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250
251 // How long we wait until we timeout on key dispatching.
252 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
253
254 // The minimum time we allow between crashes, for us to consider this
255 // application to be bad and stop and its services and reject broadcasts.
256 static final int MIN_CRASH_INTERVAL = 60*1000;
257
258 // How long we wait until we timeout on key dispatching during instrumentation.
259 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
260
261 // OOM adjustments for processes in various states:
262
263 // This is a process without anything currently running in it. Definitely
264 // the first to go! Value set in system/rootdir/init.rc on startup.
265 // This value is initalized in the constructor, careful when refering to
266 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269 // This is a process only hosting activities that are not visible,
270 // so it can be killed without any disruption. Value set in
271 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 static int HIDDEN_APP_MIN_ADJ;
274
The Android Open Source Project4df24232009-03-05 14:34:35 -0800275 // This is a process holding the home application -- we want to try
276 // avoiding killing it, even if it would normally be in the background,
277 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800279
Christopher Tate6fa95972009-06-05 18:43:55 -0700280 // This is a process currently hosting a backup operation. Killing it
281 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 // This is a process holding a secondary server -- killing it will not
285 // have much of an impact as far as the user is concerned. Value set in
286 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700289 // This is a process with a heavy-weight application. It is in the
290 // background, but we want to try to avoid killing it. Value set in
291 // system/rootdir/init.rc on startup.
292 static final int HEAVY_WEIGHT_APP_ADJ;
293
294 // This is a process only hosting components that are perceptible to the
295 // user, and we really want to avoid killing them, but they are not
296 // immediately visible. An example is background music playback. Value set in
297 // system/rootdir/init.rc on startup.
298 static final int PERCEPTIBLE_APP_ADJ;
299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 // This is a process only hosting activities that are visible to the
301 // user, so we'd prefer they don't disappear. Value set in
302 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800303 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304
305 // This is the process running the current foreground app. We'd really
306 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 // This is a process running a core server, such as telephony. Definitely
310 // don't want to kill it, but doing so is not completely fatal.
311 static final int CORE_SERVER_ADJ = -12;
312
313 // The system process runs at the default adjustment.
314 static final int SYSTEM_ADJ = -16;
315
316 // Memory pages are 4K.
317 static final int PAGE_SIZE = 4*1024;
318
319 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800320 static final int EMPTY_APP_MEM;
321 static final int HIDDEN_APP_MEM;
322 static final int HOME_APP_MEM;
323 static final int BACKUP_APP_MEM;
324 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700325 static final int HEAVY_WEIGHT_APP_MEM;
326 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327 static final int VISIBLE_APP_MEM;
328 static final int FOREGROUND_APP_MEM;
329
330 // The minimum number of hidden apps we want to be able to keep around,
331 // without empty apps being able to push them out of memory.
332 static final int MIN_HIDDEN_APPS = 2;
333
Dianne Hackborn8633e682010-04-22 16:03:41 -0700334 // The maximum number of hidden processes we will keep around before
335 // killing them; this is just a control to not let us go too crazy with
336 // keeping around processes on devices with large amounts of RAM.
337 static final int MAX_HIDDEN_APPS = 15;
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700340 // been idle for less than 15 seconds.
341 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342
343 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700344 // been idle for less than 120 seconds.
345 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700347 static int getIntProp(String name, boolean allowZero) {
348 String str = SystemProperties.get(name);
349 if (str == null) {
350 throw new IllegalArgumentException("Property not defined: " + name);
351 }
352 int val = Integer.valueOf(str);
353 if (val == 0 && !allowZero) {
354 throw new IllegalArgumentException("Property must not be zero: " + name);
355 }
356 return val;
357 }
358
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800359 static {
360 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700361 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
362 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
363 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
364 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
365 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
366 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
367 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
368 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
369 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
370 // These days we use the last empty slot for hidden apps as well.
371 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
372 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
373 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
374 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
375 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
376 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
377 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
378 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
379 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
380 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382
Dan Egnor42471dd2010-01-07 17:25:22 -0800383 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
385 static final String[] EMPTY_STRING_ARRAY = new String[0];
386
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700387 public ActivityStack mMainStack;
388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700390 * Description of a request to start a new activity, which has been held
391 * due to app switches being disabled.
392 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700393 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700394 ActivityRecord r;
395 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700396 Uri[] grantedUriPermissions;
397 int grantedMode;
398 boolean onlyIfNeeded;
399 }
400
401 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
402 = new ArrayList<PendingActivityLaunch>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * Activity we have told the window manager to have key focus.
435 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700436 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * List of intents that were used to start the most recent tasks.
439 */
440 final ArrayList<TaskRecord> mRecentTasks
441 = new ArrayList<TaskRecord>();
442
443 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 * All of the applications we currently have running organized by name.
445 * The keys are strings of the application package name (as
446 * returned by the package manager), and the keys are ApplicationRecord
447 * objects.
448 */
449 final ProcessMap<ProcessRecord> mProcessNames
450 = new ProcessMap<ProcessRecord>();
451
452 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700453 * The currently running heavy-weight process, if any.
454 */
455 ProcessRecord mHeavyWeightProcess = null;
456
457 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 * The last time that various processes have crashed.
459 */
460 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
461
462 /**
463 * Set of applications that we consider to be bad, and will reject
464 * incoming broadcasts from (which the user has no control over).
465 * Processes are added to this set when they have crashed twice within
466 * a minimum amount of time; they are removed from it when they are
467 * later restarted (hopefully due to some user action). The value is the
468 * time it was added to the list.
469 */
470 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
471
472 /**
473 * All of the processes we currently have running organized by pid.
474 * The keys are the pid running the application.
475 *
476 * <p>NOTE: This object is protected by its own lock, NOT the global
477 * activity manager lock!
478 */
479 final SparseArray<ProcessRecord> mPidsSelfLocked
480 = new SparseArray<ProcessRecord>();
481
482 /**
483 * All of the processes that have been forced to be foreground. The key
484 * is the pid of the caller who requested it (we hold a death
485 * link on it).
486 */
487 abstract class ForegroundToken implements IBinder.DeathRecipient {
488 int pid;
489 IBinder token;
490 }
491 final SparseArray<ForegroundToken> mForegroundProcesses
492 = new SparseArray<ForegroundToken>();
493
494 /**
495 * List of records for processes that someone had tried to start before the
496 * system was ready. We don't start them at that point, but ensure they
497 * are started by the time booting is complete.
498 */
499 final ArrayList<ProcessRecord> mProcessesOnHold
500 = new ArrayList<ProcessRecord>();
501
502 /**
503 * List of records for processes that we have started and are waiting
504 * for them to call back. This is really only needed when running in
505 * single processes mode, in which case we do not have a unique pid for
506 * each process.
507 */
508 final ArrayList<ProcessRecord> mStartingProcesses
509 = new ArrayList<ProcessRecord>();
510
511 /**
512 * List of persistent applications that are in the process
513 * of being started.
514 */
515 final ArrayList<ProcessRecord> mPersistentStartingProcesses
516 = new ArrayList<ProcessRecord>();
517
518 /**
519 * Processes that are being forcibly torn down.
520 */
521 final ArrayList<ProcessRecord> mRemovedProcesses
522 = new ArrayList<ProcessRecord>();
523
524 /**
525 * List of running applications, sorted by recent usage.
526 * The first entry in the list is the least recently used.
527 * It contains ApplicationRecord objects. This list does NOT include
528 * any persistent application records (since we never want to exit them).
529 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800530 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 = new ArrayList<ProcessRecord>();
532
533 /**
534 * List of processes that should gc as soon as things are idle.
535 */
536 final ArrayList<ProcessRecord> mProcessesToGc
537 = new ArrayList<ProcessRecord>();
538
539 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800540 * This is the process holding what we currently consider to be
541 * the "home" activity.
542 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700543 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800544
545 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 * Set of PendingResultRecord objects that are currently active.
547 */
548 final HashSet mPendingResultRecords = new HashSet();
549
550 /**
551 * Set of IntentSenderRecord objects that are currently active.
552 */
553 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
554 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
555
556 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700557 * Fingerprints (String.hashCode()) of stack traces that we've
558 * already logged DropBox entries for. Guarded by itself. If
559 * something (rogue user app) forces this over
560 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
561 */
562 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
563 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
564
565 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700566 * Strict Mode background batched logging state.
567 *
568 * The string buffer is guarded by itself, and its lock is also
569 * used to determine if another batched write is already
570 * in-flight.
571 */
572 private final StringBuilder mStrictModeBuffer = new StringBuilder();
573
574 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700575 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
576 */
577 private boolean mPendingBroadcastTimeoutMessage;
578
579 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 * Intent broadcast that we have tried to start, but are
581 * waiting for its application's process to be created. We only
582 * need one (instead of a list) because we always process broadcasts
583 * one at a time, so no others can be started while waiting for this
584 * one.
585 */
586 BroadcastRecord mPendingBroadcast = null;
587
588 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700589 * The receiver index that is pending, to restart the broadcast if needed.
590 */
591 int mPendingBroadcastRecvIndex;
592
593 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 * Keeps track of all IIntentReceivers that have been registered for
595 * broadcasts. Hash keys are the receiver IBinder, hash value is
596 * a ReceiverList.
597 */
598 final HashMap mRegisteredReceivers = new HashMap();
599
600 /**
601 * Resolver for broadcast intents to registered receivers.
602 * Holds BroadcastFilter (subclass of IntentFilter).
603 */
604 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
605 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
606 @Override
607 protected boolean allowFilterResult(
608 BroadcastFilter filter, List<BroadcastFilter> dest) {
609 IBinder target = filter.receiverList.receiver.asBinder();
610 for (int i=dest.size()-1; i>=0; i--) {
611 if (dest.get(i).receiverList.receiver.asBinder() == target) {
612 return false;
613 }
614 }
615 return true;
616 }
617 };
618
619 /**
620 * State of all active sticky broadcasts. Keys are the action of the
621 * sticky Intent, values are an ArrayList of all broadcasted intents with
622 * that action (which should usually be one).
623 */
624 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
625 new HashMap<String, ArrayList<Intent>>();
626
627 /**
628 * All currently running services.
629 */
630 final HashMap<ComponentName, ServiceRecord> mServices =
631 new HashMap<ComponentName, ServiceRecord>();
632
633 /**
634 * All currently running services indexed by the Intent used to start them.
635 */
636 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
637 new HashMap<Intent.FilterComparison, ServiceRecord>();
638
639 /**
640 * All currently bound service connections. Keys are the IBinder of
641 * the client's IServiceConnection.
642 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700643 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
644 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645
646 /**
647 * List of services that we have been asked to start,
648 * but haven't yet been able to. It is used to hold start requests
649 * while waiting for their corresponding application thread to get
650 * going.
651 */
652 final ArrayList<ServiceRecord> mPendingServices
653 = new ArrayList<ServiceRecord>();
654
655 /**
656 * List of services that are scheduled to restart following a crash.
657 */
658 final ArrayList<ServiceRecord> mRestartingServices
659 = new ArrayList<ServiceRecord>();
660
661 /**
662 * List of services that are in the process of being stopped.
663 */
664 final ArrayList<ServiceRecord> mStoppingServices
665 = new ArrayList<ServiceRecord>();
666
667 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700668 * Backup/restore process management
669 */
670 String mBackupAppName = null;
671 BackupRecord mBackupTarget = null;
672
673 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 * List of PendingThumbnailsRecord objects of clients who are still
675 * waiting to receive all of the thumbnails for a task.
676 */
677 final ArrayList mPendingThumbnails = new ArrayList();
678
679 /**
680 * List of HistoryRecord objects that have been finished and must
681 * still report back to a pending thumbnail receiver.
682 */
683 final ArrayList mCancelledThumbnails = new ArrayList();
684
685 /**
686 * All of the currently running global content providers. Keys are a
687 * string containing the provider name and values are a
688 * ContentProviderRecord object containing the data about it. Note
689 * that a single provider may be published under multiple names, so
690 * there may be multiple entries here for a single one in mProvidersByClass.
691 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700692 final HashMap<String, ContentProviderRecord> mProvidersByName
693 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694
695 /**
696 * All of the currently running global content providers. Keys are a
697 * string containing the provider's implementation class and values are a
698 * ContentProviderRecord object containing the data about it.
699 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700700 final HashMap<String, ContentProviderRecord> mProvidersByClass
701 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702
703 /**
704 * List of content providers who have clients waiting for them. The
705 * application is currently being launched and the provider will be
706 * removed from this list once it is published.
707 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700708 final ArrayList<ContentProviderRecord> mLaunchingProviders
709 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 /**
712 * Global set of specific Uri permissions that have been granted.
713 */
714 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
715 = new SparseArray<HashMap<Uri, UriPermission>>();
716
717 /**
718 * Thread-local storage used to carry caller permissions over through
719 * indirect content-provider access.
720 * @see #ActivityManagerService.openContentUri()
721 */
722 private class Identity {
723 public int pid;
724 public int uid;
725
726 Identity(int _pid, int _uid) {
727 pid = _pid;
728 uid = _uid;
729 }
730 }
731 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
732
733 /**
734 * All information we have collected about the runtime performance of
735 * any user id that can impact battery performance.
736 */
737 final BatteryStatsService mBatteryStatsService;
738
739 /**
740 * information about component usage
741 */
742 final UsageStatsService mUsageStatsService;
743
744 /**
745 * Current configuration information. HistoryRecord objects are given
746 * a reference to this object to indicate which configuration they are
747 * currently running in, so this object must be kept immutable.
748 */
749 Configuration mConfiguration = new Configuration();
750
751 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800752 * Current sequencing integer of the configuration, for skipping old
753 * configurations.
754 */
755 int mConfigurationSeq = 0;
756
757 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700758 * Hardware-reported OpenGLES version.
759 */
760 final int GL_ES_VERSION;
761
762 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 * List of initialization arguments to pass to all processes when binding applications to them.
764 * For example, references to the commonly used services.
765 */
766 HashMap<String, IBinder> mAppBindArgs;
767
768 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700769 * Temporary to avoid allocations. Protected by main lock.
770 */
771 final StringBuilder mStringBuilder = new StringBuilder(256);
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * Used to control how we initialize the service.
775 */
776 boolean mStartRunning = false;
777 ComponentName mTopComponent;
778 String mTopAction;
779 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700780 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 boolean mSystemReady = false;
782 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700783 boolean mWaitingUpdate = false;
784 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700785 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700786 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 Context mContext;
789
790 int mFactoryTest;
791
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700792 boolean mCheckedForSetup;
793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700795 * The time at which we will allow normal application switches again,
796 * after a call to {@link #stopAppSwitches()}.
797 */
798 long mAppSwitchesAllowedTime;
799
800 /**
801 * This is set to true after the first switch after mAppSwitchesAllowedTime
802 * is set; any switches after that will clear the time.
803 */
804 boolean mDidAppSwitch;
805
806 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700807 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700808 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 long mLastPowerCheckRealtime;
810
811 /**
812 * Last time (in uptime) at which we checked for power usage.
813 */
814 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700815
816 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 * Set while we are wanting to sleep, to prevent any
818 * activities from being started/resumed.
819 */
820 boolean mSleeping = false;
821
822 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700823 * Set if we are shutting down the system, similar to sleeping.
824 */
825 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826
827 /**
828 * Task identifier that activities are currently being started
829 * in. Incremented each time a new task is created.
830 * todo: Replace this with a TokenSpace class that generates non-repeating
831 * integers that won't wrap.
832 */
833 int mCurTask = 1;
834
835 /**
836 * Current sequence id for oom_adj computation traversal.
837 */
838 int mAdjSeq = 0;
839
840 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700841 * Current sequence id for process LRU updating.
842 */
843 int mLruSeq = 0;
844
845 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
847 * is set, indicating the user wants processes started in such a way
848 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
849 * running in each process (thus no pre-initialized process, etc).
850 */
851 boolean mSimpleProcessManagement = false;
852
853 /**
854 * System monitoring: number of processes that died since the last
855 * N procs were started.
856 */
857 int[] mProcDeaths = new int[20];
858
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700859 /**
860 * This is set if we had to do a delayed dexopt of an app before launching
861 * it, to increasing the ANR timeouts in that case.
862 */
863 boolean mDidDexOpt;
864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 String mDebugApp = null;
866 boolean mWaitForDebugger = false;
867 boolean mDebugTransient = false;
868 String mOrigDebugApp = null;
869 boolean mOrigWaitForDebugger = false;
870 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700871 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 final RemoteCallbackList<IActivityWatcher> mWatchers
874 = new RemoteCallbackList<IActivityWatcher>();
875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 /**
877 * Callback of last caller to {@link #requestPss}.
878 */
879 Runnable mRequestPssCallback;
880
881 /**
882 * Remaining processes for which we are waiting results from the last
883 * call to {@link #requestPss}.
884 */
885 final ArrayList<ProcessRecord> mRequestPssList
886 = new ArrayList<ProcessRecord>();
887
888 /**
889 * Runtime statistics collection thread. This object's lock is used to
890 * protect all related state.
891 */
892 final Thread mProcessStatsThread;
893
894 /**
895 * Used to collect process stats when showing not responding dialog.
896 * Protected by mProcessStatsThread.
897 */
898 final ProcessStats mProcessStats = new ProcessStats(
899 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700900 final AtomicLong mLastCpuTime = new AtomicLong(0);
901 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 long mLastWriteTime = 0;
904
905 /**
906 * Set to true after the system has finished booting.
907 */
908 boolean mBooted = false;
909
910 int mProcessLimit = 0;
911
912 WindowManagerService mWindowManager;
913
914 static ActivityManagerService mSelf;
915 static ActivityThread mSystemThread;
916
917 private final class AppDeathRecipient implements IBinder.DeathRecipient {
918 final ProcessRecord mApp;
919 final int mPid;
920 final IApplicationThread mAppThread;
921
922 AppDeathRecipient(ProcessRecord app, int pid,
923 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800924 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 TAG, "New death recipient " + this
926 + " for thread " + thread.asBinder());
927 mApp = app;
928 mPid = pid;
929 mAppThread = thread;
930 }
931
932 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800933 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 TAG, "Death received in " + this
935 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 synchronized(ActivityManagerService.this) {
937 appDiedLocked(mApp, mPid, mAppThread);
938 }
939 }
940 }
941
942 static final int SHOW_ERROR_MSG = 1;
943 static final int SHOW_NOT_RESPONDING_MSG = 2;
944 static final int SHOW_FACTORY_ERROR_MSG = 3;
945 static final int UPDATE_CONFIGURATION_MSG = 4;
946 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
947 static final int WAIT_FOR_DEBUGGER_MSG = 6;
948 static final int BROADCAST_INTENT_MSG = 7;
949 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 static final int SERVICE_TIMEOUT_MSG = 12;
951 static final int UPDATE_TIME_ZONE = 13;
952 static final int SHOW_UID_ERROR_MSG = 14;
953 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700955 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700956 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800957 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700958 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
959 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700960 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700961 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700962 static final int CLEAR_DNS_CACHE = 28;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963
964 AlertDialog mUidAlert;
965
966 final Handler mHandler = new Handler() {
967 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800968 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 //}
970
971 public void handleMessage(Message msg) {
972 switch (msg.what) {
973 case SHOW_ERROR_MSG: {
974 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 synchronized (ActivityManagerService.this) {
976 ProcessRecord proc = (ProcessRecord)data.get("app");
977 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800978 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 return;
980 }
981 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700982 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800983 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 d.show();
985 proc.crashDialog = d;
986 } else {
987 // The device is asleep, so just pretend that the user
988 // saw a crash dialog and hit "force quit".
989 res.set(0);
990 }
991 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700992
993 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 } break;
995 case SHOW_NOT_RESPONDING_MSG: {
996 synchronized (ActivityManagerService.this) {
997 HashMap data = (HashMap) msg.obj;
998 ProcessRecord proc = (ProcessRecord)data.get("app");
999 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001000 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 return;
1002 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001003
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001004 Intent intent = new Intent("android.intent.action.ANR");
1005 if (!mProcessesReady) {
1006 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1007 }
1008 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001009 null, null, 0, null, null, null,
1010 false, false, MY_PID, Process.SYSTEM_UID);
1011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001013 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 d.show();
1015 proc.anrDialog = d;
1016 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001017
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001018 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001020 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1021 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1022 synchronized (ActivityManagerService.this) {
1023 ProcessRecord proc = (ProcessRecord) data.get("app");
1024 if (proc == null) {
1025 Slog.e(TAG, "App not found when showing strict mode dialog.");
1026 break;
1027 }
1028 if (proc.crashDialog != null) {
1029 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1030 return;
1031 }
1032 AppErrorResult res = (AppErrorResult) data.get("result");
1033 if (!mSleeping && !mShuttingDown) {
1034 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1035 d.show();
1036 proc.crashDialog = d;
1037 } else {
1038 // The device is asleep, so just pretend that the user
1039 // saw a crash dialog and hit "force quit".
1040 res.set(0);
1041 }
1042 }
1043 ensureBootCompleted();
1044 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 case SHOW_FACTORY_ERROR_MSG: {
1046 Dialog d = new FactoryErrorDialog(
1047 mContext, msg.getData().getCharSequence("msg"));
1048 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001049 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 } break;
1051 case UPDATE_CONFIGURATION_MSG: {
1052 final ContentResolver resolver = mContext.getContentResolver();
1053 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1054 } break;
1055 case GC_BACKGROUND_PROCESSES_MSG: {
1056 synchronized (ActivityManagerService.this) {
1057 performAppGcsIfAppropriateLocked();
1058 }
1059 } break;
1060 case WAIT_FOR_DEBUGGER_MSG: {
1061 synchronized (ActivityManagerService.this) {
1062 ProcessRecord app = (ProcessRecord)msg.obj;
1063 if (msg.arg1 != 0) {
1064 if (!app.waitedForDebugger) {
1065 Dialog d = new AppWaitingForDebuggerDialog(
1066 ActivityManagerService.this,
1067 mContext, app);
1068 app.waitDialog = d;
1069 app.waitedForDebugger = true;
1070 d.show();
1071 }
1072 } else {
1073 if (app.waitDialog != null) {
1074 app.waitDialog.dismiss();
1075 app.waitDialog = null;
1076 }
1077 }
1078 }
1079 } break;
1080 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001081 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 TAG, "Received BROADCAST_INTENT_MSG");
1083 processNextBroadcast(true);
1084 } break;
1085 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001086 synchronized (ActivityManagerService.this) {
1087 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001091 if (mDidDexOpt) {
1092 mDidDexOpt = false;
1093 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1094 nmsg.obj = msg.obj;
1095 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1096 return;
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 serviceTimeout((ProcessRecord)msg.obj);
1099 } break;
1100 case UPDATE_TIME_ZONE: {
1101 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001102 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1103 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 if (r.thread != null) {
1105 try {
1106 r.thread.updateTimeZone();
1107 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001108 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 }
1110 }
1111 }
1112 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001113 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001114 case CLEAR_DNS_CACHE: {
1115 synchronized (ActivityManagerService.this) {
1116 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1117 ProcessRecord r = mLruProcesses.get(i);
1118 if (r.thread != null) {
1119 try {
1120 r.thread.clearDnsCache();
1121 } catch (RemoteException ex) {
1122 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1123 }
1124 }
1125 }
1126 }
1127 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 case SHOW_UID_ERROR_MSG: {
1129 // XXX This is a temporary dialog, no need to localize.
1130 AlertDialog d = new BaseErrorDialog(mContext);
1131 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1132 d.setCancelable(false);
1133 d.setTitle("System UIDs Inconsistent");
1134 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 +02001135 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1137 mUidAlert = d;
1138 d.show();
1139 } break;
1140 case IM_FEELING_LUCKY_MSG: {
1141 if (mUidAlert != null) {
1142 mUidAlert.dismiss();
1143 mUidAlert = null;
1144 }
1145 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001147 if (mDidDexOpt) {
1148 mDidDexOpt = false;
1149 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1150 nmsg.obj = msg.obj;
1151 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1152 return;
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 ProcessRecord app = (ProcessRecord)msg.obj;
1155 synchronized (ActivityManagerService.this) {
1156 processStartTimedOutLocked(app);
1157 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001158 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001159 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1160 synchronized (ActivityManagerService.this) {
1161 doPendingActivityLaunchesLocked(true);
1162 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001163 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001164 case KILL_APPLICATION_MSG: {
1165 synchronized (ActivityManagerService.this) {
1166 int uid = msg.arg1;
1167 boolean restart = (msg.arg2 == 1);
1168 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001169 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001170 }
1171 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001172 case FINALIZE_PENDING_INTENT_MSG: {
1173 ((PendingIntentRecord)msg.obj).completeFinalize();
1174 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001175 case POST_HEAVY_NOTIFICATION_MSG: {
1176 INotificationManager inm = NotificationManager.getService();
1177 if (inm == null) {
1178 return;
1179 }
1180
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001181 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001182 ProcessRecord process = root.app;
1183 if (process == null) {
1184 return;
1185 }
1186
1187 try {
1188 Context context = mContext.createPackageContext(process.info.packageName, 0);
1189 String text = mContext.getString(R.string.heavy_weight_notification,
1190 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1191 Notification notification = new Notification();
1192 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1193 notification.when = 0;
1194 notification.flags = Notification.FLAG_ONGOING_EVENT;
1195 notification.tickerText = text;
1196 notification.defaults = 0; // please be quiet
1197 notification.sound = null;
1198 notification.vibrate = null;
1199 notification.setLatestEventInfo(context, text,
1200 mContext.getText(R.string.heavy_weight_notification_detail),
1201 PendingIntent.getActivity(mContext, 0, root.intent,
1202 PendingIntent.FLAG_CANCEL_CURRENT));
1203
1204 try {
1205 int[] outId = new int[1];
1206 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1207 notification, outId);
1208 } catch (RuntimeException e) {
1209 Slog.w(ActivityManagerService.TAG,
1210 "Error showing notification for heavy-weight app", e);
1211 } catch (RemoteException e) {
1212 }
1213 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001214 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001215 }
1216 } break;
1217 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1218 INotificationManager inm = NotificationManager.getService();
1219 if (inm == null) {
1220 return;
1221 }
1222 try {
1223 inm.cancelNotification("android",
1224 R.string.heavy_weight_notification);
1225 } catch (RuntimeException e) {
1226 Slog.w(ActivityManagerService.TAG,
1227 "Error canceling notification for service", e);
1228 } catch (RemoteException e) {
1229 }
1230 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001231 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1232 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001233 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001234 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001235 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1236 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001237 }
1238 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240 }
1241 };
1242
1243 public static void setSystemProcess() {
1244 try {
1245 ActivityManagerService m = mSelf;
1246
1247 ServiceManager.addService("activity", m);
1248 ServiceManager.addService("meminfo", new MemBinder(m));
1249 if (MONITOR_CPU_USAGE) {
1250 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 ServiceManager.addService("permission", new PermissionController(m));
1253
1254 ApplicationInfo info =
1255 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001256 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001257 mSystemThread.installSystemApplicationInfo(info);
1258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 synchronized (mSelf) {
1260 ProcessRecord app = mSelf.newProcessRecordLocked(
1261 mSystemThread.getApplicationThread(), info,
1262 info.processName);
1263 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001264 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 app.maxAdj = SYSTEM_ADJ;
1266 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1267 synchronized (mSelf.mPidsSelfLocked) {
1268 mSelf.mPidsSelfLocked.put(app.pid, app);
1269 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001270 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 }
1272 } catch (PackageManager.NameNotFoundException e) {
1273 throw new RuntimeException(
1274 "Unable to find android system package", e);
1275 }
1276 }
1277
1278 public void setWindowManager(WindowManagerService wm) {
1279 mWindowManager = wm;
1280 }
1281
1282 public static final Context main(int factoryTest) {
1283 AThread thr = new AThread();
1284 thr.start();
1285
1286 synchronized (thr) {
1287 while (thr.mService == null) {
1288 try {
1289 thr.wait();
1290 } catch (InterruptedException e) {
1291 }
1292 }
1293 }
1294
1295 ActivityManagerService m = thr.mService;
1296 mSelf = m;
1297 ActivityThread at = ActivityThread.systemMain();
1298 mSystemThread = at;
1299 Context context = at.getSystemContext();
1300 m.mContext = context;
1301 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001302 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303
1304 m.mBatteryStatsService.publish(context);
1305 m.mUsageStatsService.publish(context);
1306
1307 synchronized (thr) {
1308 thr.mReady = true;
1309 thr.notifyAll();
1310 }
1311
1312 m.startRunning(null, null, null, null);
1313
1314 return context;
1315 }
1316
1317 public static ActivityManagerService self() {
1318 return mSelf;
1319 }
1320
1321 static class AThread extends Thread {
1322 ActivityManagerService mService;
1323 boolean mReady = false;
1324
1325 public AThread() {
1326 super("ActivityManager");
1327 }
1328
1329 public void run() {
1330 Looper.prepare();
1331
1332 android.os.Process.setThreadPriority(
1333 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001334 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335
1336 ActivityManagerService m = new ActivityManagerService();
1337
1338 synchronized (this) {
1339 mService = m;
1340 notifyAll();
1341 }
1342
1343 synchronized (this) {
1344 while (!mReady) {
1345 try {
1346 wait();
1347 } catch (InterruptedException e) {
1348 }
1349 }
1350 }
1351
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001352 // For debug builds, log event loop stalls to dropbox for analysis.
1353 if (StrictMode.conditionallyEnableDebugLogging()) {
1354 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1355 }
1356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 Looper.loop();
1358 }
1359 }
1360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 static class MemBinder extends Binder {
1362 ActivityManagerService mActivityManagerService;
1363 MemBinder(ActivityManagerService activityManagerService) {
1364 mActivityManagerService = activityManagerService;
1365 }
1366
1367 @Override
1368 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1369 ActivityManagerService service = mActivityManagerService;
1370 ArrayList<ProcessRecord> procs;
1371 synchronized (mActivityManagerService) {
1372 if (args != null && args.length > 0
1373 && args[0].charAt(0) != '-') {
1374 procs = new ArrayList<ProcessRecord>();
1375 int pid = -1;
1376 try {
1377 pid = Integer.parseInt(args[0]);
1378 } catch (NumberFormatException e) {
1379
1380 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001381 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1382 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 if (proc.pid == pid) {
1384 procs.add(proc);
1385 } else if (proc.processName.equals(args[0])) {
1386 procs.add(proc);
1387 }
1388 }
1389 if (procs.size() <= 0) {
1390 pw.println("No process found for: " + args[0]);
1391 return;
1392 }
1393 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001394 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396 }
1397 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1398 }
1399 }
1400
1401 static class CpuBinder extends Binder {
1402 ActivityManagerService mActivityManagerService;
1403 CpuBinder(ActivityManagerService activityManagerService) {
1404 mActivityManagerService = activityManagerService;
1405 }
1406
1407 @Override
1408 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1409 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001410 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1411 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1412 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 }
1414 }
1415 }
1416
1417 private ActivityManagerService() {
1418 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1419 if (v != null && Integer.getInteger(v) != 0) {
1420 mSimpleProcessManagement = true;
1421 }
1422 v = System.getenv("ANDROID_DEBUG_APP");
1423 if (v != null) {
1424 mSimpleProcessManagement = true;
1425 }
1426
Joe Onorato8a9b2202010-02-26 18:56:32 -08001427 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 File dataDir = Environment.getDataDirectory();
1430 File systemDir = new File(dataDir, "system");
1431 systemDir.mkdirs();
1432 mBatteryStatsService = new BatteryStatsService(new File(
1433 systemDir, "batterystats.bin").toString());
1434 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001435 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001436 mOnBattery = DEBUG_POWER ? true
1437 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001438 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001440 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001441 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442
Jack Palevichb90d28c2009-07-22 15:35:24 -07001443 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1444 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1445
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001446 mConfiguration.setToDefaults();
1447 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 mProcessStats.init();
1449
1450 // Add ourself to the Watchdog monitors.
1451 Watchdog.getInstance().addMonitor(this);
1452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 mProcessStatsThread = new Thread("ProcessStats") {
1454 public void run() {
1455 while (true) {
1456 try {
1457 try {
1458 synchronized(this) {
1459 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001460 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001462 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 // + ", write delay=" + nextWriteDelay);
1464 if (nextWriteDelay < nextCpuDelay) {
1465 nextCpuDelay = nextWriteDelay;
1466 }
1467 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001468 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 this.wait(nextCpuDelay);
1470 }
1471 }
1472 } catch (InterruptedException e) {
1473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 updateCpuStatsNow();
1475 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 }
1478 }
1479 }
1480 };
1481 mProcessStatsThread.start();
1482 }
1483
1484 @Override
1485 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1486 throws RemoteException {
1487 try {
1488 return super.onTransact(code, data, reply, flags);
1489 } catch (RuntimeException e) {
1490 // The activity manager only throws security exceptions, so let's
1491 // log all others.
1492 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001493 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 }
1495 throw e;
1496 }
1497 }
1498
1499 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001500 final long now = SystemClock.uptimeMillis();
1501 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1502 return;
1503 }
1504 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1505 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 mProcessStatsThread.notify();
1507 }
1508 }
1509 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 void updateCpuStatsNow() {
1512 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001513 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 final long now = SystemClock.uptimeMillis();
1515 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001518 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1519 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 haveNewCpuStats = true;
1521 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001522 //Slog.i(TAG, mProcessStats.printCurrentState());
1523 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 // + mProcessStats.getTotalCpuPercent() + "%");
1525
Joe Onorato8a9b2202010-02-26 18:56:32 -08001526 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 if ("true".equals(SystemProperties.get("events.cpu"))) {
1528 int user = mProcessStats.getLastUserTime();
1529 int system = mProcessStats.getLastSystemTime();
1530 int iowait = mProcessStats.getLastIoWaitTime();
1531 int irq = mProcessStats.getLastIrqTime();
1532 int softIrq = mProcessStats.getLastSoftIrqTime();
1533 int idle = mProcessStats.getLastIdleTime();
1534
1535 int total = user + system + iowait + irq + softIrq + idle;
1536 if (total == 0) total = 1;
1537
Doug Zongker2bec3d42009-12-04 12:52:44 -08001538 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 ((user+system+iowait+irq+softIrq) * 100) / total,
1540 (user * 100) / total,
1541 (system * 100) / total,
1542 (iowait * 100) / total,
1543 (irq * 100) / total,
1544 (softIrq * 100) / total);
1545 }
1546 }
1547
Amith Yamasanie43530a2009-08-21 13:11:37 -07001548 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001549 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001550 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 synchronized(mPidsSelfLocked) {
1552 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001553 if (mOnBattery) {
1554 int perc = bstats.startAddingCpuLocked();
1555 int totalUTime = 0;
1556 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001557 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001559 ProcessStats.Stats st = mProcessStats.getStats(i);
1560 if (!st.working) {
1561 continue;
1562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001564 int otherUTime = (st.rel_utime*perc)/100;
1565 int otherSTime = (st.rel_stime*perc)/100;
1566 totalUTime += otherUTime;
1567 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 if (pr != null) {
1569 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001570 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1571 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001572 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001573 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001574 } else {
1575 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001576 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001577 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001578 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1579 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001580 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 }
1583 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001584 bstats.finishAddingCpuLocked(perc, totalUTime,
1585 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 }
1587 }
1588 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1591 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001592 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 }
1594 }
1595 }
1596 }
1597
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 @Override
1599 public void batteryNeedsCpuUpdate() {
1600 updateCpuStatsNow();
1601 }
1602
1603 @Override
1604 public void batteryPowerChanged(boolean onBattery) {
1605 // When plugging in, update the CPU stats first before changing
1606 // the plug state.
1607 updateCpuStatsNow();
1608 synchronized (this) {
1609 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001610 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001611 }
1612 }
1613 }
1614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 /**
1616 * Initialize the application bind args. These are passed to each
1617 * process when the bindApplication() IPC is sent to the process. They're
1618 * lazily setup to make sure the services are running when they're asked for.
1619 */
1620 private HashMap<String, IBinder> getCommonServicesLocked() {
1621 if (mAppBindArgs == null) {
1622 mAppBindArgs = new HashMap<String, IBinder>();
1623
1624 // Setup the application init args
1625 mAppBindArgs.put("package", ServiceManager.getService("package"));
1626 mAppBindArgs.put("window", ServiceManager.getService("window"));
1627 mAppBindArgs.put(Context.ALARM_SERVICE,
1628 ServiceManager.getService(Context.ALARM_SERVICE));
1629 }
1630 return mAppBindArgs;
1631 }
1632
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001633 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 if (mFocusedActivity != r) {
1635 mFocusedActivity = r;
1636 mWindowManager.setFocusedApp(r, true);
1637 }
1638 }
1639
Dianne Hackborn906497c2010-05-10 15:57:38 -07001640 private final void updateLruProcessInternalLocked(ProcessRecord app,
1641 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001643 int lrui = mLruProcesses.indexOf(app);
1644 if (lrui >= 0) mLruProcesses.remove(lrui);
1645
1646 int i = mLruProcesses.size()-1;
1647 int skipTop = 0;
1648
Dianne Hackborn906497c2010-05-10 15:57:38 -07001649 app.lruSeq = mLruSeq;
1650
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001651 // compute the new weight for this process.
1652 if (updateActivityTime) {
1653 app.lastActivityTime = SystemClock.uptimeMillis();
1654 }
1655 if (app.activities.size() > 0) {
1656 // If this process has activities, we more strongly want to keep
1657 // it around.
1658 app.lruWeight = app.lastActivityTime;
1659 } else if (app.pubProviders.size() > 0) {
1660 // If this process contains content providers, we want to keep
1661 // it a little more strongly.
1662 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1663 // Also don't let it kick out the first few "real" hidden processes.
1664 skipTop = MIN_HIDDEN_APPS;
1665 } else {
1666 // If this process doesn't have activities, we less strongly
1667 // want to keep it around, and generally want to avoid getting
1668 // in front of any very recently used activities.
1669 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1670 // Also don't let it kick out the first few "real" hidden processes.
1671 skipTop = MIN_HIDDEN_APPS;
1672 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001673
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001674 while (i >= 0) {
1675 ProcessRecord p = mLruProcesses.get(i);
1676 // If this app shouldn't be in front of the first N background
1677 // apps, then skip over that many that are currently hidden.
1678 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1679 skipTop--;
1680 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001681 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001682 mLruProcesses.add(i+1, app);
1683 break;
1684 }
1685 i--;
1686 }
1687 if (i < 0) {
1688 mLruProcesses.add(0, app);
1689 }
1690
Dianne Hackborn906497c2010-05-10 15:57:38 -07001691 // If the app is currently using a content provider or service,
1692 // bump those processes as well.
1693 if (app.connections.size() > 0) {
1694 for (ConnectionRecord cr : app.connections) {
1695 if (cr.binding != null && cr.binding.service != null
1696 && cr.binding.service.app != null
1697 && cr.binding.service.app.lruSeq != mLruSeq) {
1698 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1699 updateActivityTime, i+1);
1700 }
1701 }
1702 }
1703 if (app.conProviders.size() > 0) {
1704 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1705 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1706 updateLruProcessInternalLocked(cpr.app, oomAdj,
1707 updateActivityTime, i+1);
1708 }
1709 }
1710 }
1711
Joe Onorato8a9b2202010-02-26 18:56:32 -08001712 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 if (oomAdj) {
1714 updateOomAdjLocked();
1715 }
1716 }
1717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001718 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001719 boolean oomAdj, boolean updateActivityTime) {
1720 mLruSeq++;
1721 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1722 }
1723
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001724 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 String processName, int uid) {
1726 if (uid == Process.SYSTEM_UID) {
1727 // The system gets to run in any process. If there are multiple
1728 // processes with the same uid, just pick the first (this
1729 // should never happen).
1730 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1731 processName);
1732 return procs != null ? procs.valueAt(0) : null;
1733 }
1734 ProcessRecord proc = mProcessNames.get(processName, uid);
1735 return proc;
1736 }
1737
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001738 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001739 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001740 try {
1741 if (pm.performDexOpt(packageName)) {
1742 mDidDexOpt = true;
1743 }
1744 } catch (RemoteException e) {
1745 }
1746 }
1747
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001748 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 int transit = mWindowManager.getPendingAppTransition();
1750 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1751 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1752 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1753 }
1754
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001755 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001757 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1759 // We don't have to do anything more if:
1760 // (1) There is an existing application record; and
1761 // (2) The caller doesn't think it is dead, OR there is no thread
1762 // object attached to it so we know it couldn't have crashed; and
1763 // (3) There is a pid assigned to it, so it is either starting or
1764 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001765 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 + " app=" + app + " knownToBeDead=" + knownToBeDead
1767 + " thread=" + (app != null ? app.thread : null)
1768 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001769 if (app != null && app.pid > 0) {
1770 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001771 // We already have the app running, or are waiting for it to
1772 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001773 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001774 return app;
1775 } else {
1776 // An application record is attached to a previous process,
1777 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001778 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001779 handleAppDiedLocked(app, true);
1780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 String hostingNameStr = hostingName != null
1784 ? hostingName.flattenToShortString() : null;
1785
1786 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1787 // If we are in the background, then check to see if this process
1788 // is bad. If so, we will just silently fail.
1789 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001790 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1791 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 return null;
1793 }
1794 } else {
1795 // When the user is explicitly starting a process, then clear its
1796 // crash count so that we won't make it bad until they see at
1797 // least one crash dialog again, and make the process good again
1798 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001799 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1800 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 mProcessCrashTimes.remove(info.processName, info.uid);
1802 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001803 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 info.processName);
1805 mBadProcesses.remove(info.processName, info.uid);
1806 if (app != null) {
1807 app.bad = false;
1808 }
1809 }
1810 }
1811
1812 if (app == null) {
1813 app = newProcessRecordLocked(null, info, processName);
1814 mProcessNames.put(processName, info.uid, app);
1815 } else {
1816 // If this is a new package in the process, add the package to the list
1817 app.addPackage(info.packageName);
1818 }
1819
1820 // If the system is not ready yet, then hold off on starting this
1821 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001822 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001823 && !isAllowedWhileBooting(info)
1824 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 if (!mProcessesOnHold.contains(app)) {
1826 mProcessesOnHold.add(app);
1827 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001828 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 return app;
1830 }
1831
1832 startProcessLocked(app, hostingType, hostingNameStr);
1833 return (app.pid != 0) ? app : null;
1834 }
1835
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001836 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1837 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1838 }
1839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 private final void startProcessLocked(ProcessRecord app,
1841 String hostingType, String hostingNameStr) {
1842 if (app.pid > 0 && app.pid != MY_PID) {
1843 synchronized (mPidsSelfLocked) {
1844 mPidsSelfLocked.remove(app.pid);
1845 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1846 }
1847 app.pid = 0;
1848 }
1849
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001850 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1851 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 mProcessesOnHold.remove(app);
1853
1854 updateCpuStats();
1855
1856 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1857 mProcDeaths[0] = 0;
1858
1859 try {
1860 int uid = app.info.uid;
1861 int[] gids = null;
1862 try {
1863 gids = mContext.getPackageManager().getPackageGids(
1864 app.info.packageName);
1865 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001866 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 }
1868 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1869 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1870 && mTopComponent != null
1871 && app.processName.equals(mTopComponent.getPackageName())) {
1872 uid = 0;
1873 }
1874 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1875 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1876 uid = 0;
1877 }
1878 }
1879 int debugFlags = 0;
1880 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1881 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1882 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001883 // Run the app in safe mode if its manifest requests so or the
1884 // system is booted in safe mode.
1885 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1886 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001887 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1890 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1891 }
1892 if ("1".equals(SystemProperties.get("debug.assert"))) {
1893 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1894 }
1895 int pid = Process.start("android.app.ActivityThread",
1896 mSimpleProcessManagement ? app.processName : null, uid, uid,
1897 gids, debugFlags, null);
1898 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1899 synchronized (bs) {
1900 if (bs.isOnBattery()) {
1901 app.batteryStats.incStartsLocked();
1902 }
1903 }
1904
Doug Zongker2bec3d42009-12-04 12:52:44 -08001905 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 app.processName, hostingType,
1907 hostingNameStr != null ? hostingNameStr : "");
1908
1909 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001910 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 }
1912
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001913 StringBuilder buf = mStringBuilder;
1914 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 buf.append("Start proc ");
1916 buf.append(app.processName);
1917 buf.append(" for ");
1918 buf.append(hostingType);
1919 if (hostingNameStr != null) {
1920 buf.append(" ");
1921 buf.append(hostingNameStr);
1922 }
1923 buf.append(": pid=");
1924 buf.append(pid);
1925 buf.append(" uid=");
1926 buf.append(uid);
1927 buf.append(" gids={");
1928 if (gids != null) {
1929 for (int gi=0; gi<gids.length; gi++) {
1930 if (gi != 0) buf.append(", ");
1931 buf.append(gids[gi]);
1932
1933 }
1934 }
1935 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001936 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 if (pid == 0 || pid == MY_PID) {
1938 // Processes are being emulated with threads.
1939 app.pid = MY_PID;
1940 app.removed = false;
1941 mStartingProcesses.add(app);
1942 } else if (pid > 0) {
1943 app.pid = pid;
1944 app.removed = false;
1945 synchronized (mPidsSelfLocked) {
1946 this.mPidsSelfLocked.put(pid, app);
1947 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1948 msg.obj = app;
1949 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1950 }
1951 } else {
1952 app.pid = 0;
1953 RuntimeException e = new RuntimeException(
1954 "Failure starting process " + app.processName
1955 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001956 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 }
1958 } catch (RuntimeException e) {
1959 // XXX do better error recovery.
1960 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001961 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 }
1963 }
1964
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001965 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 if (resumed) {
1967 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1968 } else {
1969 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1970 }
1971 }
1972
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001973 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001974 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1975 && mTopAction == null) {
1976 // We are running in factory test mode, but unable to find
1977 // the factory test app, so just sit around displaying the
1978 // error message and don't try to start anything.
1979 return false;
1980 }
1981 Intent intent = new Intent(
1982 mTopAction,
1983 mTopData != null ? Uri.parse(mTopData) : null);
1984 intent.setComponent(mTopComponent);
1985 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1986 intent.addCategory(Intent.CATEGORY_HOME);
1987 }
1988 ActivityInfo aInfo =
1989 intent.resolveActivityInfo(mContext.getPackageManager(),
1990 STOCK_PM_FLAGS);
1991 if (aInfo != null) {
1992 intent.setComponent(new ComponentName(
1993 aInfo.applicationInfo.packageName, aInfo.name));
1994 // Don't do this if the home app is currently being
1995 // instrumented.
1996 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1997 aInfo.applicationInfo.uid);
1998 if (app == null || app.instrumentationClass == null) {
1999 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002000 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002001 null, null, 0, 0, 0, false, false);
2002 }
2003 }
2004
2005
2006 return true;
2007 }
2008
2009 /**
2010 * Starts the "new version setup screen" if appropriate.
2011 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002012 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002013 // Only do this once per boot.
2014 if (mCheckedForSetup) {
2015 return;
2016 }
2017
2018 // We will show this screen if the current one is a different
2019 // version than the last one shown, and we are not running in
2020 // low-level factory test mode.
2021 final ContentResolver resolver = mContext.getContentResolver();
2022 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2023 Settings.Secure.getInt(resolver,
2024 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2025 mCheckedForSetup = true;
2026
2027 // See if we should be showing the platform update setup UI.
2028 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2029 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2030 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2031
2032 // We don't allow third party apps to replace this.
2033 ResolveInfo ri = null;
2034 for (int i=0; ris != null && i<ris.size(); i++) {
2035 if ((ris.get(i).activityInfo.applicationInfo.flags
2036 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2037 ri = ris.get(i);
2038 break;
2039 }
2040 }
2041
2042 if (ri != null) {
2043 String vers = ri.activityInfo.metaData != null
2044 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2045 : null;
2046 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2047 vers = ri.activityInfo.applicationInfo.metaData.getString(
2048 Intent.METADATA_SETUP_VERSION);
2049 }
2050 String lastVers = Settings.Secure.getString(
2051 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2052 if (vers != null && !vers.equals(lastVers)) {
2053 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2054 intent.setComponent(new ComponentName(
2055 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002056 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002057 null, null, 0, 0, 0, false, false);
2058 }
2059 }
2060 }
2061 }
2062
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002064 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002065
2066 final int identHash = System.identityHashCode(r);
2067 updateUsageStats(r, true);
2068
2069 int i = mWatchers.beginBroadcast();
2070 while (i > 0) {
2071 i--;
2072 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2073 if (w != null) {
2074 try {
2075 w.activityResuming(identHash);
2076 } catch (RemoteException e) {
2077 }
2078 }
2079 }
2080 mWatchers.finishBroadcast();
2081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002083 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002084 final int N = mPendingActivityLaunches.size();
2085 if (N <= 0) {
2086 return;
2087 }
2088 for (int i=0; i<N; i++) {
2089 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002090 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002091 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2092 doResume && i == (N-1));
2093 }
2094 mPendingActivityLaunches.clear();
2095 }
2096
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002097 public final int startActivity(IApplicationThread caller,
2098 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2099 int grantedMode, IBinder resultTo,
2100 String resultWho, int requestCode, boolean onlyIfNeeded,
2101 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002102 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002103 grantedUriPermissions, grantedMode, resultTo, resultWho,
2104 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002105 }
2106
2107 public final WaitResult startActivityAndWait(IApplicationThread caller,
2108 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2109 int grantedMode, IBinder resultTo,
2110 String resultWho, int requestCode, boolean onlyIfNeeded,
2111 boolean debug) {
2112 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002113 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002114 grantedUriPermissions, grantedMode, resultTo, resultWho,
2115 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002116 return res;
2117 }
2118
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002119 public final int startActivityWithConfig(IApplicationThread caller,
2120 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2121 int grantedMode, IBinder resultTo,
2122 String resultWho, int requestCode, boolean onlyIfNeeded,
2123 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002124 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002125 grantedUriPermissions, grantedMode, resultTo, resultWho,
2126 requestCode, onlyIfNeeded, debug, null, config);
2127 }
2128
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002129 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002130 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002131 IBinder resultTo, String resultWho, int requestCode,
2132 int flagsMask, int flagsValues) {
2133 // Refuse possible leaked file descriptors
2134 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2135 throw new IllegalArgumentException("File descriptors passed in Intent");
2136 }
2137
2138 IIntentSender sender = intent.getTarget();
2139 if (!(sender instanceof PendingIntentRecord)) {
2140 throw new IllegalArgumentException("Bad PendingIntent object");
2141 }
2142
2143 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002144
2145 synchronized (this) {
2146 // If this is coming from the currently resumed activity, it is
2147 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002148 if (mMainStack.mResumedActivity != null
2149 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002150 Binder.getCallingUid()) {
2151 mAppSwitchesAllowedTime = 0;
2152 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002153 }
2154
2155 return pir.sendInner(0, fillInIntent, resolvedType,
2156 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2157 }
2158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 public boolean startNextMatchingActivity(IBinder callingActivity,
2160 Intent intent) {
2161 // Refuse possible leaked file descriptors
2162 if (intent != null && intent.hasFileDescriptors() == true) {
2163 throw new IllegalArgumentException("File descriptors passed in Intent");
2164 }
2165
2166 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002167 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 if (index < 0) {
2169 return false;
2170 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002171 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 if (r.app == null || r.app.thread == null) {
2173 // The caller is not running... d'oh!
2174 return false;
2175 }
2176 intent = new Intent(intent);
2177 // The caller is not allowed to change the data.
2178 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2179 // And we are resetting to find the next component...
2180 intent.setComponent(null);
2181
2182 ActivityInfo aInfo = null;
2183 try {
2184 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002185 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002187 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188
2189 // Look for the original activity in the list...
2190 final int N = resolves != null ? resolves.size() : 0;
2191 for (int i=0; i<N; i++) {
2192 ResolveInfo rInfo = resolves.get(i);
2193 if (rInfo.activityInfo.packageName.equals(r.packageName)
2194 && rInfo.activityInfo.name.equals(r.info.name)) {
2195 // We found the current one... the next matching is
2196 // after it.
2197 i++;
2198 if (i<N) {
2199 aInfo = resolves.get(i).activityInfo;
2200 }
2201 break;
2202 }
2203 }
2204 } catch (RemoteException e) {
2205 }
2206
2207 if (aInfo == null) {
2208 // Nobody who is next!
2209 return false;
2210 }
2211
2212 intent.setComponent(new ComponentName(
2213 aInfo.applicationInfo.packageName, aInfo.name));
2214 intent.setFlags(intent.getFlags()&~(
2215 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2216 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2217 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2218 Intent.FLAG_ACTIVITY_NEW_TASK));
2219
2220 // Okay now we need to start the new activity, replacing the
2221 // currently running activity. This is a little tricky because
2222 // we want to start the new one as if the current one is finished,
2223 // but not finish the current one first so that there is no flicker.
2224 // And thus...
2225 final boolean wasFinishing = r.finishing;
2226 r.finishing = true;
2227
2228 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002229 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 final String resultWho = r.resultWho;
2231 final int requestCode = r.requestCode;
2232 r.resultTo = null;
2233 if (resultTo != null) {
2234 resultTo.removeResultsLocked(r, resultWho, requestCode);
2235 }
2236
2237 final long origId = Binder.clearCallingIdentity();
2238 // XXX we are not dealing with propagating grantedUriPermissions...
2239 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002240 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002242 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 Binder.restoreCallingIdentity(origId);
2244
2245 r.finishing = wasFinishing;
2246 if (res != START_SUCCESS) {
2247 return false;
2248 }
2249 return true;
2250 }
2251 }
2252
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002253 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 Intent intent, String resolvedType, IBinder resultTo,
2255 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002256
2257 // This is so super not safe, that only the system (or okay root)
2258 // can do it.
2259 final int callingUid = Binder.getCallingUid();
2260 if (callingUid != 0 && callingUid != Process.myUid()) {
2261 throw new SecurityException(
2262 "startActivityInPackage only available to the system");
2263 }
2264
The Android Open Source Project4df24232009-03-05 14:34:35 -08002265 final boolean componentSpecified = intent.getComponent() != null;
2266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 // Don't modify the client's object!
2268 intent = new Intent(intent);
2269
2270 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 ActivityInfo aInfo;
2272 try {
2273 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002274 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002276 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 aInfo = rInfo != null ? rInfo.activityInfo : null;
2278 } catch (RemoteException e) {
2279 aInfo = null;
2280 }
2281
2282 if (aInfo != null) {
2283 // Store the found target back into the intent, because now that
2284 // we have it we never want to do this again. For example, if the
2285 // user navigates back to this point in the history, we should
2286 // always restart the exact same activity.
2287 intent.setComponent(new ComponentName(
2288 aInfo.applicationInfo.packageName, aInfo.name));
2289 }
2290
2291 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002292 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002294 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 }
2296 }
2297
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002298 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 // Remove any existing entries that are the same kind of task.
2300 int N = mRecentTasks.size();
2301 for (int i=0; i<N; i++) {
2302 TaskRecord tr = mRecentTasks.get(i);
2303 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2304 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2305 mRecentTasks.remove(i);
2306 i--;
2307 N--;
2308 if (task.intent == null) {
2309 // If the new recent task we are adding is not fully
2310 // specified, then replace it with the existing recent task.
2311 task = tr;
2312 }
2313 }
2314 }
2315 if (N >= MAX_RECENT_TASKS) {
2316 mRecentTasks.remove(N-1);
2317 }
2318 mRecentTasks.add(0, task);
2319 }
2320
2321 public void setRequestedOrientation(IBinder token,
2322 int requestedOrientation) {
2323 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002324 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 if (index < 0) {
2326 return;
2327 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002328 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 final long origId = Binder.clearCallingIdentity();
2330 mWindowManager.setAppOrientation(r, requestedOrientation);
2331 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002332 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 r.mayFreezeScreenLocked(r.app) ? r : null);
2334 if (config != null) {
2335 r.frozenBeforeDestroy = true;
2336 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002337 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 }
2339 }
2340 Binder.restoreCallingIdentity(origId);
2341 }
2342 }
2343
2344 public int getRequestedOrientation(IBinder token) {
2345 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 if (index < 0) {
2348 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2349 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002350 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 return mWindowManager.getAppOrientation(r);
2352 }
2353 }
2354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 /**
2356 * This is the internal entry point for handling Activity.finish().
2357 *
2358 * @param token The Binder token referencing the Activity we want to finish.
2359 * @param resultCode Result code, if any, from this Activity.
2360 * @param resultData Result data (Intent), if any, from this Activity.
2361 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002362 * @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 -08002363 */
2364 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2365 // Refuse possible leaked file descriptors
2366 if (resultData != null && resultData.hasFileDescriptors() == true) {
2367 throw new IllegalArgumentException("File descriptors passed in Intent");
2368 }
2369
2370 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002371 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002373 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 if (next != null) {
2375 // ask watcher if this is allowed
2376 boolean resumeOK = true;
2377 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002378 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002380 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 }
2382
2383 if (!resumeOK) {
2384 return false;
2385 }
2386 }
2387 }
2388 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002389 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 resultData, "app-request");
2391 Binder.restoreCallingIdentity(origId);
2392 return res;
2393 }
2394 }
2395
Dianne Hackborn860755f2010-06-03 18:47:52 -07002396 public final void finishHeavyWeightApp() {
2397 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2398 != PackageManager.PERMISSION_GRANTED) {
2399 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2400 + Binder.getCallingPid()
2401 + ", uid=" + Binder.getCallingUid()
2402 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2403 Slog.w(TAG, msg);
2404 throw new SecurityException(msg);
2405 }
2406
2407 synchronized(this) {
2408 if (mHeavyWeightProcess == null) {
2409 return;
2410 }
2411
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002412 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002413 mHeavyWeightProcess.activities);
2414 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002415 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002416 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002417 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002418 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002419 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002420 null, "finish-heavy");
2421 }
2422 }
2423 }
2424
2425 mHeavyWeightProcess = null;
2426 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2427 }
2428 }
2429
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002430 public void crashApplication(int uid, int initialPid, String packageName,
2431 String message) {
2432 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2433 != PackageManager.PERMISSION_GRANTED) {
2434 String msg = "Permission Denial: crashApplication() from pid="
2435 + Binder.getCallingPid()
2436 + ", uid=" + Binder.getCallingUid()
2437 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2438 Slog.w(TAG, msg);
2439 throw new SecurityException(msg);
2440 }
2441
2442 synchronized(this) {
2443 ProcessRecord proc = null;
2444
2445 // Figure out which process to kill. We don't trust that initialPid
2446 // still has any relation to current pids, so must scan through the
2447 // list.
2448 synchronized (mPidsSelfLocked) {
2449 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2450 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2451 if (p.info.uid != uid) {
2452 continue;
2453 }
2454 if (p.pid == initialPid) {
2455 proc = p;
2456 break;
2457 }
2458 for (String str : p.pkgList) {
2459 if (str.equals(packageName)) {
2460 proc = p;
2461 }
2462 }
2463 }
2464 }
2465
2466 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002467 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002468 + " initialPid=" + initialPid
2469 + " packageName=" + packageName);
2470 return;
2471 }
2472
2473 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002474 if (proc.pid == Process.myPid()) {
2475 Log.w(TAG, "crashApplication: trying to crash self!");
2476 return;
2477 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002478 long ident = Binder.clearCallingIdentity();
2479 try {
2480 proc.thread.scheduleCrash(message);
2481 } catch (RemoteException e) {
2482 }
2483 Binder.restoreCallingIdentity(ident);
2484 }
2485 }
2486 }
2487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 public final void finishSubActivity(IBinder token, String resultWho,
2489 int requestCode) {
2490 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 if (index < 0) {
2493 return;
2494 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002495 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496
2497 final long origId = Binder.clearCallingIdentity();
2498
2499 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002500 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2501 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 if (r.resultTo == self && r.requestCode == requestCode) {
2503 if ((r.resultWho == null && resultWho == null) ||
2504 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002505 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 Activity.RESULT_CANCELED, null, "request-sub");
2507 }
2508 }
2509 }
2510
2511 Binder.restoreCallingIdentity(origId);
2512 }
2513 }
2514
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002515 public boolean willActivityBeVisible(IBinder token) {
2516 synchronized(this) {
2517 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2519 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002520 if (r == token) {
2521 return true;
2522 }
2523 if (r.fullscreen && !r.finishing) {
2524 return false;
2525 }
2526 }
2527 return true;
2528 }
2529 }
2530
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002531 public void overridePendingTransition(IBinder token, String packageName,
2532 int enterAnim, int exitAnim) {
2533 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002535 if (index < 0) {
2536 return;
2537 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002539
2540 final long origId = Binder.clearCallingIdentity();
2541
2542 if (self.state == ActivityState.RESUMED
2543 || self.state == ActivityState.PAUSING) {
2544 mWindowManager.overridePendingAppTransition(packageName,
2545 enterAnim, exitAnim);
2546 }
2547
2548 Binder.restoreCallingIdentity(origId);
2549 }
2550 }
2551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 * Main function for removing an existing process from the activity manager
2554 * as a result of that process going away. Clears out all connections
2555 * to the process.
2556 */
2557 private final void handleAppDiedLocked(ProcessRecord app,
2558 boolean restarting) {
2559 cleanUpApplicationRecordLocked(app, restarting, -1);
2560 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002561 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 }
2563
2564 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002565 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2566 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2567 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2570 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 }
2572
2573 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002574 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575
2576 boolean atTop = true;
2577 boolean hasVisibleActivities = false;
2578
2579 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 TAG, "Removing app " + app + " from history with " + i + " entries");
2583 while (i > 0) {
2584 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002585 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2588 if (r.app == app) {
2589 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002590 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 TAG, "Removing this entry! frozen=" + r.haveState
2592 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594
2595 r.inHistory = false;
2596 mWindowManager.removeAppToken(r);
2597 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002598 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002600 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601
2602 } else {
2603 // We have the current state for this activity, so
2604 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002605 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 TAG, "Keeping entry, setting app to null");
2607 if (r.visible) {
2608 hasVisibleActivities = true;
2609 }
2610 r.app = null;
2611 r.nowVisible = false;
2612 if (!r.haveState) {
2613 r.icicle = null;
2614 }
2615 }
2616
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002617 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 r.state = ActivityState.STOPPED;
2619 }
2620 atTop = false;
2621 }
2622
2623 app.activities.clear();
2624
2625 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002626 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 + " running instrumentation " + app.instrumentationClass);
2628 Bundle info = new Bundle();
2629 info.putString("shortMsg", "Process crashed.");
2630 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2631 }
2632
2633 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002634 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 // If there was nothing to resume, and we are not already
2636 // restarting this process, but there is a visible activity that
2637 // is hosted by the process... then make sure all visible
2638 // activities are running, taking care of restarting this
2639 // process.
2640 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002641 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 }
2643 }
2644 }
2645 }
2646
2647 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2648 IBinder threadBinder = thread.asBinder();
2649
2650 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002651 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2652 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2654 return i;
2655 }
2656 }
2657 return -1;
2658 }
2659
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002660 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 IApplicationThread thread) {
2662 if (thread == null) {
2663 return null;
2664 }
2665
2666 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002667 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 }
2669
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002670 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 IApplicationThread thread) {
2672
2673 mProcDeaths[0]++;
2674
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002675 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2676 synchronized (stats) {
2677 stats.noteProcessDiedLocked(app.info.uid, pid);
2678 }
2679
Magnus Edlund7bb25812010-02-24 15:45:06 +01002680 // Clean up already done if the process has been re-started.
2681 if (app.pid == pid && app.thread != null &&
2682 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002683 if (!app.killedBackground) {
2684 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2685 + ") has died.");
2686 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002687 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002688 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 TAG, "Dying app: " + app + ", pid: " + pid
2690 + ", thread: " + thread.asBinder());
2691 boolean doLowMem = app.instrumentationClass == null;
2692 handleAppDiedLocked(app, false);
2693
2694 if (doLowMem) {
2695 // If there are no longer any background processes running,
2696 // and the app that died was not running instrumentation,
2697 // then tell everyone we are now low on memory.
2698 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002699 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2700 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2702 haveBg = true;
2703 break;
2704 }
2705 }
2706
2707 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002708 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002709 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002710 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002711 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2712 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002713 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002714 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2715 // The low memory report is overriding any current
2716 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002717 // heavy/important/visible/foreground processes first.
2718 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002719 rec.lastRequestedGc = 0;
2720 } else {
2721 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002723 rec.reportLowMemory = true;
2724 rec.lastLowMemory = now;
2725 mProcessesToGc.remove(rec);
2726 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 }
2728 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002729 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 }
2731 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002732 } else if (app.pid != pid) {
2733 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002734 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002735 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002736 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002737 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002738 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 + thread.asBinder());
2740 }
2741 }
2742
Dan Egnor42471dd2010-01-07 17:25:22 -08002743 /**
2744 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002745 * @param clearTraces causes the dump file to be erased prior to the new
2746 * traces being written, if true; when false, the new traces will be
2747 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002748 * @param firstPids of dalvik VM processes to dump stack traces for first
2749 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002750 * @return file containing stack traces, or null if no dump file is configured
2751 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002752 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2753 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002754 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2755 if (tracesPath == null || tracesPath.length() == 0) {
2756 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002758
2759 File tracesFile = new File(tracesPath);
2760 try {
2761 File tracesDir = tracesFile.getParentFile();
2762 if (!tracesDir.exists()) tracesFile.mkdirs();
2763 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2764
Christopher Tate6ee412d2010-05-28 12:01:56 -07002765 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002766 tracesFile.createNewFile();
2767 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2768 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002769 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002770 return null;
2771 }
2772
2773 // Use a FileObserver to detect when traces finish writing.
2774 // The order of traces is considered important to maintain for legibility.
2775 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2776 public synchronized void onEvent(int event, String path) { notify(); }
2777 };
2778
2779 try {
2780 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002781
2782 // First collect all of the stacks of the most important pids.
2783 try {
2784 int num = firstPids.size();
2785 for (int i = 0; i < num; i++) {
2786 synchronized (observer) {
2787 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2788 observer.wait(200); // Wait for write-close, give up after 200msec
2789 }
2790 }
2791 } catch (InterruptedException e) {
2792 Log.wtf(TAG, e);
2793 }
2794
2795 // Next measure CPU usage.
2796 if (processStats != null) {
2797 processStats.init();
2798 System.gc();
2799 processStats.update();
2800 try {
2801 synchronized (processStats) {
2802 processStats.wait(500); // measure over 1/2 second.
2803 }
2804 } catch (InterruptedException e) {
2805 }
2806 processStats.update();
2807
2808 // We'll take the stack crawls of just the top apps using CPU.
2809 final int N = processStats.countWorkingStats();
2810 int numProcs = 0;
2811 for (int i=0; i<N && numProcs<5; i++) {
2812 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2813 if (lastPids.indexOfKey(stats.pid) >= 0) {
2814 numProcs++;
2815 try {
2816 synchronized (observer) {
2817 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2818 observer.wait(200); // Wait for write-close, give up after 200msec
2819 }
2820 } catch (InterruptedException e) {
2821 Log.wtf(TAG, e);
2822 }
2823
2824 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002825 }
2826 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002827
2828 return tracesFile;
2829
Dan Egnor42471dd2010-01-07 17:25:22 -08002830 } finally {
2831 observer.stopWatching();
2832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 }
2834
Jeff Brown4d94a762010-09-23 11:33:28 -07002835 private final class AppNotResponding implements Runnable {
2836 private final ProcessRecord mApp;
2837 private final String mAnnotation;
2838
2839 public AppNotResponding(ProcessRecord app, String annotation) {
2840 mApp = app;
2841 mAnnotation = annotation;
2842 }
2843
2844 @Override
2845 public void run() {
2846 appNotResponding(mApp, null, null, mAnnotation);
2847 }
2848 }
2849
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002850 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2851 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002852 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2853 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2854
Dianne Hackborn287952c2010-09-22 22:34:31 -07002855 if (mController != null) {
2856 try {
2857 // 0 == continue, -1 = kill process immediately
2858 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2859 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2860 } catch (RemoteException e) {
2861 mController = null;
2862 }
2863 }
2864
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002865 long anrTime = SystemClock.uptimeMillis();
2866 if (MONITOR_CPU_USAGE) {
2867 updateCpuStatsNow();
2868 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002869
2870 synchronized (this) {
2871 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2872 if (mShuttingDown) {
2873 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2874 return;
2875 } else if (app.notResponding) {
2876 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2877 return;
2878 } else if (app.crashing) {
2879 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2880 return;
2881 }
2882
2883 // In case we come through here for the same app before completing
2884 // this one, mark as anring now so we will bail out.
2885 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002886
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002887 // Log the ANR to the event log.
2888 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2889 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002890
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002891 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002892 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002893
2894 int parentPid = app.pid;
2895 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002896 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002897
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002898 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002899
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002900 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2901 ProcessRecord r = mLruProcesses.get(i);
2902 if (r != null && r.thread != null) {
2903 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002904 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2905 if (r.persistent) {
2906 firstPids.add(pid);
2907 } else {
2908 lastPids.put(pid, Boolean.TRUE);
2909 }
2910 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 }
2913 }
2914
Dan Egnor42471dd2010-01-07 17:25:22 -08002915 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002916 StringBuilder info = mStringBuilder;
2917 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002918 info.append("ANR in ").append(app.processName);
2919 if (activity != null && activity.shortComponentName != null) {
2920 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002921 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002922 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002924 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002926 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002927 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929
Dianne Hackborn287952c2010-09-22 22:34:31 -07002930 final ProcessStats processStats = new ProcessStats(true);
2931
2932 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2933
Dan Egnor42471dd2010-01-07 17:25:22 -08002934 String cpuInfo = null;
2935 if (MONITOR_CPU_USAGE) {
2936 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002937 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002938 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002939 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002940 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002941 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 }
2943
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002944 info.append(processStats.printCurrentState(anrTime));
2945
Joe Onorato8a9b2202010-02-26 18:56:32 -08002946 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002947 if (tracesFile == null) {
2948 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2949 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2950 }
2951
2952 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2953
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002954 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002956 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2957 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002959 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2960 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 }
2962 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002963 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 }
2965 }
2966
Dan Egnor42471dd2010-01-07 17:25:22 -08002967 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2968 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2969 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002970
2971 synchronized (this) {
2972 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2973 Process.killProcess(app.pid);
2974 return;
2975 }
2976
2977 // Set the app's notResponding state, and look up the errorReportReceiver
2978 makeAppNotRespondingLocked(app,
2979 activity != null ? activity.shortComponentName : null,
2980 annotation != null ? "ANR " + annotation : "ANR",
2981 info.toString());
2982
2983 // Bring up the infamous App Not Responding dialog
2984 Message msg = Message.obtain();
2985 HashMap map = new HashMap();
2986 msg.what = SHOW_NOT_RESPONDING_MSG;
2987 msg.obj = map;
2988 map.put("app", app);
2989 if (activity != null) {
2990 map.put("activity", activity);
2991 }
2992
2993 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002995 }
2996
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002997 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2998 if (!mLaunchWarningShown) {
2999 mLaunchWarningShown = true;
3000 mHandler.post(new Runnable() {
3001 @Override
3002 public void run() {
3003 synchronized (ActivityManagerService.this) {
3004 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3005 d.show();
3006 mHandler.postDelayed(new Runnable() {
3007 @Override
3008 public void run() {
3009 synchronized (ActivityManagerService.this) {
3010 d.dismiss();
3011 mLaunchWarningShown = false;
3012 }
3013 }
3014 }, 4000);
3015 }
3016 }
3017 });
3018 }
3019 }
3020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 public boolean clearApplicationUserData(final String packageName,
3022 final IPackageDataObserver observer) {
3023 int uid = Binder.getCallingUid();
3024 int pid = Binder.getCallingPid();
3025 long callingId = Binder.clearCallingIdentity();
3026 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003027 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 int pkgUid = -1;
3029 synchronized(this) {
3030 try {
3031 pkgUid = pm.getPackageUid(packageName);
3032 } catch (RemoteException e) {
3033 }
3034 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003035 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 return false;
3037 }
3038 if (uid == pkgUid || checkComponentPermission(
3039 android.Manifest.permission.CLEAR_APP_USER_DATA,
3040 pid, uid, -1)
3041 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003042 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 } else {
3044 throw new SecurityException(pid+" does not have permission:"+
3045 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3046 "for process:"+packageName);
3047 }
3048 }
3049
3050 try {
3051 //clear application user data
3052 pm.clearApplicationUserData(packageName, observer);
3053 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3054 Uri.fromParts("package", packageName, null));
3055 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003056 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3057 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 } catch (RemoteException e) {
3059 }
3060 } finally {
3061 Binder.restoreCallingIdentity(callingId);
3062 }
3063 return true;
3064 }
3065
Dianne Hackborn03abb812010-01-04 18:43:19 -08003066 public void killBackgroundProcesses(final String packageName) {
3067 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3068 != PackageManager.PERMISSION_GRANTED &&
3069 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3070 != PackageManager.PERMISSION_GRANTED) {
3071 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 + Binder.getCallingPid()
3073 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003074 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003075 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076 throw new SecurityException(msg);
3077 }
3078
3079 long callingId = Binder.clearCallingIdentity();
3080 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003081 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 int pkgUid = -1;
3083 synchronized(this) {
3084 try {
3085 pkgUid = pm.getPackageUid(packageName);
3086 } catch (RemoteException e) {
3087 }
3088 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003089 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 return;
3091 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003093 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003094 }
3095 } finally {
3096 Binder.restoreCallingIdentity(callingId);
3097 }
3098 }
3099
3100 public void forceStopPackage(final String packageName) {
3101 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3102 != PackageManager.PERMISSION_GRANTED) {
3103 String msg = "Permission Denial: forceStopPackage() from pid="
3104 + Binder.getCallingPid()
3105 + ", uid=" + Binder.getCallingUid()
3106 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003107 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003108 throw new SecurityException(msg);
3109 }
3110
3111 long callingId = Binder.clearCallingIdentity();
3112 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003113 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003114 int pkgUid = -1;
3115 synchronized(this) {
3116 try {
3117 pkgUid = pm.getPackageUid(packageName);
3118 } catch (RemoteException e) {
3119 }
3120 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003121 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003122 return;
3123 }
3124 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 }
3126 } finally {
3127 Binder.restoreCallingIdentity(callingId);
3128 }
3129 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003130
3131 /*
3132 * The pkg name and uid have to be specified.
3133 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3134 */
3135 public void killApplicationWithUid(String pkg, int uid) {
3136 if (pkg == null) {
3137 return;
3138 }
3139 // Make sure the uid is valid.
3140 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003141 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003142 return;
3143 }
3144 int callerUid = Binder.getCallingUid();
3145 // Only the system server can kill an application
3146 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003147 // Post an aysnc message to kill the application
3148 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3149 msg.arg1 = uid;
3150 msg.arg2 = 0;
3151 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003152 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003153 } else {
3154 throw new SecurityException(callerUid + " cannot kill pkg: " +
3155 pkg);
3156 }
3157 }
3158
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003159 public void closeSystemDialogs(String reason) {
3160 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003161 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003162 if (reason != null) {
3163 intent.putExtra("reason", reason);
3164 }
3165
3166 final int uid = Binder.getCallingUid();
3167 final long origId = Binder.clearCallingIdentity();
3168 synchronized (this) {
3169 int i = mWatchers.beginBroadcast();
3170 while (i > 0) {
3171 i--;
3172 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3173 if (w != null) {
3174 try {
3175 w.closingSystemDialogs(reason);
3176 } catch (RemoteException e) {
3177 }
3178 }
3179 }
3180 mWatchers.finishBroadcast();
3181
Dianne Hackbornffa42482009-09-23 22:20:11 -07003182 mWindowManager.closeSystemDialogs(reason);
3183
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003184 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3185 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003186 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003187 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003188 Activity.RESULT_CANCELED, null, "close-sys");
3189 }
3190 }
3191
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003192 broadcastIntentLocked(null, null, intent, null,
3193 null, 0, null, null, null, false, false, -1, uid);
3194 }
3195 Binder.restoreCallingIdentity(origId);
3196 }
3197
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003198 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003199 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003200 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3201 for (int i=pids.length-1; i>=0; i--) {
3202 infos[i] = new Debug.MemoryInfo();
3203 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003204 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003205 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003206 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003207
3208 public void killApplicationProcess(String processName, int uid) {
3209 if (processName == null) {
3210 return;
3211 }
3212
3213 int callerUid = Binder.getCallingUid();
3214 // Only the system server can kill an application
3215 if (callerUid == Process.SYSTEM_UID) {
3216 synchronized (this) {
3217 ProcessRecord app = getProcessRecordLocked(processName, uid);
3218 if (app != null) {
3219 try {
3220 app.thread.scheduleSuicide();
3221 } catch (RemoteException e) {
3222 // If the other end already died, then our work here is done.
3223 }
3224 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003225 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003226 + processName + " / " + uid);
3227 }
3228 }
3229 } else {
3230 throw new SecurityException(callerUid + " cannot kill app process: " +
3231 processName);
3232 }
3233 }
3234
Dianne Hackborn03abb812010-01-04 18:43:19 -08003235 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003236 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3238 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003239 if (!mProcessesReady) {
3240 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 intent.putExtra(Intent.EXTRA_UID, uid);
3243 broadcastIntentLocked(null, null, intent,
3244 null, null, 0, null, null, null,
3245 false, false, MY_PID, Process.SYSTEM_UID);
3246 }
3247
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003248 private final boolean killPackageProcessesLocked(String packageName, int uid,
3249 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003250 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251
Dianne Hackborn03abb812010-01-04 18:43:19 -08003252 // Remove all processes this package may have touched: all with the
3253 // same UID (except for the system or root user), and all whose name
3254 // matches the package name.
3255 final String procNamePrefix = packageName + ":";
3256 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3257 final int NA = apps.size();
3258 for (int ia=0; ia<NA; ia++) {
3259 ProcessRecord app = apps.valueAt(ia);
3260 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003261 if (doit) {
3262 procs.add(app);
3263 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003264 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3265 || app.processName.equals(packageName)
3266 || app.processName.startsWith(procNamePrefix)) {
3267 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003268 if (!doit) {
3269 return true;
3270 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003271 app.removed = true;
3272 procs.add(app);
3273 }
3274 }
3275 }
3276 }
3277
3278 int N = procs.size();
3279 for (int i=0; i<N; i++) {
3280 removeProcessLocked(procs.get(i), callerWillRestart);
3281 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003282 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003283 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003284
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003285 private final boolean forceStopPackageLocked(String name, int uid,
3286 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 int i, N;
3288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 if (uid < 0) {
3290 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003291 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 } catch (RemoteException e) {
3293 }
3294 }
3295
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003296 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003297 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003298
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003299 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3300 while (badApps.hasNext()) {
3301 SparseArray<Long> ba = badApps.next();
3302 if (ba.get(uid) != null) {
3303 badApps.remove();
3304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 }
3306 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003307
3308 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3309 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003311 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3312 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003314 if (!doit) {
3315 return true;
3316 }
3317 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003318 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 if (r.app != null) {
3320 r.app.removed = true;
3321 }
3322 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003323 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325 }
3326
3327 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3328 for (ServiceRecord service : mServices.values()) {
3329 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003330 if (!doit) {
3331 return true;
3332 }
3333 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003334 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 if (service.app != null) {
3336 service.app.removed = true;
3337 }
3338 service.app = null;
3339 services.add(service);
3340 }
3341 }
3342
3343 N = services.size();
3344 for (i=0; i<N; i++) {
3345 bringDownServiceLocked(services.get(i), true);
3346 }
3347
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003348 if (doit) {
3349 if (purgeCache) {
3350 AttributeCache ac = AttributeCache.instance();
3351 if (ac != null) {
3352 ac.removePackage(name);
3353 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003354 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003355 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003356 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003357
3358 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360
3361 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3362 final String name = app.processName;
3363 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003364 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 TAG, "Force removing process " + app + " (" + name
3366 + "/" + uid + ")");
3367
3368 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003369 if (mHeavyWeightProcess == app) {
3370 mHeavyWeightProcess = null;
3371 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 boolean needRestart = false;
3374 if (app.pid > 0 && app.pid != MY_PID) {
3375 int pid = app.pid;
3376 synchronized (mPidsSelfLocked) {
3377 mPidsSelfLocked.remove(pid);
3378 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3379 }
3380 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003381 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 Process.killProcess(pid);
3383
3384 if (app.persistent) {
3385 if (!callerWillRestart) {
3386 addAppLocked(app.info);
3387 } else {
3388 needRestart = true;
3389 }
3390 }
3391 } else {
3392 mRemovedProcesses.add(app);
3393 }
3394
3395 return needRestart;
3396 }
3397
3398 private final void processStartTimedOutLocked(ProcessRecord app) {
3399 final int pid = app.pid;
3400 boolean gone = false;
3401 synchronized (mPidsSelfLocked) {
3402 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3403 if (knownApp != null && knownApp.thread == null) {
3404 mPidsSelfLocked.remove(pid);
3405 gone = true;
3406 }
3407 }
3408
3409 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003410 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003411 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003412 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003414 if (mHeavyWeightProcess == app) {
3415 mHeavyWeightProcess = null;
3416 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3417 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003418 // Take care of any launching providers waiting for this process.
3419 checkAppInLaunchingProvidersLocked(app, true);
3420 // Take care of any services that are waiting for the process.
3421 for (int i=0; i<mPendingServices.size(); i++) {
3422 ServiceRecord sr = mPendingServices.get(i);
3423 if (app.info.uid == sr.appInfo.uid
3424 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003426 mPendingServices.remove(i);
3427 i--;
3428 bringDownServiceLocked(sr, true);
3429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003431 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003432 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003434 try {
3435 IBackupManager bm = IBackupManager.Stub.asInterface(
3436 ServiceManager.getService(Context.BACKUP_SERVICE));
3437 bm.agentDisconnected(app.info.packageName);
3438 } catch (RemoteException e) {
3439 // Can't happen; the backup manager is local
3440 }
3441 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003442 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003444 mPendingBroadcast.state = BroadcastRecord.IDLE;
3445 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003446 mPendingBroadcast = null;
3447 scheduleBroadcastsLocked();
3448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003450 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 }
3452 }
3453
3454 private final boolean attachApplicationLocked(IApplicationThread thread,
3455 int pid) {
3456
3457 // Find the application record that is being attached... either via
3458 // the pid if we are running in multiple processes, or just pull the
3459 // next app record if we are emulating process with anonymous threads.
3460 ProcessRecord app;
3461 if (pid != MY_PID && pid >= 0) {
3462 synchronized (mPidsSelfLocked) {
3463 app = mPidsSelfLocked.get(pid);
3464 }
3465 } else if (mStartingProcesses.size() > 0) {
3466 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003467 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 } else {
3469 app = null;
3470 }
3471
3472 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003475 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 if (pid > 0 && pid != MY_PID) {
3477 Process.killProcess(pid);
3478 } else {
3479 try {
3480 thread.scheduleExit();
3481 } catch (Exception e) {
3482 // Ignore exceptions.
3483 }
3484 }
3485 return false;
3486 }
3487
3488 // If this application record is still attached to a previous
3489 // process, clean it up now.
3490 if (app.thread != null) {
3491 handleAppDiedLocked(app, true);
3492 }
3493
3494 // Tell the process all about itself.
3495
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 TAG, "Binding process pid " + pid + " to record " + app);
3498
3499 String processName = app.processName;
3500 try {
3501 thread.asBinder().linkToDeath(new AppDeathRecipient(
3502 app, pid, thread), 0);
3503 } catch (RemoteException e) {
3504 app.resetPackageList();
3505 startProcessLocked(app, "link fail", processName);
3506 return false;
3507 }
3508
Doug Zongker2bec3d42009-12-04 12:52:44 -08003509 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510
3511 app.thread = thread;
3512 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003513 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3514 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 app.forcingToForeground = null;
3516 app.foregroundServices = false;
3517 app.debugging = false;
3518
3519 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3520
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003521 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003522 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003524 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003525 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003526 }
3527
Joe Onorato8a9b2202010-02-26 18:56:32 -08003528 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 TAG, "New app record " + app
3530 + " thread=" + thread.asBinder() + " pid=" + pid);
3531 try {
3532 int testMode = IApplicationThread.DEBUG_OFF;
3533 if (mDebugApp != null && mDebugApp.equals(processName)) {
3534 testMode = mWaitForDebugger
3535 ? IApplicationThread.DEBUG_WAIT
3536 : IApplicationThread.DEBUG_ON;
3537 app.debugging = true;
3538 if (mDebugTransient) {
3539 mDebugApp = mOrigDebugApp;
3540 mWaitForDebugger = mOrigWaitForDebugger;
3541 }
3542 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003543
Christopher Tate181fafa2009-05-14 11:12:14 -07003544 // If the app is being launched for restore or full backup, set it up specially
3545 boolean isRestrictedBackupMode = false;
3546 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3547 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3548 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3549 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003550
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003551 ensurePackageDexOpt(app.instrumentationInfo != null
3552 ? app.instrumentationInfo.packageName
3553 : app.info.packageName);
3554 if (app.instrumentationClass != null) {
3555 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003556 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003557 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003558 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003559 thread.bindApplication(processName, app.instrumentationInfo != null
3560 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 app.instrumentationClass, app.instrumentationProfileFile,
3562 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003563 isRestrictedBackupMode || !normalMode,
3564 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003565 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003566 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 } catch (Exception e) {
3568 // todo: Yikes! What should we do? For now we will try to
3569 // start another process, but that could easily get us in
3570 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003571 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572
3573 app.resetPackageList();
3574 startProcessLocked(app, "bind fail", processName);
3575 return false;
3576 }
3577
3578 // Remove this record from the list of starting applications.
3579 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003580 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3581 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 mProcessesOnHold.remove(app);
3583
3584 boolean badApp = false;
3585 boolean didSomething = false;
3586
3587 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003588 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003589 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3591 && processName.equals(hr.processName)) {
3592 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003593 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 didSomething = true;
3595 }
3596 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003597 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 + hr.intent.getComponent().flattenToShortString(), e);
3599 badApp = true;
3600 }
3601 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003602 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 }
3604 }
3605
3606 // Find any services that should be running in this process...
3607 if (!badApp && mPendingServices.size() > 0) {
3608 ServiceRecord sr = null;
3609 try {
3610 for (int i=0; i<mPendingServices.size(); i++) {
3611 sr = mPendingServices.get(i);
3612 if (app.info.uid != sr.appInfo.uid
3613 || !processName.equals(sr.processName)) {
3614 continue;
3615 }
3616
3617 mPendingServices.remove(i);
3618 i--;
3619 realStartServiceLocked(sr, app);
3620 didSomething = true;
3621 }
3622 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003623 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 + sr.shortName, e);
3625 badApp = true;
3626 }
3627 }
3628
3629 // Check if the next broadcast receiver is in this process...
3630 BroadcastRecord br = mPendingBroadcast;
3631 if (!badApp && br != null && br.curApp == app) {
3632 try {
3633 mPendingBroadcast = null;
3634 processCurBroadcastLocked(br, app);
3635 didSomething = true;
3636 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003637 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 + br.curComponent.flattenToShortString(), e);
3639 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003640 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3642 br.resultExtras, br.resultAbort, true);
3643 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003644 // We need to reset the state if we fails to start the receiver.
3645 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 }
3647 }
3648
Christopher Tate181fafa2009-05-14 11:12:14 -07003649 // Check whether the next backup agent is in this process...
3650 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003651 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003652 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003653 try {
3654 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3655 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003656 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003657 e.printStackTrace();
3658 }
3659 }
3660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 if (badApp) {
3662 // todo: Also need to kill application to deal with all
3663 // kinds of exceptions.
3664 handleAppDiedLocked(app, false);
3665 return false;
3666 }
3667
3668 if (!didSomething) {
3669 updateOomAdjLocked();
3670 }
3671
3672 return true;
3673 }
3674
3675 public final void attachApplication(IApplicationThread thread) {
3676 synchronized (this) {
3677 int callingPid = Binder.getCallingPid();
3678 final long origId = Binder.clearCallingIdentity();
3679 attachApplicationLocked(thread, callingPid);
3680 Binder.restoreCallingIdentity(origId);
3681 }
3682 }
3683
Dianne Hackborne88846e2009-09-30 21:34:25 -07003684 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003686 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003687 Binder.restoreCallingIdentity(origId);
3688 }
3689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003691 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003692 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 mWindowManager.enableScreenAfterBoot();
3694 }
3695
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003696 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003697 IntentFilter pkgFilter = new IntentFilter();
3698 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3699 pkgFilter.addDataScheme("package");
3700 mContext.registerReceiver(new BroadcastReceiver() {
3701 @Override
3702 public void onReceive(Context context, Intent intent) {
3703 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3704 if (pkgs != null) {
3705 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003706 synchronized (ActivityManagerService.this) {
3707 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3708 setResultCode(Activity.RESULT_OK);
3709 return;
3710 }
3711 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003712 }
3713 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003714 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003715 }, pkgFilter);
3716
3717 synchronized (this) {
3718 // Ensure that any processes we had put on hold are now started
3719 // up.
3720 final int NP = mProcessesOnHold.size();
3721 if (NP > 0) {
3722 ArrayList<ProcessRecord> procs =
3723 new ArrayList<ProcessRecord>(mProcessesOnHold);
3724 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003725 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3726 + procs.get(ip));
3727 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003728 }
3729 }
3730
3731 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003732 // Start looking for apps that are abusing wake locks.
3733 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003734 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003735 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003736 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003737 broadcastIntentLocked(null, null,
3738 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3739 null, null, 0, null, null,
3740 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3741 false, false, MY_PID, Process.SYSTEM_UID);
3742 }
3743 }
3744 }
3745
3746 final void ensureBootCompleted() {
3747 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003748 boolean enableScreen;
3749 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003750 booting = mBooting;
3751 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003752 enableScreen = !mBooted;
3753 mBooted = true;
3754 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003755
3756 if (booting) {
3757 finishBooting();
3758 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003759
3760 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003761 enableScreenAfterBoot();
3762 }
3763 }
3764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 public final void activityPaused(IBinder token, Bundle icicle) {
3766 // Refuse possible leaked file descriptors
3767 if (icicle != null && icicle.hasFileDescriptors()) {
3768 throw new IllegalArgumentException("File descriptors passed in Bundle");
3769 }
3770
3771 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003772 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 Binder.restoreCallingIdentity(origId);
3774 }
3775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 public final void activityStopped(IBinder token, Bitmap thumbnail,
3777 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003778 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 TAG, "Activity stopped: token=" + token);
3780
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003781 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782
3783 final long origId = Binder.clearCallingIdentity();
3784
3785 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003786 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003788 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 r.thumbnail = thumbnail;
3790 r.description = description;
3791 r.stopped = true;
3792 r.state = ActivityState.STOPPED;
3793 if (!r.finishing) {
3794 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003795 r.stack.destroyActivityLocked(r, true);
3796 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 }
3798 }
3799 }
3800 }
3801
3802 if (r != null) {
3803 sendPendingThumbnail(r, null, null, null, false);
3804 }
3805
3806 trimApplications();
3807
3808 Binder.restoreCallingIdentity(origId);
3809 }
3810
3811 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003812 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003813 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 }
3815
3816 public String getCallingPackage(IBinder token) {
3817 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003818 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003819 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 }
3821 }
3822
3823 public ComponentName getCallingActivity(IBinder token) {
3824 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003825 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 return r != null ? r.intent.getComponent() : null;
3827 }
3828 }
3829
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003830 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003831 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003833 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 if (r != null) {
3835 return r.resultTo;
3836 }
3837 }
3838 return null;
3839 }
3840
3841 public ComponentName getActivityClassForToken(IBinder token) {
3842 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003843 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003845 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 return r.intent.getComponent();
3847 }
3848 return null;
3849 }
3850 }
3851
3852 public String getPackageForToken(IBinder token) {
3853 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003854 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003856 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 return r.packageName;
3858 }
3859 return null;
3860 }
3861 }
3862
3863 public IIntentSender getIntentSender(int type,
3864 String packageName, IBinder token, String resultWho,
3865 int requestCode, Intent intent, String resolvedType, int flags) {
3866 // Refuse possible leaked file descriptors
3867 if (intent != null && intent.hasFileDescriptors() == true) {
3868 throw new IllegalArgumentException("File descriptors passed in Intent");
3869 }
3870
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003871 if (type == INTENT_SENDER_BROADCAST) {
3872 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3873 throw new IllegalArgumentException(
3874 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3875 }
3876 }
3877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 synchronized(this) {
3879 int callingUid = Binder.getCallingUid();
3880 try {
3881 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3882 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003883 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 .getPackageUid(packageName);
3885 if (uid != Binder.getCallingUid()) {
3886 String msg = "Permission Denial: getIntentSender() from pid="
3887 + Binder.getCallingPid()
3888 + ", uid=" + Binder.getCallingUid()
3889 + ", (need uid=" + uid + ")"
3890 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003891 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 throw new SecurityException(msg);
3893 }
3894 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003895
3896 return getIntentSenderLocked(type, packageName, callingUid,
3897 token, resultWho, requestCode, intent, resolvedType, flags);
3898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 } catch (RemoteException e) {
3900 throw new SecurityException(e);
3901 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003902 }
3903 }
3904
3905 IIntentSender getIntentSenderLocked(int type,
3906 String packageName, int callingUid, IBinder token, String resultWho,
3907 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003908 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003909 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003910 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003911 if (index < 0) {
3912 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003914 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003915 if (activity.finishing) {
3916 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003918 }
3919
3920 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3921 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3922 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3923 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3924 |PendingIntent.FLAG_UPDATE_CURRENT);
3925
3926 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3927 type, packageName, activity, resultWho,
3928 requestCode, intent, resolvedType, flags);
3929 WeakReference<PendingIntentRecord> ref;
3930 ref = mIntentSenderRecords.get(key);
3931 PendingIntentRecord rec = ref != null ? ref.get() : null;
3932 if (rec != null) {
3933 if (!cancelCurrent) {
3934 if (updateCurrent) {
3935 rec.key.requestIntent.replaceExtras(intent);
3936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 return rec;
3938 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003939 rec.canceled = true;
3940 mIntentSenderRecords.remove(key);
3941 }
3942 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 return rec;
3944 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945 rec = new PendingIntentRecord(this, key, callingUid);
3946 mIntentSenderRecords.put(key, rec.ref);
3947 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3948 if (activity.pendingResults == null) {
3949 activity.pendingResults
3950 = new HashSet<WeakReference<PendingIntentRecord>>();
3951 }
3952 activity.pendingResults.add(rec.ref);
3953 }
3954 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 }
3956
3957 public void cancelIntentSender(IIntentSender sender) {
3958 if (!(sender instanceof PendingIntentRecord)) {
3959 return;
3960 }
3961 synchronized(this) {
3962 PendingIntentRecord rec = (PendingIntentRecord)sender;
3963 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003964 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 .getPackageUid(rec.key.packageName);
3966 if (uid != Binder.getCallingUid()) {
3967 String msg = "Permission Denial: cancelIntentSender() from pid="
3968 + Binder.getCallingPid()
3969 + ", uid=" + Binder.getCallingUid()
3970 + " is not allowed to cancel packges "
3971 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003972 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 throw new SecurityException(msg);
3974 }
3975 } catch (RemoteException e) {
3976 throw new SecurityException(e);
3977 }
3978 cancelIntentSenderLocked(rec, true);
3979 }
3980 }
3981
3982 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3983 rec.canceled = true;
3984 mIntentSenderRecords.remove(rec.key);
3985 if (cleanActivity && rec.key.activity != null) {
3986 rec.key.activity.pendingResults.remove(rec.ref);
3987 }
3988 }
3989
3990 public String getPackageForIntentSender(IIntentSender pendingResult) {
3991 if (!(pendingResult instanceof PendingIntentRecord)) {
3992 return null;
3993 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003994 try {
3995 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3996 return res.key.packageName;
3997 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 }
3999 return null;
4000 }
4001
4002 public void setProcessLimit(int max) {
4003 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4004 "setProcessLimit()");
4005 mProcessLimit = max;
4006 }
4007
4008 public int getProcessLimit() {
4009 return mProcessLimit;
4010 }
4011
4012 void foregroundTokenDied(ForegroundToken token) {
4013 synchronized (ActivityManagerService.this) {
4014 synchronized (mPidsSelfLocked) {
4015 ForegroundToken cur
4016 = mForegroundProcesses.get(token.pid);
4017 if (cur != token) {
4018 return;
4019 }
4020 mForegroundProcesses.remove(token.pid);
4021 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4022 if (pr == null) {
4023 return;
4024 }
4025 pr.forcingToForeground = null;
4026 pr.foregroundServices = false;
4027 }
4028 updateOomAdjLocked();
4029 }
4030 }
4031
4032 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4033 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4034 "setProcessForeground()");
4035 synchronized(this) {
4036 boolean changed = false;
4037
4038 synchronized (mPidsSelfLocked) {
4039 ProcessRecord pr = mPidsSelfLocked.get(pid);
4040 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004041 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 return;
4043 }
4044 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4045 if (oldToken != null) {
4046 oldToken.token.unlinkToDeath(oldToken, 0);
4047 mForegroundProcesses.remove(pid);
4048 pr.forcingToForeground = null;
4049 changed = true;
4050 }
4051 if (isForeground && token != null) {
4052 ForegroundToken newToken = new ForegroundToken() {
4053 public void binderDied() {
4054 foregroundTokenDied(this);
4055 }
4056 };
4057 newToken.pid = pid;
4058 newToken.token = token;
4059 try {
4060 token.linkToDeath(newToken, 0);
4061 mForegroundProcesses.put(pid, newToken);
4062 pr.forcingToForeground = token;
4063 changed = true;
4064 } catch (RemoteException e) {
4065 // If the process died while doing this, we will later
4066 // do the cleanup with the process death link.
4067 }
4068 }
4069 }
4070
4071 if (changed) {
4072 updateOomAdjLocked();
4073 }
4074 }
4075 }
4076
4077 // =========================================================
4078 // PERMISSIONS
4079 // =========================================================
4080
4081 static class PermissionController extends IPermissionController.Stub {
4082 ActivityManagerService mActivityManagerService;
4083 PermissionController(ActivityManagerService activityManagerService) {
4084 mActivityManagerService = activityManagerService;
4085 }
4086
4087 public boolean checkPermission(String permission, int pid, int uid) {
4088 return mActivityManagerService.checkPermission(permission, pid,
4089 uid) == PackageManager.PERMISSION_GRANTED;
4090 }
4091 }
4092
4093 /**
4094 * This can be called with or without the global lock held.
4095 */
4096 int checkComponentPermission(String permission, int pid, int uid,
4097 int reqUid) {
4098 // We might be performing an operation on behalf of an indirect binder
4099 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4100 // client identity accordingly before proceeding.
4101 Identity tlsIdentity = sCallerIdentity.get();
4102 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004103 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4105 uid = tlsIdentity.uid;
4106 pid = tlsIdentity.pid;
4107 }
4108
4109 // Root, system server and our own process get to do everything.
4110 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4111 !Process.supportsProcesses()) {
4112 return PackageManager.PERMISSION_GRANTED;
4113 }
4114 // If the target requires a specific UID, always fail for others.
4115 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004116 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 return PackageManager.PERMISSION_DENIED;
4118 }
4119 if (permission == null) {
4120 return PackageManager.PERMISSION_GRANTED;
4121 }
4122 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004123 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 .checkUidPermission(permission, uid);
4125 } catch (RemoteException e) {
4126 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004127 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 }
4129 return PackageManager.PERMISSION_DENIED;
4130 }
4131
4132 /**
4133 * As the only public entry point for permissions checking, this method
4134 * can enforce the semantic that requesting a check on a null global
4135 * permission is automatically denied. (Internally a null permission
4136 * string is used when calling {@link #checkComponentPermission} in cases
4137 * when only uid-based security is needed.)
4138 *
4139 * This can be called with or without the global lock held.
4140 */
4141 public int checkPermission(String permission, int pid, int uid) {
4142 if (permission == null) {
4143 return PackageManager.PERMISSION_DENIED;
4144 }
4145 return checkComponentPermission(permission, pid, uid, -1);
4146 }
4147
4148 /**
4149 * Binder IPC calls go through the public entry point.
4150 * This can be called with or without the global lock held.
4151 */
4152 int checkCallingPermission(String permission) {
4153 return checkPermission(permission,
4154 Binder.getCallingPid(),
4155 Binder.getCallingUid());
4156 }
4157
4158 /**
4159 * This can be called with or without the global lock held.
4160 */
4161 void enforceCallingPermission(String permission, String func) {
4162 if (checkCallingPermission(permission)
4163 == PackageManager.PERMISSION_GRANTED) {
4164 return;
4165 }
4166
4167 String msg = "Permission Denial: " + func + " from pid="
4168 + Binder.getCallingPid()
4169 + ", uid=" + Binder.getCallingUid()
4170 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004171 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 throw new SecurityException(msg);
4173 }
4174
4175 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004176 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4177 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4178 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4179 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4180 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004182 // Is the component private from the target uid?
4183 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4184
4185 // Acceptable if the there is no read permission needed from the
4186 // target or the target is holding the read permission.
4187 if (!readPerm) {
4188 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004190 == PackageManager.PERMISSION_GRANTED)) {
4191 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 }
4193 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004194
4195 // Acceptable if the there is no write permission needed from the
4196 // target or the target is holding the read permission.
4197 if (!writePerm) {
4198 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004200 == PackageManager.PERMISSION_GRANTED)) {
4201 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 }
4203 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004204
4205 // Acceptable if there is a path permission matching the URI that
4206 // the target holds the permission on.
4207 PathPermission[] pps = pi.pathPermissions;
4208 if (pps != null && (!readPerm || !writePerm)) {
4209 final String path = uri.getPath();
4210 int i = pps.length;
4211 while (i > 0 && (!readPerm || !writePerm)) {
4212 i--;
4213 PathPermission pp = pps[i];
4214 if (!readPerm) {
4215 final String pprperm = pp.getReadPermission();
4216 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4217 + pprperm + " for " + pp.getPath()
4218 + ": match=" + pp.match(path)
4219 + " check=" + pm.checkUidPermission(pprperm, uid));
4220 if (pprperm != null && pp.match(path) &&
4221 (pm.checkUidPermission(pprperm, uid)
4222 == PackageManager.PERMISSION_GRANTED)) {
4223 readPerm = true;
4224 }
4225 }
4226 if (!writePerm) {
4227 final String ppwperm = pp.getWritePermission();
4228 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4229 + ppwperm + " for " + pp.getPath()
4230 + ": match=" + pp.match(path)
4231 + " check=" + pm.checkUidPermission(ppwperm, uid));
4232 if (ppwperm != null && pp.match(path) &&
4233 (pm.checkUidPermission(ppwperm, uid)
4234 == PackageManager.PERMISSION_GRANTED)) {
4235 writePerm = true;
4236 }
4237 }
4238 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 } catch (RemoteException e) {
4241 return false;
4242 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004243
4244 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 }
4246
4247 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4248 int modeFlags) {
4249 // Root gets to do everything.
4250 if (uid == 0 || !Process.supportsProcesses()) {
4251 return true;
4252 }
4253 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4254 if (perms == null) return false;
4255 UriPermission perm = perms.get(uri);
4256 if (perm == null) return false;
4257 return (modeFlags&perm.modeFlags) == modeFlags;
4258 }
4259
4260 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4261 // Another redirected-binder-call permissions check as in
4262 // {@link checkComponentPermission}.
4263 Identity tlsIdentity = sCallerIdentity.get();
4264 if (tlsIdentity != null) {
4265 uid = tlsIdentity.uid;
4266 pid = tlsIdentity.pid;
4267 }
4268
4269 // Our own process gets to do everything.
4270 if (pid == MY_PID) {
4271 return PackageManager.PERMISSION_GRANTED;
4272 }
4273 synchronized(this) {
4274 return checkUriPermissionLocked(uri, uid, modeFlags)
4275 ? PackageManager.PERMISSION_GRANTED
4276 : PackageManager.PERMISSION_DENIED;
4277 }
4278 }
4279
Dianne Hackborn39792d22010-08-19 18:01:52 -07004280 /**
4281 * Check if the targetPkg can be granted permission to access uri by
4282 * the callingUid using the given modeFlags. Throws a security exception
4283 * if callingUid is not allowed to do this. Returns the uid of the target
4284 * if the URI permission grant should be performed; returns -1 if it is not
4285 * needed (for example targetPkg already has permission to access the URI).
4286 */
4287 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4288 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4290 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4291 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004292 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 }
4294
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004295 if (targetPkg != null) {
4296 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4297 "Checking grant " + targetPkg + " permission to " + uri);
4298 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004299
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004300 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301
4302 // If this is not a content: uri, we can't do anything with it.
4303 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004304 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004305 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004306 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 String name = uri.getAuthority();
4310 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004311 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 if (cpr != null) {
4313 pi = cpr.info;
4314 } else {
4315 try {
4316 pi = pm.resolveContentProvider(name,
4317 PackageManager.GET_URI_PERMISSION_PATTERNS);
4318 } catch (RemoteException ex) {
4319 }
4320 }
4321 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004322 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004323 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 }
4325
4326 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004327 if (targetPkg != null) {
4328 try {
4329 targetUid = pm.getPackageUid(targetPkg);
4330 if (targetUid < 0) {
4331 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4332 "Can't grant URI permission no uid for: " + targetPkg);
4333 return -1;
4334 }
4335 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004336 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004338 } else {
4339 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 }
4341
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004342 if (targetUid >= 0) {
4343 // First... does the target actually need this permission?
4344 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4345 // No need to grant the target this permission.
4346 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4347 "Target " + targetPkg + " already has full permission to " + uri);
4348 return -1;
4349 }
4350 } else {
4351 // First... there is no target package, so can anyone access it?
4352 boolean allowed = pi.exported;
4353 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4354 if (pi.readPermission != null) {
4355 allowed = false;
4356 }
4357 }
4358 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4359 if (pi.writePermission != null) {
4360 allowed = false;
4361 }
4362 }
4363 if (allowed) {
4364 return -1;
4365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 }
4367
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004368 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 if (!pi.grantUriPermissions) {
4370 throw new SecurityException("Provider " + pi.packageName
4371 + "/" + pi.name
4372 + " does not allow granting of Uri permissions (uri "
4373 + uri + ")");
4374 }
4375 if (pi.uriPermissionPatterns != null) {
4376 final int N = pi.uriPermissionPatterns.length;
4377 boolean allowed = false;
4378 for (int i=0; i<N; i++) {
4379 if (pi.uriPermissionPatterns[i] != null
4380 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4381 allowed = true;
4382 break;
4383 }
4384 }
4385 if (!allowed) {
4386 throw new SecurityException("Provider " + pi.packageName
4387 + "/" + pi.name
4388 + " does not allow granting of permission to path of Uri "
4389 + uri);
4390 }
4391 }
4392
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004393 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004395 if (callingUid != Process.myUid()) {
4396 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4397 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4398 throw new SecurityException("Uid " + callingUid
4399 + " does not have permission to uri " + uri);
4400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 }
4402 }
4403
Dianne Hackborn39792d22010-08-19 18:01:52 -07004404 return targetUid;
4405 }
4406
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004407 public int checkGrantUriPermission(int callingUid, String targetPkg,
4408 Uri uri, int modeFlags) {
4409 synchronized(this) {
4410 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4411 }
4412 }
4413
Dianne Hackborn39792d22010-08-19 18:01:52 -07004414 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4415 Uri uri, int modeFlags, UriPermissionOwner owner) {
4416 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4417 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4418 if (modeFlags == 0) {
4419 return;
4420 }
4421
4422 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 // to the uri, and the target doesn't. Let's now give this to
4424 // the target.
4425
Joe Onorato8a9b2202010-02-26 18:56:32 -08004426 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004427 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 HashMap<Uri, UriPermission> targetUris
4430 = mGrantedUriPermissions.get(targetUid);
4431 if (targetUris == null) {
4432 targetUris = new HashMap<Uri, UriPermission>();
4433 mGrantedUriPermissions.put(targetUid, targetUris);
4434 }
4435
4436 UriPermission perm = targetUris.get(uri);
4437 if (perm == null) {
4438 perm = new UriPermission(targetUid, uri);
4439 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004443 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 perm.globalModeFlags |= modeFlags;
4445 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004446 perm.readOwners.add(owner);
4447 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004449 perm.writeOwners.add(owner);
4450 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452 }
4453
Dianne Hackborn39792d22010-08-19 18:01:52 -07004454 void grantUriPermissionLocked(int callingUid,
4455 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004456 if (targetPkg == null) {
4457 throw new NullPointerException("targetPkg");
4458 }
4459
Dianne Hackborn39792d22010-08-19 18:01:52 -07004460 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4461 if (targetUid < 0) {
4462 return;
4463 }
4464
4465 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4466 }
4467
4468 /**
4469 * Like checkGrantUriPermissionLocked, but takes an Intent.
4470 */
4471 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4472 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004473 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004474 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004475 + " from " + intent + "; flags=0x"
4476 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4477
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004478 if (targetPkg == null) {
4479 throw new NullPointerException("targetPkg");
4480 }
4481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004483 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 }
4485 Uri data = intent.getData();
4486 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004487 return -1;
4488 }
4489 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4490 intent.getFlags());
4491 }
4492
4493 /**
4494 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4495 */
4496 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4497 String targetPkg, Intent intent, UriPermissionOwner owner) {
4498 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4499 intent.getFlags(), owner);
4500 }
4501
4502 void grantUriPermissionFromIntentLocked(int callingUid,
4503 String targetPkg, Intent intent, UriPermissionOwner owner) {
4504 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4505 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 return;
4507 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004508
4509 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 }
4511
4512 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4513 Uri uri, int modeFlags) {
4514 synchronized(this) {
4515 final ProcessRecord r = getRecordForAppLocked(caller);
4516 if (r == null) {
4517 throw new SecurityException("Unable to find app for caller "
4518 + caller
4519 + " when granting permission to uri " + uri);
4520 }
4521 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004522 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 }
4524 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004525 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 }
4527
4528 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4529 null);
4530 }
4531 }
4532
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004533 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4535 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4536 HashMap<Uri, UriPermission> perms
4537 = mGrantedUriPermissions.get(perm.uid);
4538 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004539 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004540 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541 perms.remove(perm.uri);
4542 if (perms.size() == 0) {
4543 mGrantedUriPermissions.remove(perm.uid);
4544 }
4545 }
4546 }
4547 }
4548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4550 int modeFlags) {
4551 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4552 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4553 if (modeFlags == 0) {
4554 return;
4555 }
4556
Joe Onorato8a9b2202010-02-26 18:56:32 -08004557 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004558 "Revoking all granted permissions to " + uri);
4559
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004560 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561
4562 final String authority = uri.getAuthority();
4563 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004564 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 if (cpr != null) {
4566 pi = cpr.info;
4567 } else {
4568 try {
4569 pi = pm.resolveContentProvider(authority,
4570 PackageManager.GET_URI_PERMISSION_PATTERNS);
4571 } catch (RemoteException ex) {
4572 }
4573 }
4574 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004575 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 return;
4577 }
4578
4579 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004580 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 // Right now, if you are not the original owner of the permission,
4582 // you are not allowed to revoke it.
4583 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4584 throw new SecurityException("Uid " + callingUid
4585 + " does not have permission to uri " + uri);
4586 //}
4587 }
4588
4589 // Go through all of the permissions and remove any that match.
4590 final List<String> SEGMENTS = uri.getPathSegments();
4591 if (SEGMENTS != null) {
4592 final int NS = SEGMENTS.size();
4593 int N = mGrantedUriPermissions.size();
4594 for (int i=0; i<N; i++) {
4595 HashMap<Uri, UriPermission> perms
4596 = mGrantedUriPermissions.valueAt(i);
4597 Iterator<UriPermission> it = perms.values().iterator();
4598 toploop:
4599 while (it.hasNext()) {
4600 UriPermission perm = it.next();
4601 Uri targetUri = perm.uri;
4602 if (!authority.equals(targetUri.getAuthority())) {
4603 continue;
4604 }
4605 List<String> targetSegments = targetUri.getPathSegments();
4606 if (targetSegments == null) {
4607 continue;
4608 }
4609 if (targetSegments.size() < NS) {
4610 continue;
4611 }
4612 for (int j=0; j<NS; j++) {
4613 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4614 continue toploop;
4615 }
4616 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004617 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004618 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 perm.clearModes(modeFlags);
4620 if (perm.modeFlags == 0) {
4621 it.remove();
4622 }
4623 }
4624 if (perms.size() == 0) {
4625 mGrantedUriPermissions.remove(
4626 mGrantedUriPermissions.keyAt(i));
4627 N--;
4628 i--;
4629 }
4630 }
4631 }
4632 }
4633
4634 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4635 int modeFlags) {
4636 synchronized(this) {
4637 final ProcessRecord r = getRecordForAppLocked(caller);
4638 if (r == null) {
4639 throw new SecurityException("Unable to find app for caller "
4640 + caller
4641 + " when revoking permission to uri " + uri);
4642 }
4643 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004644 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 return;
4646 }
4647
4648 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4649 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4650 if (modeFlags == 0) {
4651 return;
4652 }
4653
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004654 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655
4656 final String authority = uri.getAuthority();
4657 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004658 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 if (cpr != null) {
4660 pi = cpr.info;
4661 } else {
4662 try {
4663 pi = pm.resolveContentProvider(authority,
4664 PackageManager.GET_URI_PERMISSION_PATTERNS);
4665 } catch (RemoteException ex) {
4666 }
4667 }
4668 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004669 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 return;
4671 }
4672
4673 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4674 }
4675 }
4676
Dianne Hackborn7e269642010-08-25 19:50:20 -07004677 @Override
4678 public IBinder newUriPermissionOwner(String name) {
4679 synchronized(this) {
4680 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4681 return owner.getExternalTokenLocked();
4682 }
4683 }
4684
4685 @Override
4686 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4687 Uri uri, int modeFlags) {
4688 synchronized(this) {
4689 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4690 if (owner == null) {
4691 throw new IllegalArgumentException("Unknown owner: " + token);
4692 }
4693 if (fromUid != Binder.getCallingUid()) {
4694 if (Binder.getCallingUid() != Process.myUid()) {
4695 // Only system code can grant URI permissions on behalf
4696 // of other users.
4697 throw new SecurityException("nice try");
4698 }
4699 }
4700 if (targetPkg == null) {
4701 throw new IllegalArgumentException("null target");
4702 }
4703 if (uri == null) {
4704 throw new IllegalArgumentException("null uri");
4705 }
4706
4707 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4708 }
4709 }
4710
4711 @Override
4712 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4713 synchronized(this) {
4714 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4715 if (owner == null) {
4716 throw new IllegalArgumentException("Unknown owner: " + token);
4717 }
4718
4719 if (uri == null) {
4720 owner.removeUriPermissionsLocked(mode);
4721 } else {
4722 owner.removeUriPermissionLocked(uri, mode);
4723 }
4724 }
4725 }
4726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4728 synchronized (this) {
4729 ProcessRecord app =
4730 who != null ? getRecordForAppLocked(who) : null;
4731 if (app == null) return;
4732
4733 Message msg = Message.obtain();
4734 msg.what = WAIT_FOR_DEBUGGER_MSG;
4735 msg.obj = app;
4736 msg.arg1 = waiting ? 1 : 0;
4737 mHandler.sendMessage(msg);
4738 }
4739 }
4740
4741 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4742 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004743 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004745 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 }
4747
4748 // =========================================================
4749 // TASK MANAGEMENT
4750 // =========================================================
4751
4752 public List getTasks(int maxNum, int flags,
4753 IThumbnailReceiver receiver) {
4754 ArrayList list = new ArrayList();
4755
4756 PendingThumbnailsRecord pending = null;
4757 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004758 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759
4760 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004761 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4763 + ", receiver=" + receiver);
4764
4765 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4766 != PackageManager.PERMISSION_GRANTED) {
4767 if (receiver != null) {
4768 // If the caller wants to wait for pending thumbnails,
4769 // it ain't gonna get them.
4770 try {
4771 receiver.finished();
4772 } catch (RemoteException ex) {
4773 }
4774 }
4775 String msg = "Permission Denial: getTasks() from pid="
4776 + Binder.getCallingPid()
4777 + ", uid=" + Binder.getCallingUid()
4778 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004779 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 throw new SecurityException(msg);
4781 }
4782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004783 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004784 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004785 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004786 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 CharSequence topDescription = null;
4788 TaskRecord curTask = null;
4789 int numActivities = 0;
4790 int numRunning = 0;
4791 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004792 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004794 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795
4796 // Initialize state for next task if needed.
4797 if (top == null ||
4798 (top.state == ActivityState.INITIALIZING
4799 && top.task == r.task)) {
4800 top = r;
4801 topDescription = r.description;
4802 curTask = r.task;
4803 numActivities = numRunning = 0;
4804 }
4805
4806 // Add 'r' into the current task.
4807 numActivities++;
4808 if (r.app != null && r.app.thread != null) {
4809 numRunning++;
4810 }
4811 if (topDescription == null) {
4812 topDescription = r.description;
4813 }
4814
Joe Onorato8a9b2202010-02-26 18:56:32 -08004815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 TAG, r.intent.getComponent().flattenToShortString()
4817 + ": task=" + r.task);
4818
4819 // If the next one is a different task, generate a new
4820 // TaskInfo entry for what we have.
4821 if (next == null || next.task != curTask) {
4822 ActivityManager.RunningTaskInfo ci
4823 = new ActivityManager.RunningTaskInfo();
4824 ci.id = curTask.taskId;
4825 ci.baseActivity = r.intent.getComponent();
4826 ci.topActivity = top.intent.getComponent();
4827 ci.thumbnail = top.thumbnail;
4828 ci.description = topDescription;
4829 ci.numActivities = numActivities;
4830 ci.numRunning = numRunning;
4831 //System.out.println(
4832 // "#" + maxNum + ": " + " descr=" + ci.description);
4833 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 TAG, "State=" + top.state + "Idle=" + top.idle
4836 + " app=" + top.app
4837 + " thr=" + (top.app != null ? top.app.thread : null));
4838 if (top.state == ActivityState.RESUMED
4839 || top.state == ActivityState.PAUSING) {
4840 if (top.idle && top.app != null
4841 && top.app.thread != null) {
4842 topRecord = top;
4843 topThumbnail = top.app.thread;
4844 } else {
4845 top.thumbnailNeeded = true;
4846 }
4847 }
4848 if (pending == null) {
4849 pending = new PendingThumbnailsRecord(receiver);
4850 }
4851 pending.pendingRecords.add(top);
4852 }
4853 list.add(ci);
4854 maxNum--;
4855 top = null;
4856 }
4857 }
4858
4859 if (pending != null) {
4860 mPendingThumbnails.add(pending);
4861 }
4862 }
4863
Joe Onorato8a9b2202010-02-26 18:56:32 -08004864 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865
4866 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004867 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 try {
4869 topThumbnail.requestThumbnail(topRecord);
4870 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004871 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 sendPendingThumbnail(null, topRecord, null, null, true);
4873 }
4874 }
4875
4876 if (pending == null && receiver != null) {
4877 // In this case all thumbnails were available and the client
4878 // is being asked to be told when the remaining ones come in...
4879 // which is unusually, since the top-most currently running
4880 // activity should never have a canned thumbnail! Oh well.
4881 try {
4882 receiver.finished();
4883 } catch (RemoteException ex) {
4884 }
4885 }
4886
4887 return list;
4888 }
4889
4890 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4891 int flags) {
4892 synchronized (this) {
4893 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4894 "getRecentTasks()");
4895
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004896 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 final int N = mRecentTasks.size();
4899 ArrayList<ActivityManager.RecentTaskInfo> res
4900 = new ArrayList<ActivityManager.RecentTaskInfo>(
4901 maxNum < N ? maxNum : N);
4902 for (int i=0; i<N && maxNum > 0; i++) {
4903 TaskRecord tr = mRecentTasks.get(i);
4904 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4905 || (tr.intent == null)
4906 || ((tr.intent.getFlags()
4907 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4908 ActivityManager.RecentTaskInfo rti
4909 = new ActivityManager.RecentTaskInfo();
4910 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4911 rti.baseIntent = new Intent(
4912 tr.intent != null ? tr.intent : tr.affinityIntent);
4913 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004914
4915 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4916 // Check whether this activity is currently available.
4917 try {
4918 if (rti.origActivity != null) {
4919 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4920 continue;
4921 }
4922 } else if (rti.baseIntent != null) {
4923 if (pm.queryIntentActivities(rti.baseIntent,
4924 null, 0) == null) {
4925 continue;
4926 }
4927 }
4928 } catch (RemoteException e) {
4929 // Will never happen.
4930 }
4931 }
4932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 res.add(rti);
4934 maxNum--;
4935 }
4936 }
4937 return res;
4938 }
4939 }
4940
4941 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4942 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004943 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 TaskRecord jt = startTask;
4945
4946 // First look backwards
4947 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004948 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 if (r.task != jt) {
4950 jt = r.task;
4951 if (affinity.equals(jt.affinity)) {
4952 return j;
4953 }
4954 }
4955 }
4956
4957 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004958 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 jt = startTask;
4960 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004961 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 if (r.task != jt) {
4963 if (affinity.equals(jt.affinity)) {
4964 return j;
4965 }
4966 jt = r.task;
4967 }
4968 }
4969
4970 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004971 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 return N-1;
4973 }
4974
4975 return -1;
4976 }
4977
4978 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004979 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 */
4981 public void moveTaskToFront(int task) {
4982 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4983 "moveTaskToFront()");
4984
4985 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004986 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4987 Binder.getCallingUid(), "Task to front")) {
4988 return;
4989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 final long origId = Binder.clearCallingIdentity();
4991 try {
4992 int N = mRecentTasks.size();
4993 for (int i=0; i<N; i++) {
4994 TaskRecord tr = mRecentTasks.get(i);
4995 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004996 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997 return;
4998 }
4999 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005000 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5001 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005003 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 return;
5005 }
5006 }
5007 } finally {
5008 Binder.restoreCallingIdentity(origId);
5009 }
5010 }
5011 }
5012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 public void moveTaskToBack(int task) {
5014 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5015 "moveTaskToBack()");
5016
5017 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005018 if (mMainStack.mResumedActivity != null
5019 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005020 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5021 Binder.getCallingUid(), "Task to back")) {
5022 return;
5023 }
5024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005026 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 Binder.restoreCallingIdentity(origId);
5028 }
5029 }
5030
5031 /**
5032 * Moves an activity, and all of the other activities within the same task, to the bottom
5033 * of the history stack. The activity's order within the task is unchanged.
5034 *
5035 * @param token A reference to the activity we wish to move
5036 * @param nonRoot If false then this only works if the activity is the root
5037 * of a task; if true it will work for any activity in a task.
5038 * @return Returns true if the move completed, false if not.
5039 */
5040 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5041 synchronized(this) {
5042 final long origId = Binder.clearCallingIdentity();
5043 int taskId = getTaskForActivityLocked(token, !nonRoot);
5044 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005045 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 }
5047 Binder.restoreCallingIdentity(origId);
5048 }
5049 return false;
5050 }
5051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 public void moveTaskBackwards(int task) {
5053 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5054 "moveTaskBackwards()");
5055
5056 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005057 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5058 Binder.getCallingUid(), "Task backwards")) {
5059 return;
5060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 final long origId = Binder.clearCallingIdentity();
5062 moveTaskBackwardsLocked(task);
5063 Binder.restoreCallingIdentity(origId);
5064 }
5065 }
5066
5067 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005068 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 }
5070
5071 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5072 synchronized(this) {
5073 return getTaskForActivityLocked(token, onlyRoot);
5074 }
5075 }
5076
5077 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005078 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 TaskRecord lastTask = null;
5080 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005081 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 if (r == token) {
5083 if (!onlyRoot || lastTask != r.task) {
5084 return r.task.taskId;
5085 }
5086 return -1;
5087 }
5088 lastTask = r.task;
5089 }
5090
5091 return -1;
5092 }
5093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 public void finishOtherInstances(IBinder token, ComponentName className) {
5095 synchronized(this) {
5096 final long origId = Binder.clearCallingIdentity();
5097
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005098 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 TaskRecord lastTask = null;
5100 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005101 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 if (r.realActivity.equals(className)
5103 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005104 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 null, "others")) {
5106 i--;
5107 N--;
5108 }
5109 }
5110 lastTask = r.task;
5111 }
5112
5113 Binder.restoreCallingIdentity(origId);
5114 }
5115 }
5116
5117 // =========================================================
5118 // THUMBNAILS
5119 // =========================================================
5120
5121 public void reportThumbnail(IBinder token,
5122 Bitmap thumbnail, CharSequence description) {
5123 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5124 final long origId = Binder.clearCallingIdentity();
5125 sendPendingThumbnail(null, token, thumbnail, description, true);
5126 Binder.restoreCallingIdentity(origId);
5127 }
5128
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005129 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 Bitmap thumbnail, CharSequence description, boolean always) {
5131 TaskRecord task = null;
5132 ArrayList receivers = null;
5133
5134 //System.out.println("Send pending thumbnail: " + r);
5135
5136 synchronized(this) {
5137 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005138 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 if (index < 0) {
5140 return;
5141 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005142 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 }
5144 if (thumbnail == null) {
5145 thumbnail = r.thumbnail;
5146 description = r.description;
5147 }
5148 if (thumbnail == null && !always) {
5149 // If there is no thumbnail, and this entry is not actually
5150 // going away, then abort for now and pick up the next
5151 // thumbnail we get.
5152 return;
5153 }
5154 task = r.task;
5155
5156 int N = mPendingThumbnails.size();
5157 int i=0;
5158 while (i<N) {
5159 PendingThumbnailsRecord pr =
5160 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5161 //System.out.println("Looking in " + pr.pendingRecords);
5162 if (pr.pendingRecords.remove(r)) {
5163 if (receivers == null) {
5164 receivers = new ArrayList();
5165 }
5166 receivers.add(pr);
5167 if (pr.pendingRecords.size() == 0) {
5168 pr.finished = true;
5169 mPendingThumbnails.remove(i);
5170 N--;
5171 continue;
5172 }
5173 }
5174 i++;
5175 }
5176 }
5177
5178 if (receivers != null) {
5179 final int N = receivers.size();
5180 for (int i=0; i<N; i++) {
5181 try {
5182 PendingThumbnailsRecord pr =
5183 (PendingThumbnailsRecord)receivers.get(i);
5184 pr.receiver.newThumbnail(
5185 task != null ? task.taskId : -1, thumbnail, description);
5186 if (pr.finished) {
5187 pr.receiver.finished();
5188 }
5189 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005190 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 }
5192 }
5193 }
5194 }
5195
5196 // =========================================================
5197 // CONTENT PROVIDERS
5198 // =========================================================
5199
5200 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5201 List providers = null;
5202 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005203 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005205 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 } catch (RemoteException ex) {
5207 }
5208 if (providers != null) {
5209 final int N = providers.size();
5210 for (int i=0; i<N; i++) {
5211 ProviderInfo cpi =
5212 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005213 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 if (cpr == null) {
5215 cpr = new ContentProviderRecord(cpi, app.info);
5216 mProvidersByClass.put(cpi.name, cpr);
5217 }
5218 app.pubProviders.put(cpi.name, cpr);
5219 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005220 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 }
5222 }
5223 return providers;
5224 }
5225
5226 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005227 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5229 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5230 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5231 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005232 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 return null;
5234 }
5235 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5236 cpi.exported ? -1 : cpi.applicationInfo.uid)
5237 == PackageManager.PERMISSION_GRANTED) {
5238 return null;
5239 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005240
5241 PathPermission[] pps = cpi.pathPermissions;
5242 if (pps != null) {
5243 int i = pps.length;
5244 while (i > 0) {
5245 i--;
5246 PathPermission pp = pps[i];
5247 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5248 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005249 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005250 return null;
5251 }
5252 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5253 cpi.exported ? -1 : cpi.applicationInfo.uid)
5254 == PackageManager.PERMISSION_GRANTED) {
5255 return null;
5256 }
5257 }
5258 }
5259
Dianne Hackbornb424b632010-08-18 15:59:05 -07005260 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5261 if (perms != null) {
5262 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5263 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5264 return null;
5265 }
5266 }
5267 }
5268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 String msg = "Permission Denial: opening provider " + cpi.name
5270 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5271 + ", uid=" + callingUid + ") requires "
5272 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005273 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 return msg;
5275 }
5276
5277 private final ContentProviderHolder getContentProviderImpl(
5278 IApplicationThread caller, String name) {
5279 ContentProviderRecord cpr;
5280 ProviderInfo cpi = null;
5281
5282 synchronized(this) {
5283 ProcessRecord r = null;
5284 if (caller != null) {
5285 r = getRecordForAppLocked(caller);
5286 if (r == null) {
5287 throw new SecurityException(
5288 "Unable to find app for caller " + caller
5289 + " (pid=" + Binder.getCallingPid()
5290 + ") when getting content provider " + name);
5291 }
5292 }
5293
5294 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005295 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 if (cpr != null) {
5297 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005298 String msg;
5299 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5300 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302
5303 if (r != null && cpr.canRunHere(r)) {
5304 // This provider has been published or is in the process
5305 // of being published... but it is also allowed to run
5306 // in the caller's process, so don't make a connection
5307 // and just let the caller instantiate its own instance.
5308 if (cpr.provider != null) {
5309 // don't give caller the provider object, it needs
5310 // to make its own.
5311 cpr = new ContentProviderRecord(cpr);
5312 }
5313 return cpr;
5314 }
5315
5316 final long origId = Binder.clearCallingIdentity();
5317
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005318 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319 // return it right away.
5320 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005321 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005322 "Adding provider requested by "
5323 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005324 + cpr.info.processName);
5325 Integer cnt = r.conProviders.get(cpr);
5326 if (cnt == null) {
5327 r.conProviders.put(cpr, new Integer(1));
5328 } else {
5329 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005332 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5333 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005334 // make sure to count it as being accessed and thus
5335 // back up on the LRU list. This is good because
5336 // content providers are often expensive to start.
5337 updateLruProcessLocked(cpr.app, false, true);
5338 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005339 } else {
5340 cpr.externals++;
5341 }
5342
5343 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 updateOomAdjLocked(cpr.app);
5345 }
5346
5347 Binder.restoreCallingIdentity(origId);
5348
5349 } else {
5350 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005351 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005352 resolveContentProvider(name,
5353 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 } catch (RemoteException ex) {
5355 }
5356 if (cpi == null) {
5357 return null;
5358 }
5359
Dianne Hackbornb424b632010-08-18 15:59:05 -07005360 String msg;
5361 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5362 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 }
5364
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005365 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005366 && !cpi.processName.equals("system")) {
5367 // If this content provider does not run in the system
5368 // process, and the system is not yet ready to run other
5369 // processes, then fail fast instead of hanging.
5370 throw new IllegalArgumentException(
5371 "Attempt to launch content provider before system ready");
5372 }
5373
Dianne Hackborn860755f2010-06-03 18:47:52 -07005374 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 final boolean firstClass = cpr == null;
5376 if (firstClass) {
5377 try {
5378 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005379 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005380 getApplicationInfo(
5381 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005382 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 + cpi.name);
5386 return null;
5387 }
5388 cpr = new ContentProviderRecord(cpi, ai);
5389 } catch (RemoteException ex) {
5390 // pm is in same process, this will never happen.
5391 }
5392 }
5393
5394 if (r != null && cpr.canRunHere(r)) {
5395 // If this is a multiprocess provider, then just return its
5396 // info and allow the caller to instantiate it. Only do
5397 // this if the provider is the same user as the caller's
5398 // process, or can run as root (so can be in any process).
5399 return cpr;
5400 }
5401
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005402 if (DEBUG_PROVIDER) {
5403 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005404 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005405 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 }
5407
5408 // This is single process, and our app is now connecting to it.
5409 // See if we are already in the process of launching this
5410 // provider.
5411 final int N = mLaunchingProviders.size();
5412 int i;
5413 for (i=0; i<N; i++) {
5414 if (mLaunchingProviders.get(i) == cpr) {
5415 break;
5416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 }
5418
5419 // If the provider is not already being launched, then get it
5420 // started.
5421 if (i >= N) {
5422 final long origId = Binder.clearCallingIdentity();
5423 ProcessRecord proc = startProcessLocked(cpi.processName,
5424 cpr.appInfo, false, 0, "content provider",
5425 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005426 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005428 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 + cpi.applicationInfo.packageName + "/"
5430 + cpi.applicationInfo.uid + " for provider "
5431 + name + ": process is bad");
5432 return null;
5433 }
5434 cpr.launchingApp = proc;
5435 mLaunchingProviders.add(cpr);
5436 Binder.restoreCallingIdentity(origId);
5437 }
5438
5439 // Make sure the provider is published (the same provider class
5440 // may be published under multiple names).
5441 if (firstClass) {
5442 mProvidersByClass.put(cpi.name, cpr);
5443 }
5444 mProvidersByName.put(name, cpr);
5445
5446 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005447 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005448 "Adding provider requested by "
5449 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005450 + cpr.info.processName);
5451 Integer cnt = r.conProviders.get(cpr);
5452 if (cnt == null) {
5453 r.conProviders.put(cpr, new Integer(1));
5454 } else {
5455 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 cpr.clients.add(r);
5458 } else {
5459 cpr.externals++;
5460 }
5461 }
5462 }
5463
5464 // Wait for the provider to be published...
5465 synchronized (cpr) {
5466 while (cpr.provider == null) {
5467 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005468 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 + cpi.applicationInfo.packageName + "/"
5470 + cpi.applicationInfo.uid + " for provider "
5471 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005472 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 cpi.applicationInfo.packageName,
5474 cpi.applicationInfo.uid, name);
5475 return null;
5476 }
5477 try {
5478 cpr.wait();
5479 } catch (InterruptedException ex) {
5480 }
5481 }
5482 }
5483 return cpr;
5484 }
5485
5486 public final ContentProviderHolder getContentProvider(
5487 IApplicationThread caller, String name) {
5488 if (caller == null) {
5489 String msg = "null IApplicationThread when getting content provider "
5490 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005491 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 throw new SecurityException(msg);
5493 }
5494
5495 return getContentProviderImpl(caller, name);
5496 }
5497
5498 private ContentProviderHolder getContentProviderExternal(String name) {
5499 return getContentProviderImpl(null, name);
5500 }
5501
5502 /**
5503 * Drop a content provider from a ProcessRecord's bookkeeping
5504 * @param cpr
5505 */
5506 public void removeContentProvider(IApplicationThread caller, String name) {
5507 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005508 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005510 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005511 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005512 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 return;
5514 }
5515 final ProcessRecord r = getRecordForAppLocked(caller);
5516 if (r == null) {
5517 throw new SecurityException(
5518 "Unable to find app for caller " + caller +
5519 " when removing content provider " + name);
5520 }
5521 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005522 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005523 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005524 + r.info.processName + " from process "
5525 + localCpr.appInfo.processName);
5526 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005528 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005529 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 return;
5531 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005532 Integer cnt = r.conProviders.get(localCpr);
5533 if (cnt == null || cnt.intValue() <= 1) {
5534 localCpr.clients.remove(r);
5535 r.conProviders.remove(localCpr);
5536 } else {
5537 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 }
5540 updateOomAdjLocked();
5541 }
5542 }
5543
5544 private void removeContentProviderExternal(String name) {
5545 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005546 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005547 if(cpr == null) {
5548 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005549 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 return;
5551 }
5552
5553 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005554 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 localCpr.externals--;
5556 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005557 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 }
5559 updateOomAdjLocked();
5560 }
5561 }
5562
5563 public final void publishContentProviders(IApplicationThread caller,
5564 List<ContentProviderHolder> providers) {
5565 if (providers == null) {
5566 return;
5567 }
5568
5569 synchronized(this) {
5570 final ProcessRecord r = getRecordForAppLocked(caller);
5571 if (r == null) {
5572 throw new SecurityException(
5573 "Unable to find app for caller " + caller
5574 + " (pid=" + Binder.getCallingPid()
5575 + ") when publishing content providers");
5576 }
5577
5578 final long origId = Binder.clearCallingIdentity();
5579
5580 final int N = providers.size();
5581 for (int i=0; i<N; i++) {
5582 ContentProviderHolder src = providers.get(i);
5583 if (src == null || src.info == null || src.provider == null) {
5584 continue;
5585 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005586 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 if (dst != null) {
5588 mProvidersByClass.put(dst.info.name, dst);
5589 String names[] = dst.info.authority.split(";");
5590 for (int j = 0; j < names.length; j++) {
5591 mProvidersByName.put(names[j], dst);
5592 }
5593
5594 int NL = mLaunchingProviders.size();
5595 int j;
5596 for (j=0; j<NL; j++) {
5597 if (mLaunchingProviders.get(j) == dst) {
5598 mLaunchingProviders.remove(j);
5599 j--;
5600 NL--;
5601 }
5602 }
5603 synchronized (dst) {
5604 dst.provider = src.provider;
5605 dst.app = r;
5606 dst.notifyAll();
5607 }
5608 updateOomAdjLocked(r);
5609 }
5610 }
5611
5612 Binder.restoreCallingIdentity(origId);
5613 }
5614 }
5615
5616 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005617 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005618 synchronized (mSelf) {
5619 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5620 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005621 if (providers != null) {
5622 for (int i=providers.size()-1; i>=0; i--) {
5623 ProviderInfo pi = (ProviderInfo)providers.get(i);
5624 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5625 Slog.w(TAG, "Not installing system proc provider " + pi.name
5626 + ": not system .apk");
5627 providers.remove(i);
5628 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005629 }
5630 }
5631 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005632 if (providers != null) {
5633 mSystemThread.installSystemProviders(providers);
5634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 }
5636
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005637 /**
5638 * Allows app to retrieve the MIME type of a URI without having permission
5639 * to access its content provider.
5640 *
5641 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5642 *
5643 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5644 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5645 */
5646 public String getProviderMimeType(Uri uri) {
5647 final String name = uri.getAuthority();
5648 final long ident = Binder.clearCallingIdentity();
5649 ContentProviderHolder holder = null;
5650
5651 try {
5652 holder = getContentProviderExternal(name);
5653 if (holder != null) {
5654 return holder.provider.getType(uri);
5655 }
5656 } catch (RemoteException e) {
5657 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5658 return null;
5659 } finally {
5660 if (holder != null) {
5661 removeContentProviderExternal(name);
5662 }
5663 Binder.restoreCallingIdentity(ident);
5664 }
5665
5666 return null;
5667 }
5668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 // =========================================================
5670 // GLOBAL MANAGEMENT
5671 // =========================================================
5672
5673 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5674 ApplicationInfo info, String customProcess) {
5675 String proc = customProcess != null ? customProcess : info.processName;
5676 BatteryStatsImpl.Uid.Proc ps = null;
5677 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5678 synchronized (stats) {
5679 ps = stats.getProcessStatsLocked(info.uid, proc);
5680 }
5681 return new ProcessRecord(ps, thread, info, proc);
5682 }
5683
5684 final ProcessRecord addAppLocked(ApplicationInfo info) {
5685 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5686
5687 if (app == null) {
5688 app = newProcessRecordLocked(null, info, null);
5689 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005690 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 }
5692
5693 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5694 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5695 app.persistent = true;
5696 app.maxAdj = CORE_SERVER_ADJ;
5697 }
5698 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5699 mPersistentStartingProcesses.add(app);
5700 startProcessLocked(app, "added application", app.processName);
5701 }
5702
5703 return app;
5704 }
5705
5706 public void unhandledBack() {
5707 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5708 "unhandledBack()");
5709
5710 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005711 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005712 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 TAG, "Performing unhandledBack(): stack size = " + count);
5714 if (count > 1) {
5715 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005716 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5718 Binder.restoreCallingIdentity(origId);
5719 }
5720 }
5721 }
5722
5723 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5724 String name = uri.getAuthority();
5725 ContentProviderHolder cph = getContentProviderExternal(name);
5726 ParcelFileDescriptor pfd = null;
5727 if (cph != null) {
5728 // We record the binder invoker's uid in thread-local storage before
5729 // going to the content provider to open the file. Later, in the code
5730 // that handles all permissions checks, we look for this uid and use
5731 // that rather than the Activity Manager's own uid. The effect is that
5732 // we do the check against the caller's permissions even though it looks
5733 // to the content provider like the Activity Manager itself is making
5734 // the request.
5735 sCallerIdentity.set(new Identity(
5736 Binder.getCallingPid(), Binder.getCallingUid()));
5737 try {
5738 pfd = cph.provider.openFile(uri, "r");
5739 } catch (FileNotFoundException e) {
5740 // do nothing; pfd will be returned null
5741 } finally {
5742 // Ensure that whatever happens, we clean up the identity state
5743 sCallerIdentity.remove();
5744 }
5745
5746 // We've got the fd now, so we're done with the provider.
5747 removeContentProviderExternal(name);
5748 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005749 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 }
5751 return pfd;
5752 }
5753
5754 public void goingToSleep() {
5755 synchronized(this) {
5756 mSleeping = true;
5757 mWindowManager.setEventDispatching(false);
5758
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005759 if (mMainStack.mResumedActivity != null) {
5760 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005761 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005762 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005763 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005764
5765 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005766 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005767 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5768 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005769 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770 }
5771 }
5772
Dianne Hackborn55280a92009-05-07 15:53:46 -07005773 public boolean shutdown(int timeout) {
5774 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5775 != PackageManager.PERMISSION_GRANTED) {
5776 throw new SecurityException("Requires permission "
5777 + android.Manifest.permission.SHUTDOWN);
5778 }
5779
5780 boolean timedout = false;
5781
5782 synchronized(this) {
5783 mShuttingDown = true;
5784 mWindowManager.setEventDispatching(false);
5785
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005786 if (mMainStack.mResumedActivity != null) {
5787 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005788 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005789 while (mMainStack.mResumedActivity != null
5790 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005791 long delay = endTime - System.currentTimeMillis();
5792 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005793 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005794 timedout = true;
5795 break;
5796 }
5797 try {
5798 this.wait();
5799 } catch (InterruptedException e) {
5800 }
5801 }
5802 }
5803 }
5804
5805 mUsageStatsService.shutdown();
5806 mBatteryStatsService.shutdown();
5807
5808 return timedout;
5809 }
5810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 public void wakingUp() {
5812 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005813 if (mMainStack.mGoingToSleep.isHeld()) {
5814 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 }
5816 mWindowManager.setEventDispatching(true);
5817 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005818 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 }
5820 }
5821
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005822 public void stopAppSwitches() {
5823 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5824 != PackageManager.PERMISSION_GRANTED) {
5825 throw new SecurityException("Requires permission "
5826 + android.Manifest.permission.STOP_APP_SWITCHES);
5827 }
5828
5829 synchronized(this) {
5830 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5831 + APP_SWITCH_DELAY_TIME;
5832 mDidAppSwitch = false;
5833 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5834 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5835 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5836 }
5837 }
5838
5839 public void resumeAppSwitches() {
5840 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5841 != PackageManager.PERMISSION_GRANTED) {
5842 throw new SecurityException("Requires permission "
5843 + android.Manifest.permission.STOP_APP_SWITCHES);
5844 }
5845
5846 synchronized(this) {
5847 // Note that we don't execute any pending app switches... we will
5848 // let those wait until either the timeout, or the next start
5849 // activity request.
5850 mAppSwitchesAllowedTime = 0;
5851 }
5852 }
5853
5854 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5855 String name) {
5856 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5857 return true;
5858 }
5859
5860 final int perm = checkComponentPermission(
5861 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5862 callingUid, -1);
5863 if (perm == PackageManager.PERMISSION_GRANTED) {
5864 return true;
5865 }
5866
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005868 return false;
5869 }
5870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 public void setDebugApp(String packageName, boolean waitForDebugger,
5872 boolean persistent) {
5873 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5874 "setDebugApp()");
5875
5876 // Note that this is not really thread safe if there are multiple
5877 // callers into it at the same time, but that's not a situation we
5878 // care about.
5879 if (persistent) {
5880 final ContentResolver resolver = mContext.getContentResolver();
5881 Settings.System.putString(
5882 resolver, Settings.System.DEBUG_APP,
5883 packageName);
5884 Settings.System.putInt(
5885 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5886 waitForDebugger ? 1 : 0);
5887 }
5888
5889 synchronized (this) {
5890 if (!persistent) {
5891 mOrigDebugApp = mDebugApp;
5892 mOrigWaitForDebugger = mWaitForDebugger;
5893 }
5894 mDebugApp = packageName;
5895 mWaitForDebugger = waitForDebugger;
5896 mDebugTransient = !persistent;
5897 if (packageName != null) {
5898 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005899 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 Binder.restoreCallingIdentity(origId);
5901 }
5902 }
5903 }
5904
5905 public void setAlwaysFinish(boolean enabled) {
5906 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5907 "setAlwaysFinish()");
5908
5909 Settings.System.putInt(
5910 mContext.getContentResolver(),
5911 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5912
5913 synchronized (this) {
5914 mAlwaysFinishActivities = enabled;
5915 }
5916 }
5917
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005918 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005920 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005922 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 }
5924 }
5925
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005926 public boolean isUserAMonkey() {
5927 // For now the fact that there is a controller implies
5928 // we have a monkey.
5929 synchronized (this) {
5930 return mController != null;
5931 }
5932 }
5933
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005934 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005935 synchronized (this) {
5936 mWatchers.register(watcher);
5937 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005938 }
5939
5940 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005941 synchronized (this) {
5942 mWatchers.unregister(watcher);
5943 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005944 }
5945
Daniel Sandler69a48172010-06-23 16:29:36 -04005946 public void setImmersive(IBinder token, boolean immersive) {
5947 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005948 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005949 if (index < 0) {
5950 throw new IllegalArgumentException();
5951 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005952 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005953 r.immersive = immersive;
5954 }
5955 }
5956
5957 public boolean isImmersive(IBinder token) {
5958 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005959 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005960 if (index < 0) {
5961 throw new IllegalArgumentException();
5962 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005963 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005964 return r.immersive;
5965 }
5966 }
5967
5968 public boolean isTopActivityImmersive() {
5969 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005970 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005971 return (r != null) ? r.immersive : false;
5972 }
5973 }
5974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 public final void enterSafeMode() {
5976 synchronized(this) {
5977 // It only makes sense to do this before the system is ready
5978 // and started launching other packages.
5979 if (!mSystemReady) {
5980 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005981 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005982 } catch (RemoteException e) {
5983 }
5984
5985 View v = LayoutInflater.from(mContext).inflate(
5986 com.android.internal.R.layout.safe_mode, null);
5987 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07005988 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5990 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5991 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5992 lp.format = v.getBackground().getOpacity();
5993 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5994 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5995 ((WindowManager)mContext.getSystemService(
5996 Context.WINDOW_SERVICE)).addView(v, lp);
5997 }
5998 }
5999 }
6000
6001 public void noteWakeupAlarm(IIntentSender sender) {
6002 if (!(sender instanceof PendingIntentRecord)) {
6003 return;
6004 }
6005 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6006 synchronized (stats) {
6007 if (mBatteryStatsService.isOnBattery()) {
6008 mBatteryStatsService.enforceCallingPermission();
6009 PendingIntentRecord rec = (PendingIntentRecord)sender;
6010 int MY_UID = Binder.getCallingUid();
6011 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6012 BatteryStatsImpl.Uid.Pkg pkg =
6013 stats.getPackageStatsLocked(uid, rec.key.packageName);
6014 pkg.incWakeupsLocked();
6015 }
6016 }
6017 }
6018
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006019 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006021 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006023 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006024 // XXX Note: don't acquire main activity lock here, because the window
6025 // manager calls in with its locks held.
6026
6027 boolean killed = false;
6028 synchronized (mPidsSelfLocked) {
6029 int[] types = new int[pids.length];
6030 int worstType = 0;
6031 for (int i=0; i<pids.length; i++) {
6032 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6033 if (proc != null) {
6034 int type = proc.setAdj;
6035 types[i] = type;
6036 if (type > worstType) {
6037 worstType = type;
6038 }
6039 }
6040 }
6041
6042 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6043 // then constrain it so we will kill all hidden procs.
6044 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6045 worstType = HIDDEN_APP_MIN_ADJ;
6046 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006047 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 for (int i=0; i<pids.length; i++) {
6049 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6050 if (proc == null) {
6051 continue;
6052 }
6053 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006054 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006055 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006056 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6057 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006059 proc.killedBackground = true;
6060 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006061 }
6062 }
6063 }
6064 return killed;
6065 }
6066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 public final void startRunning(String pkg, String cls, String action,
6068 String data) {
6069 synchronized(this) {
6070 if (mStartRunning) {
6071 return;
6072 }
6073 mStartRunning = true;
6074 mTopComponent = pkg != null && cls != null
6075 ? new ComponentName(pkg, cls) : null;
6076 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6077 mTopData = data;
6078 if (!mSystemReady) {
6079 return;
6080 }
6081 }
6082
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006083 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 }
6085
6086 private void retrieveSettings() {
6087 final ContentResolver resolver = mContext.getContentResolver();
6088 String debugApp = Settings.System.getString(
6089 resolver, Settings.System.DEBUG_APP);
6090 boolean waitForDebugger = Settings.System.getInt(
6091 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6092 boolean alwaysFinishActivities = Settings.System.getInt(
6093 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6094
6095 Configuration configuration = new Configuration();
6096 Settings.System.getConfiguration(resolver, configuration);
6097
6098 synchronized (this) {
6099 mDebugApp = mOrigDebugApp = debugApp;
6100 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6101 mAlwaysFinishActivities = alwaysFinishActivities;
6102 // This happens before any activities are started, so we can
6103 // change mConfiguration in-place.
6104 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006105 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006106 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 }
6108 }
6109
6110 public boolean testIsSystemReady() {
6111 // no need to synchronize(this) just to read & return the value
6112 return mSystemReady;
6113 }
6114
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006115 private static File getCalledPreBootReceiversFile() {
6116 File dataDir = Environment.getDataDirectory();
6117 File systemDir = new File(dataDir, "system");
6118 File fname = new File(systemDir, "called_pre_boots.dat");
6119 return fname;
6120 }
6121
6122 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6123 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6124 File file = getCalledPreBootReceiversFile();
6125 FileInputStream fis = null;
6126 try {
6127 fis = new FileInputStream(file);
6128 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6129 int vers = dis.readInt();
6130 String codename = dis.readUTF();
6131 if (vers == android.os.Build.VERSION.SDK_INT
6132 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6133 int num = dis.readInt();
6134 while (num > 0) {
6135 num--;
6136 String pkg = dis.readUTF();
6137 String cls = dis.readUTF();
6138 lastDoneReceivers.add(new ComponentName(pkg, cls));
6139 }
6140 }
6141 } catch (FileNotFoundException e) {
6142 } catch (IOException e) {
6143 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6144 } finally {
6145 if (fis != null) {
6146 try {
6147 fis.close();
6148 } catch (IOException e) {
6149 }
6150 }
6151 }
6152 return lastDoneReceivers;
6153 }
6154
6155 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6156 File file = getCalledPreBootReceiversFile();
6157 FileOutputStream fos = null;
6158 DataOutputStream dos = null;
6159 try {
6160 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6161 fos = new FileOutputStream(file);
6162 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6163 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6164 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6165 dos.writeInt(list.size());
6166 for (int i=0; i<list.size(); i++) {
6167 dos.writeUTF(list.get(i).getPackageName());
6168 dos.writeUTF(list.get(i).getClassName());
6169 }
6170 } catch (IOException e) {
6171 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6172 file.delete();
6173 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006174 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006175 if (dos != null) {
6176 try {
6177 dos.close();
6178 } catch (IOException e) {
6179 // TODO Auto-generated catch block
6180 e.printStackTrace();
6181 }
6182 }
6183 }
6184 }
6185
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006186 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006187 // In the simulator, startRunning will never have been called, which
6188 // normally sets a few crucial variables. Do it here instead.
6189 if (!Process.supportsProcesses()) {
6190 mStartRunning = true;
6191 mTopAction = Intent.ACTION_MAIN;
6192 }
6193
6194 synchronized(this) {
6195 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006196 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 return;
6198 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006199
6200 // Check to see if there are any update receivers to run.
6201 if (!mDidUpdate) {
6202 if (mWaitingUpdate) {
6203 return;
6204 }
6205 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6206 List<ResolveInfo> ris = null;
6207 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006208 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006209 intent, null, 0);
6210 } catch (RemoteException e) {
6211 }
6212 if (ris != null) {
6213 for (int i=ris.size()-1; i>=0; i--) {
6214 if ((ris.get(i).activityInfo.applicationInfo.flags
6215 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6216 ris.remove(i);
6217 }
6218 }
6219 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006220
6221 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6222
6223 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006224 for (int i=0; i<ris.size(); i++) {
6225 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006226 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6227 if (lastDoneReceivers.contains(comp)) {
6228 ris.remove(i);
6229 i--;
6230 }
6231 }
6232
6233 for (int i=0; i<ris.size(); i++) {
6234 ActivityInfo ai = ris.get(i).activityInfo;
6235 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6236 doneReceivers.add(comp);
6237 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006238 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006239 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006240 finisher = new IIntentReceiver.Stub() {
6241 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006242 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006243 boolean sticky) {
6244 // The raw IIntentReceiver interface is called
6245 // with the AM lock held, so redispatch to
6246 // execute our code without the lock.
6247 mHandler.post(new Runnable() {
6248 public void run() {
6249 synchronized (ActivityManagerService.this) {
6250 mDidUpdate = true;
6251 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006252 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006253 systemReady(goingCallback);
6254 }
6255 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006256 }
6257 };
6258 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006259 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006260 broadcastIntentLocked(null, null, intent, null, finisher,
6261 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006262 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006263 mWaitingUpdate = true;
6264 }
6265 }
6266 }
6267 if (mWaitingUpdate) {
6268 return;
6269 }
6270 mDidUpdate = true;
6271 }
6272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 mSystemReady = true;
6274 if (!mStartRunning) {
6275 return;
6276 }
6277 }
6278
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006279 ArrayList<ProcessRecord> procsToKill = null;
6280 synchronized(mPidsSelfLocked) {
6281 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6282 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6283 if (!isAllowedWhileBooting(proc.info)){
6284 if (procsToKill == null) {
6285 procsToKill = new ArrayList<ProcessRecord>();
6286 }
6287 procsToKill.add(proc);
6288 }
6289 }
6290 }
6291
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006292 synchronized(this) {
6293 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006294 for (int i=procsToKill.size()-1; i>=0; i--) {
6295 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006296 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006297 removeProcessLocked(proc, true);
6298 }
6299 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006300
6301 // Now that we have cleaned up any update processes, we
6302 // are ready to start launching real processes and know that
6303 // we won't trample on them any more.
6304 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006305 }
6306
Joe Onorato8a9b2202010-02-26 18:56:32 -08006307 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006308 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309 SystemClock.uptimeMillis());
6310
6311 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006312 // Make sure we have no pre-ready processes sitting around.
6313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6315 ResolveInfo ri = mContext.getPackageManager()
6316 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006317 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 CharSequence errorMsg = null;
6319 if (ri != null) {
6320 ActivityInfo ai = ri.activityInfo;
6321 ApplicationInfo app = ai.applicationInfo;
6322 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6323 mTopAction = Intent.ACTION_FACTORY_TEST;
6324 mTopData = null;
6325 mTopComponent = new ComponentName(app.packageName,
6326 ai.name);
6327 } else {
6328 errorMsg = mContext.getResources().getText(
6329 com.android.internal.R.string.factorytest_not_system);
6330 }
6331 } else {
6332 errorMsg = mContext.getResources().getText(
6333 com.android.internal.R.string.factorytest_no_action);
6334 }
6335 if (errorMsg != null) {
6336 mTopAction = null;
6337 mTopData = null;
6338 mTopComponent = null;
6339 Message msg = Message.obtain();
6340 msg.what = SHOW_FACTORY_ERROR_MSG;
6341 msg.getData().putCharSequence("msg", errorMsg);
6342 mHandler.sendMessage(msg);
6343 }
6344 }
6345 }
6346
6347 retrieveSettings();
6348
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006349 if (goingCallback != null) goingCallback.run();
6350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 synchronized (this) {
6352 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6353 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006354 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006355 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 if (apps != null) {
6357 int N = apps.size();
6358 int i;
6359 for (i=0; i<N; i++) {
6360 ApplicationInfo info
6361 = (ApplicationInfo)apps.get(i);
6362 if (info != null &&
6363 !info.packageName.equals("android")) {
6364 addAppLocked(info);
6365 }
6366 }
6367 }
6368 } catch (RemoteException ex) {
6369 // pm is in same process, this will never happen.
6370 }
6371 }
6372
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006373 // Start up initial activity.
6374 mBooting = true;
6375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006377 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 Message msg = Message.obtain();
6379 msg.what = SHOW_UID_ERROR_MSG;
6380 mHandler.sendMessage(msg);
6381 }
6382 } catch (RemoteException e) {
6383 }
6384
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006385 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 }
6387 }
6388
Dan Egnorb7f03672009-12-09 16:22:32 -08006389 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006390 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006392 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006393 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006394 startAppProblemLocked(app);
6395 app.stopFreezingAllLocked();
6396 return handleAppCrashLocked(app);
6397 }
6398
Dan Egnorb7f03672009-12-09 16:22:32 -08006399 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006400 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006402 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006403 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6404 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 startAppProblemLocked(app);
6406 app.stopFreezingAllLocked();
6407 }
6408
6409 /**
6410 * Generate a process error record, suitable for attachment to a ProcessRecord.
6411 *
6412 * @param app The ProcessRecord in which the error occurred.
6413 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6414 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006415 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 * @param shortMsg Short message describing the crash.
6417 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006418 * @param stackTrace Full crash stack trace, may be null.
6419 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 * @return Returns a fully-formed AppErrorStateInfo record.
6421 */
6422 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006423 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 report.condition = condition;
6427 report.processName = app.processName;
6428 report.pid = app.pid;
6429 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006430 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 report.shortMsg = shortMsg;
6432 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006433 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434
6435 return report;
6436 }
6437
Dan Egnor42471dd2010-01-07 17:25:22 -08006438 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 synchronized (this) {
6440 app.crashing = false;
6441 app.crashingReport = null;
6442 app.notResponding = false;
6443 app.notRespondingReport = null;
6444 if (app.anrDialog == fromDialog) {
6445 app.anrDialog = null;
6446 }
6447 if (app.waitDialog == fromDialog) {
6448 app.waitDialog = null;
6449 }
6450 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006451 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006452 Slog.i(ActivityManagerService.TAG, "Killing "
6453 + app.processName + " (pid=" + app.pid + "): user's request");
6454 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6455 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006456 Process.killProcess(app.pid);
6457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006458 }
6459 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006460
Dan Egnorb7f03672009-12-09 16:22:32 -08006461 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 long now = SystemClock.uptimeMillis();
6463
6464 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6465 app.info.uid);
6466 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6467 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006468 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006470 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 app.info.processName, app.info.uid);
6472 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006473 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6474 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006475 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006476 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006478 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006479 }
6480 }
6481 if (!app.persistent) {
6482 // We don't want to start this process again until the user
6483 // explicitly does so... but for persistent process, we really
6484 // need to keep it running. If a persistent process is actually
6485 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006486 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006487 app.info.processName);
6488 mBadProcesses.put(app.info.processName, app.info.uid, now);
6489 app.bad = true;
6490 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6491 app.removed = true;
6492 removeProcessLocked(app, false);
6493 return false;
6494 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006495 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006496 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006497 if (r.app == app) {
6498 // If the top running activity is from this crashing
6499 // process, then terminate it to avoid getting in a loop.
6500 Slog.w(TAG, " Force finishing activity "
6501 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006502 int index = mMainStack.indexOfTokenLocked(r);
6503 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006504 Activity.RESULT_CANCELED, null, "crashed");
6505 // Also terminate an activities below it that aren't yet
6506 // stopped, to avoid a situation where one will get
6507 // re-start our crashing activity once it gets resumed again.
6508 index--;
6509 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006510 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006511 if (r.state == ActivityState.RESUMED
6512 || r.state == ActivityState.PAUSING
6513 || r.state == ActivityState.PAUSED) {
6514 if (!r.isHomeActivity) {
6515 Slog.w(TAG, " Force finishing activity "
6516 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006517 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006518 Activity.RESULT_CANCELED, null, "crashed");
6519 }
6520 }
6521 }
6522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 }
6524
6525 // Bump up the crash count of any services currently running in the proc.
6526 if (app.services.size() != 0) {
6527 // Any services running in the application need to be placed
6528 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006529 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006531 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006532 sr.crashCount++;
6533 }
6534 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006535
6536 // If the crashing process is what we consider to be the "home process" and it has been
6537 // replaced by a third-party app, clear the package preferred activities from packages
6538 // with a home activity running in the process to prevent a repeatedly crashing app
6539 // from blocking the user to manually clear the list.
6540 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6541 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6542 Iterator it = mHomeProcess.activities.iterator();
6543 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006544 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006545 if (r.isHomeActivity) {
6546 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6547 try {
6548 ActivityThread.getPackageManager()
6549 .clearPackagePreferredActivities(r.packageName);
6550 } catch (RemoteException c) {
6551 // pm is in same process, this will never happen.
6552 }
6553 }
6554 }
6555 }
6556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6558 return true;
6559 }
6560
6561 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006562 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6563 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 skipCurrentReceiverLocked(app);
6565 }
6566
6567 void skipCurrentReceiverLocked(ProcessRecord app) {
6568 boolean reschedule = false;
6569 BroadcastRecord r = app.curReceiver;
6570 if (r != null) {
6571 // The current broadcast is waiting for this app's receiver
6572 // to be finished. Looks like that's not going to happen, so
6573 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006574 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006575 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6576 r.resultExtras, r.resultAbort, true);
6577 reschedule = true;
6578 }
6579 r = mPendingBroadcast;
6580 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006581 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006583 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6585 r.resultExtras, r.resultAbort, true);
6586 reschedule = true;
6587 }
6588 if (reschedule) {
6589 scheduleBroadcastsLocked();
6590 }
6591 }
6592
Dan Egnor60d87622009-12-16 16:32:58 -08006593 /**
6594 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6595 * The application process will exit immediately after this call returns.
6596 * @param app object of the crashing app, null for the system server
6597 * @param crashInfo describing the exception
6598 */
6599 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6600 ProcessRecord r = findAppProcess(app);
6601
6602 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6603 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006604 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006605 crashInfo.exceptionClassName,
6606 crashInfo.exceptionMessage,
6607 crashInfo.throwFileName,
6608 crashInfo.throwLineNumber);
6609
Dan Egnor42471dd2010-01-07 17:25:22 -08006610 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006611
6612 crashApplication(r, crashInfo);
6613 }
6614
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006615 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006616 IBinder app,
6617 int violationMask,
6618 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006619 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006620
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006621 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006622 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006623 boolean logIt = true;
6624 synchronized (mAlreadyLoggedViolatedStacks) {
6625 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6626 logIt = false;
6627 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006628 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006629 // the relative pain numbers, without logging all
6630 // the stack traces repeatedly. We'd want to do
6631 // likewise in the client code, which also does
6632 // dup suppression, before the Binder call.
6633 } else {
6634 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6635 mAlreadyLoggedViolatedStacks.clear();
6636 }
6637 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6638 }
6639 }
6640 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006641 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006642 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006643 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006644
6645 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6646 AppErrorResult result = new AppErrorResult();
6647 synchronized (this) {
6648 final long origId = Binder.clearCallingIdentity();
6649
6650 Message msg = Message.obtain();
6651 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6652 HashMap<String, Object> data = new HashMap<String, Object>();
6653 data.put("result", result);
6654 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006655 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006656 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006657 msg.obj = data;
6658 mHandler.sendMessage(msg);
6659
6660 Binder.restoreCallingIdentity(origId);
6661 }
6662 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006663 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006664 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006665 }
6666
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006667 // Depending on the policy in effect, there could be a bunch of
6668 // these in quick succession so we try to batch these together to
6669 // minimize disk writes, number of dropbox entries, and maximize
6670 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006671 private void logStrictModeViolationToDropBox(
6672 ProcessRecord process,
6673 StrictMode.ViolationInfo info) {
6674 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006675 return;
6676 }
6677 final boolean isSystemApp = process == null ||
6678 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6679 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6680 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6681 final DropBoxManager dbox = (DropBoxManager)
6682 mContext.getSystemService(Context.DROPBOX_SERVICE);
6683
6684 // Exit early if the dropbox isn't configured to accept this report type.
6685 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6686
6687 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006688 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006689 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6690 synchronized (sb) {
6691 bufferWasEmpty = sb.length() == 0;
6692 appendDropBoxProcessHeaders(process, sb);
6693 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6694 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006695 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6696 if (info.violationNumThisLoop != 0) {
6697 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6698 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006699 if (info.numAnimationsRunning != 0) {
6700 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6701 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006702 if (info.broadcastIntentAction != null) {
6703 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6704 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006705 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006706 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006707 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006708 if (info.tags != null) {
6709 for (String tag : info.tags) {
6710 sb.append("Span-Tag: ").append(tag).append("\n");
6711 }
6712 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006713 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006714 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6715 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006716 }
6717 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006718
6719 // Only buffer up to ~64k. Various logging bits truncate
6720 // things at 128k.
6721 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006722 }
6723
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006724 // Flush immediately if the buffer's grown too large, or this
6725 // is a non-system app. Non-system apps are isolated with a
6726 // different tag & policy and not batched.
6727 //
6728 // Batching is useful during internal testing with
6729 // StrictMode settings turned up high. Without batching,
6730 // thousands of separate files could be created on boot.
6731 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006732 new Thread("Error dump: " + dropboxTag) {
6733 @Override
6734 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006735 String report;
6736 synchronized (sb) {
6737 report = sb.toString();
6738 sb.delete(0, sb.length());
6739 sb.trimToSize();
6740 }
6741 if (report.length() != 0) {
6742 dbox.addText(dropboxTag, report);
6743 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006744 }
6745 }.start();
6746 return;
6747 }
6748
6749 // System app batching:
6750 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006751 // An existing dropbox-writing thread is outstanding, so
6752 // we don't need to start it up. The existing thread will
6753 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006754 return;
6755 }
6756
6757 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6758 // (After this point, we shouldn't access AMS internal data structures.)
6759 new Thread("Error dump: " + dropboxTag) {
6760 @Override
6761 public void run() {
6762 // 5 second sleep to let stacks arrive and be batched together
6763 try {
6764 Thread.sleep(5000); // 5 seconds
6765 } catch (InterruptedException e) {}
6766
6767 String errorReport;
6768 synchronized (mStrictModeBuffer) {
6769 errorReport = mStrictModeBuffer.toString();
6770 if (errorReport.length() == 0) {
6771 return;
6772 }
6773 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6774 mStrictModeBuffer.trimToSize();
6775 }
6776 dbox.addText(dropboxTag, errorReport);
6777 }
6778 }.start();
6779 }
6780
Dan Egnor60d87622009-12-16 16:32:58 -08006781 /**
6782 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6783 * @param app object of the crashing app, null for the system server
6784 * @param tag reported by the caller
6785 * @param crashInfo describing the context of the error
6786 * @return true if the process should exit immediately (WTF is fatal)
6787 */
6788 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006789 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006790 ProcessRecord r = findAppProcess(app);
6791
6792 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6793 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006794 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006795 tag, crashInfo.exceptionMessage);
6796
Dan Egnor42471dd2010-01-07 17:25:22 -08006797 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006798
Doug Zongker43866e02010-01-07 12:09:54 -08006799 if (Settings.Secure.getInt(mContext.getContentResolver(),
6800 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006801 crashApplication(r, crashInfo);
6802 return true;
6803 } else {
6804 return false;
6805 }
6806 }
6807
6808 /**
6809 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6810 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6811 */
6812 private ProcessRecord findAppProcess(IBinder app) {
6813 if (app == null) {
6814 return null;
6815 }
6816
6817 synchronized (this) {
6818 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6819 final int NA = apps.size();
6820 for (int ia=0; ia<NA; ia++) {
6821 ProcessRecord p = apps.valueAt(ia);
6822 if (p.thread != null && p.thread.asBinder() == app) {
6823 return p;
6824 }
6825 }
6826 }
6827
Joe Onorato8a9b2202010-02-26 18:56:32 -08006828 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006829 return null;
6830 }
6831 }
6832
6833 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006834 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6835 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006836 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006837 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6838 // Note: ProcessRecord 'process' is guarded by the service
6839 // instance. (notably process.pkgList, which could otherwise change
6840 // concurrently during execution of this method)
6841 synchronized (this) {
6842 if (process == null || process.pid == MY_PID) {
6843 sb.append("Process: system_server\n");
6844 } else {
6845 sb.append("Process: ").append(process.processName).append("\n");
6846 }
6847 if (process == null) {
6848 return;
6849 }
Dan Egnora455d192010-03-12 08:52:28 -08006850 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006851 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006852 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6853 for (String pkg : process.pkgList) {
6854 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006855 try {
Dan Egnora455d192010-03-12 08:52:28 -08006856 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6857 if (pi != null) {
6858 sb.append(" v").append(pi.versionCode);
6859 if (pi.versionName != null) {
6860 sb.append(" (").append(pi.versionName).append(")");
6861 }
6862 }
6863 } catch (RemoteException e) {
6864 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006865 }
Dan Egnora455d192010-03-12 08:52:28 -08006866 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006867 }
Dan Egnora455d192010-03-12 08:52:28 -08006868 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006869 }
6870
6871 private static String processClass(ProcessRecord process) {
6872 if (process == null || process.pid == MY_PID) {
6873 return "system_server";
6874 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6875 return "system_app";
6876 } else {
6877 return "data_app";
6878 }
6879 }
6880
6881 /**
6882 * Write a description of an error (crash, WTF, ANR) to the drop box.
6883 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6884 * @param process which caused the error, null means the system server
6885 * @param activity which triggered the error, null if unknown
6886 * @param parent activity related to the error, null if unknown
6887 * @param subject line related to the error, null if absent
6888 * @param report in long form describing the error, null if absent
6889 * @param logFile to include in the report, null if none
6890 * @param crashInfo giving an application stack trace, null if absent
6891 */
6892 public void addErrorToDropBox(String eventType,
6893 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6894 final String report, final File logFile,
6895 final ApplicationErrorReport.CrashInfo crashInfo) {
6896 // NOTE -- this must never acquire the ActivityManagerService lock,
6897 // otherwise the watchdog may be prevented from resetting the system.
6898
6899 final String dropboxTag = processClass(process) + "_" + eventType;
6900 final DropBoxManager dbox = (DropBoxManager)
6901 mContext.getSystemService(Context.DROPBOX_SERVICE);
6902
6903 // Exit early if the dropbox isn't configured to accept this report type.
6904 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6905
6906 final StringBuilder sb = new StringBuilder(1024);
6907 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006908 if (activity != null) {
6909 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6910 }
6911 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6912 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6913 }
6914 if (parent != null && parent != activity) {
6915 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6916 }
6917 if (subject != null) {
6918 sb.append("Subject: ").append(subject).append("\n");
6919 }
6920 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006921 if (Debug.isDebuggerConnected()) {
6922 sb.append("Debugger: Connected\n");
6923 }
Dan Egnora455d192010-03-12 08:52:28 -08006924 sb.append("\n");
6925
6926 // Do the rest in a worker thread to avoid blocking the caller on I/O
6927 // (After this point, we shouldn't access AMS internal data structures.)
6928 Thread worker = new Thread("Error dump: " + dropboxTag) {
6929 @Override
6930 public void run() {
6931 if (report != null) {
6932 sb.append(report);
6933 }
6934 if (logFile != null) {
6935 try {
6936 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6937 } catch (IOException e) {
6938 Slog.e(TAG, "Error reading " + logFile, e);
6939 }
6940 }
6941 if (crashInfo != null && crashInfo.stackTrace != null) {
6942 sb.append(crashInfo.stackTrace);
6943 }
6944
6945 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6946 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6947 if (lines > 0) {
6948 sb.append("\n");
6949
6950 // Merge several logcat streams, and take the last N lines
6951 InputStreamReader input = null;
6952 try {
6953 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6954 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6955 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6956
6957 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6958 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6959 input = new InputStreamReader(logcat.getInputStream());
6960
6961 int num;
6962 char[] buf = new char[8192];
6963 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6964 } catch (IOException e) {
6965 Slog.e(TAG, "Error running logcat", e);
6966 } finally {
6967 if (input != null) try { input.close(); } catch (IOException e) {}
6968 }
6969 }
6970
6971 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006972 }
Dan Egnora455d192010-03-12 08:52:28 -08006973 };
6974
6975 if (process == null || process.pid == MY_PID) {
6976 worker.run(); // We may be about to die -- need to run this synchronously
6977 } else {
6978 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006979 }
6980 }
6981
6982 /**
6983 * Bring up the "unexpected error" dialog box for a crashing app.
6984 * Deal with edge cases (intercepts from instrumented applications,
6985 * ActivityController, error intent receivers, that sort of thing).
6986 * @param r the application crashing
6987 * @param crashInfo describing the failure
6988 */
6989 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006990 long timeMillis = System.currentTimeMillis();
6991 String shortMsg = crashInfo.exceptionClassName;
6992 String longMsg = crashInfo.exceptionMessage;
6993 String stackTrace = crashInfo.stackTrace;
6994 if (shortMsg != null && longMsg != null) {
6995 longMsg = shortMsg + ": " + longMsg;
6996 } else if (shortMsg != null) {
6997 longMsg = shortMsg;
6998 }
6999
Dan Egnor60d87622009-12-16 16:32:58 -08007000 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007001 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007002 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007003 try {
7004 String name = r != null ? r.processName : null;
7005 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007006 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007007 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007008 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007009 + " at watcher's request");
7010 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007011 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 }
7013 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007014 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007015 }
7016 }
7017
7018 final long origId = Binder.clearCallingIdentity();
7019
7020 // If this process is running instrumentation, finish it.
7021 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007022 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007023 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007024 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7025 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 Bundle info = new Bundle();
7027 info.putString("shortMsg", shortMsg);
7028 info.putString("longMsg", longMsg);
7029 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7030 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007031 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007032 }
7033
Dan Egnor60d87622009-12-16 16:32:58 -08007034 // If we can't identify the process or it's already exceeded its crash quota,
7035 // quit right away without showing a crash dialog.
7036 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007038 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039 }
7040
7041 Message msg = Message.obtain();
7042 msg.what = SHOW_ERROR_MSG;
7043 HashMap data = new HashMap();
7044 data.put("result", result);
7045 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 msg.obj = data;
7047 mHandler.sendMessage(msg);
7048
7049 Binder.restoreCallingIdentity(origId);
7050 }
7051
7052 int res = result.get();
7053
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007054 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007055 synchronized (this) {
7056 if (r != null) {
7057 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7058 SystemClock.uptimeMillis());
7059 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007060 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007061 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007062 }
7063 }
7064
7065 if (appErrorIntent != null) {
7066 try {
7067 mContext.startActivity(appErrorIntent);
7068 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007069 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007073
7074 Intent createAppErrorIntentLocked(ProcessRecord r,
7075 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7076 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007077 if (report == null) {
7078 return null;
7079 }
7080 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7081 result.setComponent(r.errorReportReceiver);
7082 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7083 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7084 return result;
7085 }
7086
Dan Egnorb7f03672009-12-09 16:22:32 -08007087 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7088 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007089 if (r.errorReportReceiver == null) {
7090 return null;
7091 }
7092
7093 if (!r.crashing && !r.notResponding) {
7094 return null;
7095 }
7096
Dan Egnorb7f03672009-12-09 16:22:32 -08007097 ApplicationErrorReport report = new ApplicationErrorReport();
7098 report.packageName = r.info.packageName;
7099 report.installerPackageName = r.errorReportReceiver.getPackageName();
7100 report.processName = r.processName;
7101 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007102 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007103
Dan Egnorb7f03672009-12-09 16:22:32 -08007104 if (r.crashing) {
7105 report.type = ApplicationErrorReport.TYPE_CRASH;
7106 report.crashInfo = crashInfo;
7107 } else if (r.notResponding) {
7108 report.type = ApplicationErrorReport.TYPE_ANR;
7109 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007110
Dan Egnorb7f03672009-12-09 16:22:32 -08007111 report.anrInfo.activity = r.notRespondingReport.tag;
7112 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7113 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007114 }
7115
Dan Egnorb7f03672009-12-09 16:22:32 -08007116 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007117 }
7118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7120 // assume our apps are happy - lazy create the list
7121 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7122
7123 synchronized (this) {
7124
7125 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007126 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7127 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7129 // This one's in trouble, so we'll generate a report for it
7130 // crashes are higher priority (in case there's a crash *and* an anr)
7131 ActivityManager.ProcessErrorStateInfo report = null;
7132 if (app.crashing) {
7133 report = app.crashingReport;
7134 } else if (app.notResponding) {
7135 report = app.notRespondingReport;
7136 }
7137
7138 if (report != null) {
7139 if (errList == null) {
7140 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7141 }
7142 errList.add(report);
7143 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007144 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 " crashing = " + app.crashing +
7146 " notResponding = " + app.notResponding);
7147 }
7148 }
7149 }
7150 }
7151
7152 return errList;
7153 }
7154
7155 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7156 // Lazy instantiation of list
7157 List<ActivityManager.RunningAppProcessInfo> runList = null;
7158 synchronized (this) {
7159 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007160 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7161 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7163 // Generate process state info for running application
7164 ActivityManager.RunningAppProcessInfo currApp =
7165 new ActivityManager.RunningAppProcessInfo(app.processName,
7166 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007167 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007168 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007169 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007170 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007171 if (app.persistent) {
7172 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007175 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7177 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7178 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007179 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7180 } else if (adj >= HOME_APP_ADJ) {
7181 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7182 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007183 } else if (adj >= SECONDARY_SERVER_ADJ) {
7184 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007185 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007186 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007187 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7188 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007189 } else if (adj >= VISIBLE_APP_ADJ) {
7190 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7191 } else {
7192 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7193 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007194 currApp.importanceReasonCode = app.adjTypeCode;
7195 if (app.adjSource instanceof ProcessRecord) {
7196 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007197 } else if (app.adjSource instanceof ActivityRecord) {
7198 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007199 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7200 }
7201 if (app.adjTarget instanceof ComponentName) {
7202 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7203 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007204 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 // + " lru=" + currApp.lru);
7206 if (runList == null) {
7207 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7208 }
7209 runList.add(currApp);
7210 }
7211 }
7212 }
7213 return runList;
7214 }
7215
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007216 public List<ApplicationInfo> getRunningExternalApplications() {
7217 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7218 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7219 if (runningApps != null && runningApps.size() > 0) {
7220 Set<String> extList = new HashSet<String>();
7221 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7222 if (app.pkgList != null) {
7223 for (String pkg : app.pkgList) {
7224 extList.add(pkg);
7225 }
7226 }
7227 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007228 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007229 for (String pkg : extList) {
7230 try {
7231 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7232 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7233 retList.add(info);
7234 }
7235 } catch (RemoteException e) {
7236 }
7237 }
7238 }
7239 return retList;
7240 }
7241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 @Override
7243 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007244 if (checkCallingPermission(android.Manifest.permission.DUMP)
7245 != PackageManager.PERMISSION_GRANTED) {
7246 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7247 + Binder.getCallingPid()
7248 + ", uid=" + Binder.getCallingUid()
7249 + " without permission "
7250 + android.Manifest.permission.DUMP);
7251 return;
7252 }
7253
7254 boolean dumpAll = false;
7255
7256 int opti = 0;
7257 while (opti < args.length) {
7258 String opt = args[opti];
7259 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7260 break;
7261 }
7262 opti++;
7263 if ("-a".equals(opt)) {
7264 dumpAll = true;
7265 } else if ("-h".equals(opt)) {
7266 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007267 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007268 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007269 pw.println(" a[ctivities]: activity stack state");
7270 pw.println(" b[roadcasts]: broadcast state");
7271 pw.println(" i[ntents]: pending intent state");
7272 pw.println(" p[rocesses]: process state");
7273 pw.println(" o[om]: out of memory management");
7274 pw.println(" prov[iders]: content provider state");
7275 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007276 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007277 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007278 } else {
7279 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007281 }
7282
7283 // Is the caller requesting to dump a particular piece of data?
7284 if (opti < args.length) {
7285 String cmd = args[opti];
7286 opti++;
7287 if ("activities".equals(cmd) || "a".equals(cmd)) {
7288 synchronized (this) {
7289 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007291 return;
7292 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7293 synchronized (this) {
7294 dumpBroadcastsLocked(fd, pw, args, opti, true);
7295 }
7296 return;
7297 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7298 synchronized (this) {
7299 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7300 }
7301 return;
7302 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7303 synchronized (this) {
7304 dumpProcessesLocked(fd, pw, args, opti, true);
7305 }
7306 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007307 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7308 synchronized (this) {
7309 dumpOomLocked(fd, pw, args, opti, true);
7310 }
7311 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007312 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7313 synchronized (this) {
7314 dumpProvidersLocked(fd, pw, args, opti, true);
7315 }
7316 return;
7317 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007318 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007319 return;
7320 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7321 synchronized (this) {
7322 dumpServicesLocked(fd, pw, args, opti, true);
7323 }
7324 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007325 } else {
7326 // Dumping a single activity?
7327 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7328 return;
7329 }
7330 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007332 }
7333
7334 // No piece of data specified, dump everything.
7335 synchronized (this) {
7336 boolean needSep;
7337 if (dumpAll) {
7338 pw.println("Providers in Current Activity Manager State:");
7339 }
7340 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7341 if (needSep) {
7342 pw.println(" ");
7343 }
7344 if (dumpAll) {
7345 pw.println("-------------------------------------------------------------------------------");
7346 pw.println("Broadcasts in Current Activity Manager State:");
7347 }
7348 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7349 if (needSep) {
7350 pw.println(" ");
7351 }
7352 if (dumpAll) {
7353 pw.println("-------------------------------------------------------------------------------");
7354 pw.println("Services in Current Activity Manager State:");
7355 }
7356 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7357 if (needSep) {
7358 pw.println(" ");
7359 }
7360 if (dumpAll) {
7361 pw.println("-------------------------------------------------------------------------------");
7362 pw.println("PendingIntents in Current Activity Manager State:");
7363 }
7364 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7365 if (needSep) {
7366 pw.println(" ");
7367 }
7368 if (dumpAll) {
7369 pw.println("-------------------------------------------------------------------------------");
7370 pw.println("Activities in Current Activity Manager State:");
7371 }
7372 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7373 if (needSep) {
7374 pw.println(" ");
7375 }
7376 if (dumpAll) {
7377 pw.println("-------------------------------------------------------------------------------");
7378 pw.println("Processes in Current Activity Manager State:");
7379 }
7380 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7381 }
7382 }
7383
7384 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7385 int opti, boolean dumpAll, boolean needHeader) {
7386 if (needHeader) {
7387 pw.println(" Activity stack:");
7388 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007389 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390 pw.println(" ");
7391 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007392 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7393 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007395 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007396 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007397 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007398 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007400 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007401 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007403 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 pw.println(" ");
7405 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007406 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007409 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007410 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7411 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007412 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007413 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007415 if (dumpAll && mRecentTasks.size() > 0) {
7416 pw.println(" ");
7417 pw.println("Recent tasks in Current Activity Manager State:");
7418
7419 final int N = mRecentTasks.size();
7420 for (int i=0; i<N; i++) {
7421 TaskRecord tr = mRecentTasks.get(i);
7422 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7423 pw.println(tr);
7424 mRecentTasks.get(i).dump(pw, " ");
7425 }
7426 }
7427
7428 pw.println(" ");
7429 pw.println(" mCurTask: " + mCurTask);
7430
7431 return true;
7432 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007433
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007434 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7435 int opti, boolean dumpAll) {
7436 boolean needSep = false;
7437 int numPers = 0;
7438
7439 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7441 final int NA = procs.size();
7442 for (int ia=0; ia<NA; ia++) {
7443 if (!needSep) {
7444 pw.println(" All known processes:");
7445 needSep = true;
7446 }
7447 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007448 pw.print(r.persistent ? " *PERS*" : " *APP*");
7449 pw.print(" UID "); pw.print(procs.keyAt(ia));
7450 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451 r.dump(pw, " ");
7452 if (r.persistent) {
7453 numPers++;
7454 }
7455 }
7456 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007457 }
7458
7459 if (mLruProcesses.size() > 0) {
7460 if (needSep) pw.println(" ");
7461 needSep = true;
7462 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007463 dumpProcessOomList(pw, this, mLruProcesses, " ",
7464 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007465 needSep = true;
7466 }
7467
7468 synchronized (mPidsSelfLocked) {
7469 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 if (needSep) pw.println(" ");
7471 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007472 pw.println(" PID mappings:");
7473 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7474 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7475 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 }
7477 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007478 }
7479
7480 if (mForegroundProcesses.size() > 0) {
7481 if (needSep) pw.println(" ");
7482 needSep = true;
7483 pw.println(" Foreground Processes:");
7484 for (int i=0; i<mForegroundProcesses.size(); i++) {
7485 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7486 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007488 }
7489
7490 if (mPersistentStartingProcesses.size() > 0) {
7491 if (needSep) pw.println(" ");
7492 needSep = true;
7493 pw.println(" Persisent processes that are starting:");
7494 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007495 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007497
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 if (mStartingProcesses.size() > 0) {
7499 if (needSep) pw.println(" ");
7500 needSep = true;
7501 pw.println(" Processes that are starting:");
7502 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007503 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007506 if (mRemovedProcesses.size() > 0) {
7507 if (needSep) pw.println(" ");
7508 needSep = true;
7509 pw.println(" Processes that are being removed:");
7510 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007511 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007512 }
7513
7514 if (mProcessesOnHold.size() > 0) {
7515 if (needSep) pw.println(" ");
7516 needSep = true;
7517 pw.println(" Processes that are on old until the system is ready:");
7518 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007519 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007521
Dianne Hackborn287952c2010-09-22 22:34:31 -07007522 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007523
7524 if (mProcessCrashTimes.getMap().size() > 0) {
7525 if (needSep) pw.println(" ");
7526 needSep = true;
7527 pw.println(" Time since processes crashed:");
7528 long now = SystemClock.uptimeMillis();
7529 for (Map.Entry<String, SparseArray<Long>> procs
7530 : mProcessCrashTimes.getMap().entrySet()) {
7531 SparseArray<Long> uids = procs.getValue();
7532 final int N = uids.size();
7533 for (int i=0; i<N; i++) {
7534 pw.print(" Process "); pw.print(procs.getKey());
7535 pw.print(" uid "); pw.print(uids.keyAt(i));
7536 pw.print(": last crashed ");
7537 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007538 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007539 }
7540 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007543 if (mBadProcesses.getMap().size() > 0) {
7544 if (needSep) pw.println(" ");
7545 needSep = true;
7546 pw.println(" Bad processes:");
7547 for (Map.Entry<String, SparseArray<Long>> procs
7548 : mBadProcesses.getMap().entrySet()) {
7549 SparseArray<Long> uids = procs.getValue();
7550 final int N = uids.size();
7551 for (int i=0; i<N; i++) {
7552 pw.print(" Bad process "); pw.print(procs.getKey());
7553 pw.print(" uid "); pw.print(uids.keyAt(i));
7554 pw.print(": crashed at time ");
7555 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 }
7557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007560 pw.println(" ");
7561 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007562 if (mHeavyWeightProcess != null) {
7563 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7564 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007565 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007566 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007567 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7568 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7569 || mOrigWaitForDebugger) {
7570 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7571 + " mDebugTransient=" + mDebugTransient
7572 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7573 }
7574 if (mAlwaysFinishActivities || mController != null) {
7575 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7576 + " mController=" + mController);
7577 }
7578 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007581 + " mProcessesReady=" + mProcessesReady
7582 + " mSystemReady=" + mSystemReady);
7583 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 + " mBooted=" + mBooted
7585 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007586 pw.print(" mLastPowerCheckRealtime=");
7587 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7588 pw.println("");
7589 pw.print(" mLastPowerCheckUptime=");
7590 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7591 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007592 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7593 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007594 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007596
7597 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 }
7599
Dianne Hackborn287952c2010-09-22 22:34:31 -07007600 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7601 int opti, boolean needSep, boolean dumpAll) {
7602 if (mProcessesToGc.size() > 0) {
7603 if (needSep) pw.println(" ");
7604 needSep = true;
7605 pw.println(" Processes that are waiting to GC:");
7606 long now = SystemClock.uptimeMillis();
7607 for (int i=0; i<mProcessesToGc.size(); i++) {
7608 ProcessRecord proc = mProcessesToGc.get(i);
7609 pw.print(" Process "); pw.println(proc);
7610 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7611 pw.print(", last gced=");
7612 pw.print(now-proc.lastRequestedGc);
7613 pw.print(" ms ago, last lowMem=");
7614 pw.print(now-proc.lastLowMemory);
7615 pw.println(" ms ago");
7616
7617 }
7618 }
7619 return needSep;
7620 }
7621
7622 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7623 int opti, boolean dumpAll) {
7624 boolean needSep = false;
7625
7626 if (mLruProcesses.size() > 0) {
7627 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7628
7629 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7630 @Override
7631 public int compare(ProcessRecord object1, ProcessRecord object2) {
7632 if (object1.setAdj != object2.setAdj) {
7633 return object1.setAdj > object2.setAdj ? -1 : 1;
7634 }
7635 if (object1.setSchedGroup != object2.setSchedGroup) {
7636 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7637 }
7638 if (object1.keeping != object2.keeping) {
7639 return object1.keeping ? -1 : 1;
7640 }
7641 if (object1.pid != object2.pid) {
7642 return object1.pid > object2.pid ? -1 : 1;
7643 }
7644 return 0;
7645 }
7646 };
7647
7648 Collections.sort(procs, comparator);
7649
7650 if (needSep) pw.println(" ");
7651 needSep = true;
7652 pw.println(" Process OOM control:");
7653 dumpProcessOomList(pw, this, procs, " ",
7654 "Proc", "PERS", true);
7655 needSep = true;
7656 }
7657
7658 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7659
7660 pw.println(" ");
7661 pw.println(" mHomeProcess: " + mHomeProcess);
7662 if (mHeavyWeightProcess != null) {
7663 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7664 }
7665
7666 return true;
7667 }
7668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 /**
7670 * There are three ways to call this:
7671 * - no service specified: dump all the services
7672 * - a flattened component name that matched an existing service was specified as the
7673 * first arg: dump that one service
7674 * - the first arg isn't the flattened component name of an existing service:
7675 * dump all services whose component contains the first arg as a substring
7676 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007677 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 String[] newArgs;
7679 String componentNameString;
7680 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007681 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 componentNameString = null;
7683 newArgs = EMPTY_STRING_ARRAY;
7684 r = null;
7685 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007686 componentNameString = args[opti];
7687 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007689 synchronized (this) {
7690 r = componentName != null ? mServices.get(componentName) : null;
7691 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007692 newArgs = new String[args.length - opti];
7693 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 }
7695
7696 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007697 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007699 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7700 synchronized (this) {
7701 for (ServiceRecord r1 : mServices.values()) {
7702 if (componentNameString == null
7703 || r1.name.flattenToString().contains(componentNameString)) {
7704 services.add(r1);
7705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 }
7707 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007708 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007709 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 }
7712 }
7713
7714 /**
7715 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7716 * there is a thread associated with the service.
7717 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007718 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7719 pw.println("------------------------------------------------------------"
7720 + "-------------------");
7721 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 if (r.app != null && r.app.thread != null) {
7723 try {
7724 // flush anything that is already in the PrintWriter since the thread is going
7725 // to write to the file descriptor directly
7726 pw.flush();
7727 r.app.thread.dumpService(fd, r, args);
7728 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007729 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 } catch (RemoteException e) {
7731 pw.println("got a RemoteException while dumping the service");
7732 }
7733 }
7734 }
7735
Dianne Hackborn625ac272010-09-17 18:29:22 -07007736 /**
7737 * There are three things that cmd can be:
7738 * - a flattened component name that matched an existing activity
7739 * - the cmd arg isn't the flattened component name of an existing activity:
7740 * dump all activity whose component contains the cmd as a substring
7741 * - A hex number of the ActivityRecord object instance.
7742 */
7743 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7744 int opti, boolean dumpAll) {
7745 String[] newArgs;
7746 ComponentName componentName = ComponentName.unflattenFromString(name);
7747 int objectId = 0;
7748 try {
7749 objectId = Integer.parseInt(name, 16);
7750 name = null;
7751 componentName = null;
7752 } catch (RuntimeException e) {
7753 }
7754 newArgs = new String[args.length - opti];
7755 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7756
7757 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7758 synchronized (this) {
7759 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7760 if (componentName != null) {
7761 if (r1.intent.getComponent().equals(componentName)) {
7762 activities.add(r1);
7763 }
7764 } else if (name != null) {
7765 if (r1.intent.getComponent().flattenToString().contains(name)) {
7766 activities.add(r1);
7767 }
7768 } else if (System.identityHashCode(this) == objectId) {
7769 activities.add(r1);
7770 }
7771 }
7772 }
7773
7774 if (activities.size() <= 0) {
7775 return false;
7776 }
7777
7778 for (int i=0; i<activities.size(); i++) {
7779 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7780 }
7781 return true;
7782 }
7783
7784 /**
7785 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7786 * there is a thread associated with the activity.
7787 */
7788 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7789 boolean dumpAll) {
7790 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7791 if (dumpAll) {
7792 synchronized (this) {
7793 pw.print(" * "); pw.println(r);
7794 r.dump(pw, " ");
7795 }
7796 pw.println("");
7797 }
7798 if (r.app != null && r.app.thread != null) {
7799 try {
7800 // flush anything that is already in the PrintWriter since the thread is going
7801 // to write to the file descriptor directly
7802 pw.flush();
7803 r.app.thread.dumpActivity(fd, r, args);
7804 pw.print("\n");
7805 pw.flush();
7806 } catch (RemoteException e) {
7807 pw.println("got a RemoteException while dumping the activity");
7808 }
7809 }
7810 }
7811
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007812 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7813 int opti, boolean dumpAll) {
7814 boolean needSep = false;
7815
7816 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 if (mRegisteredReceivers.size() > 0) {
7818 pw.println(" ");
7819 pw.println(" Registered Receivers:");
7820 Iterator it = mRegisteredReceivers.values().iterator();
7821 while (it.hasNext()) {
7822 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007823 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824 r.dump(pw, " ");
7825 }
7826 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828 pw.println(" ");
7829 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007830 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007831 needSep = true;
7832 }
7833
7834 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7835 || mPendingBroadcast != null) {
7836 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007838 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007840 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7841 pw.println(" Broadcast #" + i + ":");
7842 mParallelBroadcasts.get(i).dump(pw, " ");
7843 }
7844 if (mOrderedBroadcasts.size() > 0) {
7845 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007846 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007847 }
7848 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7849 pw.println(" Serialized Broadcast #" + i + ":");
7850 mOrderedBroadcasts.get(i).dump(pw, " ");
7851 }
7852 pw.println(" ");
7853 pw.println(" Pending broadcast:");
7854 if (mPendingBroadcast != null) {
7855 mPendingBroadcast.dump(pw, " ");
7856 } else {
7857 pw.println(" (null)");
7858 }
7859 needSep = true;
7860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007862 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007864 pw.println(" Historical broadcasts:");
7865 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7866 BroadcastRecord r = mBroadcastHistory[i];
7867 if (r == null) {
7868 break;
7869 }
7870 pw.println(" Historical Broadcast #" + i + ":");
7871 r.dump(pw, " ");
7872 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007873 needSep = true;
7874 }
7875
7876 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007877 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007878 pw.println(" Sticky broadcasts:");
7879 StringBuilder sb = new StringBuilder(128);
7880 for (Map.Entry<String, ArrayList<Intent>> ent
7881 : mStickyBroadcasts.entrySet()) {
7882 pw.print(" * Sticky action "); pw.print(ent.getKey());
7883 pw.println(":");
7884 ArrayList<Intent> intents = ent.getValue();
7885 final int N = intents.size();
7886 for (int i=0; i<N; i++) {
7887 sb.setLength(0);
7888 sb.append(" Intent: ");
7889 intents.get(i).toShortString(sb, true, false);
7890 pw.println(sb.toString());
7891 Bundle bundle = intents.get(i).getExtras();
7892 if (bundle != null) {
7893 pw.print(" ");
7894 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 }
7896 }
7897 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007898 needSep = true;
7899 }
7900
7901 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007903 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 pw.println(" mHandler:");
7905 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007906 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007908
7909 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 }
7911
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7913 int opti, boolean dumpAll) {
7914 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007916 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 if (mServices.size() > 0) {
7918 pw.println(" Active services:");
7919 Iterator<ServiceRecord> it = mServices.values().iterator();
7920 while (it.hasNext()) {
7921 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007922 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 r.dump(pw, " ");
7924 }
7925 needSep = true;
7926 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007929 if (mPendingServices.size() > 0) {
7930 if (needSep) pw.println(" ");
7931 pw.println(" Pending services:");
7932 for (int i=0; i<mPendingServices.size(); i++) {
7933 ServiceRecord r = mPendingServices.get(i);
7934 pw.print(" * Pending "); pw.println(r);
7935 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007937 needSep = true;
7938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007940 if (mRestartingServices.size() > 0) {
7941 if (needSep) pw.println(" ");
7942 pw.println(" Restarting services:");
7943 for (int i=0; i<mRestartingServices.size(); i++) {
7944 ServiceRecord r = mRestartingServices.get(i);
7945 pw.print(" * Restarting "); pw.println(r);
7946 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007948 needSep = true;
7949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007951 if (mStoppingServices.size() > 0) {
7952 if (needSep) pw.println(" ");
7953 pw.println(" Stopping services:");
7954 for (int i=0; i<mStoppingServices.size(); i++) {
7955 ServiceRecord r = mStoppingServices.get(i);
7956 pw.print(" * Stopping "); pw.println(r);
7957 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007959 needSep = true;
7960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007961
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007962 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007963 if (mServiceConnections.size() > 0) {
7964 if (needSep) pw.println(" ");
7965 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007966 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 = mServiceConnections.values().iterator();
7968 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007969 ArrayList<ConnectionRecord> r = it.next();
7970 for (int i=0; i<r.size(); i++) {
7971 pw.print(" * "); pw.println(r.get(i));
7972 r.get(i).dump(pw, " ");
7973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007974 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007975 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 }
7977 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007978
7979 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 }
7981
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007982 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7983 int opti, boolean dumpAll) {
7984 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007985
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007986 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 if (mProvidersByClass.size() > 0) {
7988 if (needSep) pw.println(" ");
7989 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007990 Iterator<Map.Entry<String, ContentProviderRecord>> it
7991 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007992 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007993 Map.Entry<String, ContentProviderRecord> e = it.next();
7994 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007995 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 r.dump(pw, " ");
7997 }
7998 needSep = true;
7999 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008000
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008001 if (mProvidersByName.size() > 0) {
8002 pw.println(" ");
8003 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008004 Iterator<Map.Entry<String, ContentProviderRecord>> it
8005 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008006 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008007 Map.Entry<String, ContentProviderRecord> e = it.next();
8008 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008009 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8010 pw.println(r);
8011 }
8012 needSep = true;
8013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008015
8016 if (mLaunchingProviders.size() > 0) {
8017 if (needSep) pw.println(" ");
8018 pw.println(" Launching content providers:");
8019 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8020 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8021 pw.println(mLaunchingProviders.get(i));
8022 }
8023 needSep = true;
8024 }
8025
8026 if (mGrantedUriPermissions.size() > 0) {
8027 pw.println();
8028 pw.println("Granted Uri Permissions:");
8029 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8030 int uid = mGrantedUriPermissions.keyAt(i);
8031 HashMap<Uri, UriPermission> perms
8032 = mGrantedUriPermissions.valueAt(i);
8033 pw.print(" * UID "); pw.print(uid);
8034 pw.println(" holds:");
8035 for (UriPermission perm : perms.values()) {
8036 pw.print(" "); pw.println(perm);
8037 perm.dump(pw, " ");
8038 }
8039 }
8040 needSep = true;
8041 }
8042
8043 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 }
8045
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008046 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8047 int opti, boolean dumpAll) {
8048 boolean needSep = false;
8049
8050 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008051 if (this.mIntentSenderRecords.size() > 0) {
8052 Iterator<WeakReference<PendingIntentRecord>> it
8053 = mIntentSenderRecords.values().iterator();
8054 while (it.hasNext()) {
8055 WeakReference<PendingIntentRecord> ref = it.next();
8056 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008057 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008059 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008060 rec.dump(pw, " ");
8061 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008062 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 }
8064 }
8065 }
8066 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008067
8068 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 }
8070
8071 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008072 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 TaskRecord lastTask = null;
8074 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008075 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008076 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 if (lastTask != r.task) {
8078 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008079 pw.print(prefix);
8080 pw.print(full ? "* " : " ");
8081 pw.println(lastTask);
8082 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008083 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008086 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8087 pw.print(" #"); pw.print(i); pw.print(": ");
8088 pw.println(r);
8089 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008090 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 }
8093 }
8094
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008095 private static String buildOomTag(String prefix, String space, int val, int base) {
8096 if (val == base) {
8097 if (space == null) return prefix;
8098 return prefix + " ";
8099 }
8100 return prefix + "+" + Integer.toString(val-base);
8101 }
8102
8103 private static final int dumpProcessList(PrintWriter pw,
8104 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008105 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008107 final int N = list.size()-1;
8108 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008110 pw.println(String.format("%s%s #%2d: %s",
8111 prefix, (r.persistent ? persistentLabel : normalLabel),
8112 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 if (r.persistent) {
8114 numPers++;
8115 }
8116 }
8117 return numPers;
8118 }
8119
Dianne Hackborn287952c2010-09-22 22:34:31 -07008120 private static final void dumpProcessOomList(PrintWriter pw,
8121 ActivityManagerService service, List<ProcessRecord> list,
8122 String prefix, String normalLabel, String persistentLabel,
8123 boolean inclDetails) {
8124
8125 final long curRealtime = SystemClock.elapsedRealtime();
8126 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8127 final long curUptime = SystemClock.uptimeMillis();
8128 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8129
8130 final int N = list.size()-1;
8131 for (int i=N; i>=0; i--) {
8132 ProcessRecord r = list.get(i);
8133 String oomAdj;
8134 if (r.setAdj >= EMPTY_APP_ADJ) {
8135 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8136 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8137 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8138 } else if (r.setAdj >= HOME_APP_ADJ) {
8139 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8140 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8141 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8142 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8143 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8144 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8145 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8146 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8147 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8148 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8149 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8150 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8151 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8152 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8153 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8154 } else if (r.setAdj >= SYSTEM_ADJ) {
8155 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8156 } else {
8157 oomAdj = Integer.toString(r.setAdj);
8158 }
8159 String schedGroup;
8160 switch (r.setSchedGroup) {
8161 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8162 schedGroup = "B";
8163 break;
8164 case Process.THREAD_GROUP_DEFAULT:
8165 schedGroup = "F";
8166 break;
8167 default:
8168 schedGroup = Integer.toString(r.setSchedGroup);
8169 break;
8170 }
8171 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8172 prefix, (r.persistent ? persistentLabel : normalLabel),
8173 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8174 if (r.adjSource != null || r.adjTarget != null) {
8175 pw.print(prefix);
8176 pw.print(" ");
8177 if (r.adjTarget instanceof ComponentName) {
8178 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8179 } else if (r.adjTarget != null) {
8180 pw.print(r.adjTarget.toString());
8181 } else {
8182 pw.print("{null}");
8183 }
8184 pw.print("<=");
8185 if (r.adjSource instanceof ProcessRecord) {
8186 pw.print("Proc{");
8187 pw.print(((ProcessRecord)r.adjSource).toShortString());
8188 pw.println("}");
8189 } else if (r.adjSource != null) {
8190 pw.println(r.adjSource.toString());
8191 } else {
8192 pw.println("{null}");
8193 }
8194 }
8195 if (inclDetails) {
8196 pw.print(prefix);
8197 pw.print(" ");
8198 pw.print("oom: max="); pw.print(r.maxAdj);
8199 pw.print(" hidden="); pw.print(r.hiddenAdj);
8200 pw.print(" curRaw="); pw.print(r.curRawAdj);
8201 pw.print(" setRaw="); pw.print(r.setRawAdj);
8202 pw.print(" cur="); pw.print(r.curAdj);
8203 pw.print(" set="); pw.println(r.setAdj);
8204 pw.print(prefix);
8205 pw.print(" ");
8206 pw.print("keeping="); pw.print(r.keeping);
8207 pw.print(" hidden="); pw.print(r.hidden);
8208 pw.print(" empty="); pw.println(r.empty);
8209
8210 if (!r.keeping) {
8211 if (r.lastWakeTime != 0) {
8212 long wtime;
8213 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8214 synchronized (stats) {
8215 wtime = stats.getProcessWakeTime(r.info.uid,
8216 r.pid, curRealtime);
8217 }
8218 long timeUsed = wtime - r.lastWakeTime;
8219 pw.print(prefix);
8220 pw.print(" ");
8221 pw.print("keep awake over ");
8222 TimeUtils.formatDuration(realtimeSince, pw);
8223 pw.print(" used ");
8224 TimeUtils.formatDuration(timeUsed, pw);
8225 pw.print(" (");
8226 pw.print((timeUsed*100)/realtimeSince);
8227 pw.println("%)");
8228 }
8229 if (r.lastCpuTime != 0) {
8230 long timeUsed = r.curCpuTime - r.lastCpuTime;
8231 pw.print(prefix);
8232 pw.print(" ");
8233 pw.print("run cpu over ");
8234 TimeUtils.formatDuration(uptimeSince, pw);
8235 pw.print(" used ");
8236 TimeUtils.formatDuration(timeUsed, pw);
8237 pw.print(" (");
8238 pw.print((timeUsed*100)/uptimeSince);
8239 pw.println("%)");
8240 }
8241 }
8242 }
8243 }
8244 }
8245
Dianne Hackborn472ad872010-04-07 17:31:48 -07008246 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008248 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 long uptime = SystemClock.uptimeMillis();
8250 long realtime = SystemClock.elapsedRealtime();
8251
8252 if (isCheckinRequest) {
8253 // short checkin version
8254 pw.println(uptime + "," + realtime);
8255 pw.flush();
8256 } else {
8257 pw.println("Applications Memory Usage (kB):");
8258 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8259 }
8260 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8261 ProcessRecord r = (ProcessRecord)list.get(i);
8262 if (r.thread != null) {
8263 if (!isCheckinRequest) {
8264 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8265 pw.flush();
8266 }
8267 try {
8268 r.thread.asBinder().dump(fd, args);
8269 } catch (RemoteException e) {
8270 if (!isCheckinRequest) {
8271 pw.println("Got RemoteException!");
8272 pw.flush();
8273 }
8274 }
8275 }
8276 }
8277 }
8278
8279 /**
8280 * Searches array of arguments for the specified string
8281 * @param args array of argument strings
8282 * @param value value to search for
8283 * @return true if the value is contained in the array
8284 */
8285 private static boolean scanArgs(String[] args, String value) {
8286 if (args != null) {
8287 for (String arg : args) {
8288 if (value.equals(arg)) {
8289 return true;
8290 }
8291 }
8292 }
8293 return false;
8294 }
8295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008296 private final void killServicesLocked(ProcessRecord app,
8297 boolean allowRestart) {
8298 // Report disconnected services.
8299 if (false) {
8300 // XXX we are letting the client link to the service for
8301 // death notifications.
8302 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008303 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008305 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008306 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008307 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 = r.connections.values().iterator();
8309 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008310 ArrayList<ConnectionRecord> cl = jt.next();
8311 for (int i=0; i<cl.size(); i++) {
8312 ConnectionRecord c = cl.get(i);
8313 if (c.binding.client != app) {
8314 try {
8315 //c.conn.connected(r.className, null);
8316 } catch (Exception e) {
8317 // todo: this should be asynchronous!
8318 Slog.w(TAG, "Exception thrown disconnected servce "
8319 + r.shortName
8320 + " from app " + app.processName, e);
8321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 }
8323 }
8324 }
8325 }
8326 }
8327 }
8328 }
8329
8330 // Clean up any connections this application has to other services.
8331 if (app.connections.size() > 0) {
8332 Iterator<ConnectionRecord> it = app.connections.iterator();
8333 while (it.hasNext()) {
8334 ConnectionRecord r = it.next();
8335 removeConnectionLocked(r, app, null);
8336 }
8337 }
8338 app.connections.clear();
8339
8340 if (app.services.size() != 0) {
8341 // Any services running in the application need to be placed
8342 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008343 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008344 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008345 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 synchronized (sr.stats.getBatteryStats()) {
8347 sr.stats.stopLaunchedLocked();
8348 }
8349 sr.app = null;
8350 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008351 if (mStoppingServices.remove(sr)) {
8352 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8353 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008354
8355 boolean hasClients = sr.bindings.size() > 0;
8356 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 Iterator<IntentBindRecord> bindings
8358 = sr.bindings.values().iterator();
8359 while (bindings.hasNext()) {
8360 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008361 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 + ": shouldUnbind=" + b.hasBound);
8363 b.binder = null;
8364 b.requested = b.received = b.hasBound = false;
8365 }
8366 }
8367
8368 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008369 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008371 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372 sr.crashCount, sr.shortName, app.pid);
8373 bringDownServiceLocked(sr, true);
8374 } else if (!allowRestart) {
8375 bringDownServiceLocked(sr, true);
8376 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008377 boolean canceled = scheduleServiceRestartLocked(sr, true);
8378
8379 // Should the service remain running? Note that in the
8380 // extreme case of so many attempts to deliver a command
8381 // that it failed, that we also will stop it here.
8382 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8383 if (sr.pendingStarts.size() == 0) {
8384 sr.startRequested = false;
8385 if (!hasClients) {
8386 // Whoops, no reason to restart!
8387 bringDownServiceLocked(sr, true);
8388 }
8389 }
8390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 }
8392 }
8393
8394 if (!allowRestart) {
8395 app.services.clear();
8396 }
8397 }
8398
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008399 // Make sure we have no more records on the stopping list.
8400 int i = mStoppingServices.size();
8401 while (i > 0) {
8402 i--;
8403 ServiceRecord sr = mStoppingServices.get(i);
8404 if (sr.app == app) {
8405 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008406 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008407 }
8408 }
8409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 app.executingServices.clear();
8411 }
8412
8413 private final void removeDyingProviderLocked(ProcessRecord proc,
8414 ContentProviderRecord cpr) {
8415 synchronized (cpr) {
8416 cpr.launchingApp = null;
8417 cpr.notifyAll();
8418 }
8419
8420 mProvidersByClass.remove(cpr.info.name);
8421 String names[] = cpr.info.authority.split(";");
8422 for (int j = 0; j < names.length; j++) {
8423 mProvidersByName.remove(names[j]);
8424 }
8425
8426 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8427 while (cit.hasNext()) {
8428 ProcessRecord capp = cit.next();
8429 if (!capp.persistent && capp.thread != null
8430 && capp.pid != 0
8431 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008432 Slog.i(TAG, "Kill " + capp.processName
8433 + " (pid " + capp.pid + "): provider " + cpr.info.name
8434 + " in dying process " + proc.processName);
8435 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8436 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 Process.killProcess(capp.pid);
8438 }
8439 }
8440
8441 mLaunchingProviders.remove(cpr);
8442 }
8443
8444 /**
8445 * Main code for cleaning up a process when it has gone away. This is
8446 * called both as a result of the process dying, or directly when stopping
8447 * a process when running in single process mode.
8448 */
8449 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8450 boolean restarting, int index) {
8451 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008452 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 }
8454
Dianne Hackborn36124872009-10-08 16:22:03 -07008455 mProcessesToGc.remove(app);
8456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 // Dismiss any open dialogs.
8458 if (app.crashDialog != null) {
8459 app.crashDialog.dismiss();
8460 app.crashDialog = null;
8461 }
8462 if (app.anrDialog != null) {
8463 app.anrDialog.dismiss();
8464 app.anrDialog = null;
8465 }
8466 if (app.waitDialog != null) {
8467 app.waitDialog.dismiss();
8468 app.waitDialog = null;
8469 }
8470
8471 app.crashing = false;
8472 app.notResponding = false;
8473
8474 app.resetPackageList();
8475 app.thread = null;
8476 app.forcingToForeground = null;
8477 app.foregroundServices = false;
8478
8479 killServicesLocked(app, true);
8480
8481 boolean restart = false;
8482
8483 int NL = mLaunchingProviders.size();
8484
8485 // Remove published content providers.
8486 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008487 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008488 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008489 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008490 cpr.provider = null;
8491 cpr.app = null;
8492
8493 // See if someone is waiting for this provider... in which
8494 // case we don't remove it, but just let it restart.
8495 int i = 0;
8496 if (!app.bad) {
8497 for (; i<NL; i++) {
8498 if (mLaunchingProviders.get(i) == cpr) {
8499 restart = true;
8500 break;
8501 }
8502 }
8503 } else {
8504 i = NL;
8505 }
8506
8507 if (i >= NL) {
8508 removeDyingProviderLocked(app, cpr);
8509 NL = mLaunchingProviders.size();
8510 }
8511 }
8512 app.pubProviders.clear();
8513 }
8514
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008515 // Take care of any launching providers waiting for this process.
8516 if (checkAppInLaunchingProvidersLocked(app, false)) {
8517 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 // Unregister from connected content providers.
8521 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008522 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008523 while (it.hasNext()) {
8524 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8525 cpr.clients.remove(app);
8526 }
8527 app.conProviders.clear();
8528 }
8529
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008530 // At this point there may be remaining entries in mLaunchingProviders
8531 // where we were the only one waiting, so they are no longer of use.
8532 // Look for these and clean up if found.
8533 // XXX Commented out for now. Trying to figure out a way to reproduce
8534 // the actual situation to identify what is actually going on.
8535 if (false) {
8536 for (int i=0; i<NL; i++) {
8537 ContentProviderRecord cpr = (ContentProviderRecord)
8538 mLaunchingProviders.get(i);
8539 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8540 synchronized (cpr) {
8541 cpr.launchingApp = null;
8542 cpr.notifyAll();
8543 }
8544 }
8545 }
8546 }
8547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 skipCurrentReceiverLocked(app);
8549
8550 // Unregister any receivers.
8551 if (app.receivers.size() > 0) {
8552 Iterator<ReceiverList> it = app.receivers.iterator();
8553 while (it.hasNext()) {
8554 removeReceiverLocked(it.next());
8555 }
8556 app.receivers.clear();
8557 }
8558
Christopher Tate181fafa2009-05-14 11:12:14 -07008559 // If the app is undergoing backup, tell the backup manager about it
8560 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008561 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008562 try {
8563 IBackupManager bm = IBackupManager.Stub.asInterface(
8564 ServiceManager.getService(Context.BACKUP_SERVICE));
8565 bm.agentDisconnected(app.info.packageName);
8566 } catch (RemoteException e) {
8567 // can't happen; backup manager is local
8568 }
8569 }
8570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 // If the caller is restarting this app, then leave it in its
8572 // current lists and let the caller take care of it.
8573 if (restarting) {
8574 return;
8575 }
8576
8577 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008578 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 "Removing non-persistent process during cleanup: " + app);
8580 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008581 if (mHeavyWeightProcess == app) {
8582 mHeavyWeightProcess = null;
8583 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 } else if (!app.removed) {
8586 // This app is persistent, so we need to keep its record around.
8587 // If it is not already on the pending app list, add it there
8588 // and start a new process for it.
8589 app.thread = null;
8590 app.forcingToForeground = null;
8591 app.foregroundServices = false;
8592 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8593 mPersistentStartingProcesses.add(app);
8594 restart = true;
8595 }
8596 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008597 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8598 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 mProcessesOnHold.remove(app);
8600
The Android Open Source Project4df24232009-03-05 14:34:35 -08008601 if (app == mHomeProcess) {
8602 mHomeProcess = null;
8603 }
8604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 if (restart) {
8606 // We have components that still need to be running in the
8607 // process, so re-launch it.
8608 mProcessNames.put(app.processName, app.info.uid, app);
8609 startProcessLocked(app, "restart", app.processName);
8610 } else if (app.pid > 0 && app.pid != MY_PID) {
8611 // Goodbye!
8612 synchronized (mPidsSelfLocked) {
8613 mPidsSelfLocked.remove(app.pid);
8614 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8615 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008616 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 }
8618 }
8619
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008620 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8621 // Look through the content providers we are waiting to have launched,
8622 // and if any run in this process then either schedule a restart of
8623 // the process or kill the client waiting for it if this process has
8624 // gone bad.
8625 int NL = mLaunchingProviders.size();
8626 boolean restart = false;
8627 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008628 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008629 if (cpr.launchingApp == app) {
8630 if (!alwaysBad && !app.bad) {
8631 restart = true;
8632 } else {
8633 removeDyingProviderLocked(app, cpr);
8634 NL = mLaunchingProviders.size();
8635 }
8636 }
8637 }
8638 return restart;
8639 }
8640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 // =========================================================
8642 // SERVICES
8643 // =========================================================
8644
8645 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8646 ActivityManager.RunningServiceInfo info =
8647 new ActivityManager.RunningServiceInfo();
8648 info.service = r.name;
8649 if (r.app != null) {
8650 info.pid = r.app.pid;
8651 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008652 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 info.process = r.processName;
8654 info.foreground = r.isForeground;
8655 info.activeSince = r.createTime;
8656 info.started = r.startRequested;
8657 info.clientCount = r.connections.size();
8658 info.crashCount = r.crashCount;
8659 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008660 if (r.isForeground) {
8661 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8662 }
8663 if (r.startRequested) {
8664 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8665 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008666 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008667 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8668 }
8669 if (r.app != null && r.app.persistent) {
8670 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8671 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008672
8673 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8674 for (int i=0; i<connl.size(); i++) {
8675 ConnectionRecord conn = connl.get(i);
8676 if (conn.clientLabel != 0) {
8677 info.clientPackage = conn.binding.client.info.packageName;
8678 info.clientLabel = conn.clientLabel;
8679 return info;
8680 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008681 }
8682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 return info;
8684 }
8685
8686 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8687 int flags) {
8688 synchronized (this) {
8689 ArrayList<ActivityManager.RunningServiceInfo> res
8690 = new ArrayList<ActivityManager.RunningServiceInfo>();
8691
8692 if (mServices.size() > 0) {
8693 Iterator<ServiceRecord> it = mServices.values().iterator();
8694 while (it.hasNext() && res.size() < maxNum) {
8695 res.add(makeRunningServiceInfoLocked(it.next()));
8696 }
8697 }
8698
8699 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8700 ServiceRecord r = mRestartingServices.get(i);
8701 ActivityManager.RunningServiceInfo info =
8702 makeRunningServiceInfoLocked(r);
8703 info.restarting = r.nextRestartTime;
8704 res.add(info);
8705 }
8706
8707 return res;
8708 }
8709 }
8710
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008711 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8712 synchronized (this) {
8713 ServiceRecord r = mServices.get(name);
8714 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008715 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8716 for (int i=0; i<conn.size(); i++) {
8717 if (conn.get(i).clientIntent != null) {
8718 return conn.get(i).clientIntent;
8719 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008720 }
8721 }
8722 }
8723 }
8724 return null;
8725 }
8726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 private final ServiceRecord findServiceLocked(ComponentName name,
8728 IBinder token) {
8729 ServiceRecord r = mServices.get(name);
8730 return r == token ? r : null;
8731 }
8732
8733 private final class ServiceLookupResult {
8734 final ServiceRecord record;
8735 final String permission;
8736
8737 ServiceLookupResult(ServiceRecord _record, String _permission) {
8738 record = _record;
8739 permission = _permission;
8740 }
8741 };
8742
8743 private ServiceLookupResult findServiceLocked(Intent service,
8744 String resolvedType) {
8745 ServiceRecord r = null;
8746 if (service.getComponent() != null) {
8747 r = mServices.get(service.getComponent());
8748 }
8749 if (r == null) {
8750 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8751 r = mServicesByIntent.get(filter);
8752 }
8753
8754 if (r == null) {
8755 try {
8756 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008757 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008758 service, resolvedType, 0);
8759 ServiceInfo sInfo =
8760 rInfo != null ? rInfo.serviceInfo : null;
8761 if (sInfo == null) {
8762 return null;
8763 }
8764
8765 ComponentName name = new ComponentName(
8766 sInfo.applicationInfo.packageName, sInfo.name);
8767 r = mServices.get(name);
8768 } catch (RemoteException ex) {
8769 // pm is in same process, this will never happen.
8770 }
8771 }
8772 if (r != null) {
8773 int callingPid = Binder.getCallingPid();
8774 int callingUid = Binder.getCallingUid();
8775 if (checkComponentPermission(r.permission,
8776 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8777 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008778 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 + " from pid=" + callingPid
8780 + ", uid=" + callingUid
8781 + " requires " + r.permission);
8782 return new ServiceLookupResult(null, r.permission);
8783 }
8784 return new ServiceLookupResult(r, null);
8785 }
8786 return null;
8787 }
8788
8789 private class ServiceRestarter implements Runnable {
8790 private ServiceRecord mService;
8791
8792 void setService(ServiceRecord service) {
8793 mService = service;
8794 }
8795
8796 public void run() {
8797 synchronized(ActivityManagerService.this) {
8798 performServiceRestartLocked(mService);
8799 }
8800 }
8801 }
8802
8803 private ServiceLookupResult retrieveServiceLocked(Intent service,
8804 String resolvedType, int callingPid, int callingUid) {
8805 ServiceRecord r = null;
8806 if (service.getComponent() != null) {
8807 r = mServices.get(service.getComponent());
8808 }
8809 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8810 r = mServicesByIntent.get(filter);
8811 if (r == null) {
8812 try {
8813 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008814 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008815 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 ServiceInfo sInfo =
8817 rInfo != null ? rInfo.serviceInfo : null;
8818 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008819 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008820 ": not found");
8821 return null;
8822 }
8823
8824 ComponentName name = new ComponentName(
8825 sInfo.applicationInfo.packageName, sInfo.name);
8826 r = mServices.get(name);
8827 if (r == null) {
8828 filter = new Intent.FilterComparison(service.cloneFilter());
8829 ServiceRestarter res = new ServiceRestarter();
8830 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8831 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8832 synchronized (stats) {
8833 ss = stats.getServiceStatsLocked(
8834 sInfo.applicationInfo.uid, sInfo.packageName,
8835 sInfo.name);
8836 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008837 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 res.setService(r);
8839 mServices.put(name, r);
8840 mServicesByIntent.put(filter, r);
8841
8842 // Make sure this component isn't in the pending list.
8843 int N = mPendingServices.size();
8844 for (int i=0; i<N; i++) {
8845 ServiceRecord pr = mPendingServices.get(i);
8846 if (pr.name.equals(name)) {
8847 mPendingServices.remove(i);
8848 i--;
8849 N--;
8850 }
8851 }
8852 }
8853 } catch (RemoteException ex) {
8854 // pm is in same process, this will never happen.
8855 }
8856 }
8857 if (r != null) {
8858 if (checkComponentPermission(r.permission,
8859 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8860 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008861 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 + " from pid=" + Binder.getCallingPid()
8863 + ", uid=" + Binder.getCallingUid()
8864 + " requires " + r.permission);
8865 return new ServiceLookupResult(null, r.permission);
8866 }
8867 return new ServiceLookupResult(r, null);
8868 }
8869 return null;
8870 }
8871
Dianne Hackborn287952c2010-09-22 22:34:31 -07008872 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8873 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8874 + why + " of " + r + " in app " + r.app);
8875 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8876 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008877 long now = SystemClock.uptimeMillis();
8878 if (r.executeNesting == 0 && r.app != null) {
8879 if (r.app.executingServices.size() == 0) {
8880 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8881 msg.obj = r.app;
8882 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8883 }
8884 r.app.executingServices.add(r);
8885 }
8886 r.executeNesting++;
8887 r.executingStart = now;
8888 }
8889
8890 private final void sendServiceArgsLocked(ServiceRecord r,
8891 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008892 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 if (N == 0) {
8894 return;
8895 }
8896
Dianne Hackborn39792d22010-08-19 18:01:52 -07008897 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008898 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008899 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008900 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8901 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008902 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008903 // If somehow we got a dummy start at the front, then
8904 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008905 continue;
8906 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008907 si.deliveredTime = SystemClock.uptimeMillis();
8908 r.deliveredStarts.add(si);
8909 si.deliveryCount++;
8910 if (si.targetPermissionUid >= 0) {
8911 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008912 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008913 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008914 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008915 if (!oomAdjusted) {
8916 oomAdjusted = true;
8917 updateOomAdjLocked(r.app);
8918 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008919 int flags = 0;
8920 if (si.deliveryCount > 0) {
8921 flags |= Service.START_FLAG_RETRY;
8922 }
8923 if (si.doneExecutingCount > 0) {
8924 flags |= Service.START_FLAG_REDELIVERY;
8925 }
8926 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008927 } catch (RemoteException e) {
8928 // Remote process gone... we'll let the normal cleanup take
8929 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008930 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008931 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008933 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 break;
8935 }
8936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 }
8938
8939 private final boolean requestServiceBindingLocked(ServiceRecord r,
8940 IntentBindRecord i, boolean rebind) {
8941 if (r.app == null || r.app.thread == null) {
8942 // If service is not currently running, can't yet bind.
8943 return false;
8944 }
8945 if ((!i.requested || rebind) && i.apps.size() > 0) {
8946 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008947 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8949 if (!rebind) {
8950 i.requested = true;
8951 }
8952 i.hasBound = true;
8953 i.doRebind = false;
8954 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008955 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008956 return false;
8957 }
8958 }
8959 return true;
8960 }
8961
8962 private final void requestServiceBindingsLocked(ServiceRecord r) {
8963 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8964 while (bindings.hasNext()) {
8965 IntentBindRecord i = bindings.next();
8966 if (!requestServiceBindingLocked(r, i, false)) {
8967 break;
8968 }
8969 }
8970 }
8971
8972 private final void realStartServiceLocked(ServiceRecord r,
8973 ProcessRecord app) throws RemoteException {
8974 if (app.thread == null) {
8975 throw new RemoteException();
8976 }
8977
8978 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008979 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008980
8981 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008982 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008983 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984
8985 boolean created = false;
8986 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008987 mStringBuilder.setLength(0);
8988 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008989 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008990 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008991 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 synchronized (r.stats.getBatteryStats()) {
8993 r.stats.startLaunchedLocked();
8994 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008995 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008997 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 created = true;
8999 } finally {
9000 if (!created) {
9001 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009002 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009003 }
9004 }
9005
9006 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009007
9008 // If the service is in the started state, and there are no
9009 // pending arguments, then fake up one so its onStartCommand() will
9010 // be called.
9011 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9012 r.lastStartId++;
9013 if (r.lastStartId < 1) {
9014 r.lastStartId = 1;
9015 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009016 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009017 }
9018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009019 sendServiceArgsLocked(r, true);
9020 }
9021
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009022 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9023 boolean allowCancel) {
9024 boolean canceled = false;
9025
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009026 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009027 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009028 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009029
9030 // Any delivered but not yet finished starts should be put back
9031 // on the pending list.
9032 final int N = r.deliveredStarts.size();
9033 if (N > 0) {
9034 for (int i=N-1; i>=0; i--) {
9035 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009036 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009037 if (si.intent == null) {
9038 // We'll generate this again if needed.
9039 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9040 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9041 r.pendingStarts.add(0, si);
9042 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9043 dur *= 2;
9044 if (minDuration < dur) minDuration = dur;
9045 if (resetTime < dur) resetTime = dur;
9046 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009047 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009048 + r.name);
9049 canceled = true;
9050 }
9051 }
9052 r.deliveredStarts.clear();
9053 }
9054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 r.totalRestartCount++;
9056 if (r.restartDelay == 0) {
9057 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009058 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 } else {
9060 // If it has been a "reasonably long time" since the service
9061 // was started, then reset our restart duration back to
9062 // the beginning, so we don't infinitely increase the duration
9063 // on a service that just occasionally gets killed (which is
9064 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009065 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009067 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009069 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009070 if (r.restartDelay < minDuration) {
9071 r.restartDelay = minDuration;
9072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 }
9074 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009075
9076 r.nextRestartTime = now + r.restartDelay;
9077
9078 // Make sure that we don't end up restarting a bunch of services
9079 // all at the same time.
9080 boolean repeat;
9081 do {
9082 repeat = false;
9083 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9084 ServiceRecord r2 = mRestartingServices.get(i);
9085 if (r2 != r && r.nextRestartTime
9086 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9087 && r.nextRestartTime
9088 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9089 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9090 r.restartDelay = r.nextRestartTime - now;
9091 repeat = true;
9092 break;
9093 }
9094 }
9095 } while (repeat);
9096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 if (!mRestartingServices.contains(r)) {
9098 mRestartingServices.add(r);
9099 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009100
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009101 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009103 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009104 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009105 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009106 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009108 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 r.shortName, r.restartDelay);
9110
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009111 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 }
9113
9114 final void performServiceRestartLocked(ServiceRecord r) {
9115 if (!mRestartingServices.contains(r)) {
9116 return;
9117 }
9118 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9119 }
9120
9121 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9122 if (r.restartDelay == 0) {
9123 return false;
9124 }
9125 r.resetRestartCounter();
9126 mRestartingServices.remove(r);
9127 mHandler.removeCallbacks(r.restarter);
9128 return true;
9129 }
9130
9131 private final boolean bringUpServiceLocked(ServiceRecord r,
9132 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009133 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 //r.dump(" ");
9135
Dianne Hackborn36124872009-10-08 16:22:03 -07009136 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137 sendServiceArgsLocked(r, false);
9138 return true;
9139 }
9140
9141 if (!whileRestarting && r.restartDelay > 0) {
9142 // If waiting for a restart, then do nothing.
9143 return true;
9144 }
9145
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009146 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009148 // We are now bringing the service up, so no longer in the
9149 // restarting state.
9150 mRestartingServices.remove(r);
9151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009152 final String appName = r.processName;
9153 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9154 if (app != null && app.thread != null) {
9155 try {
9156 realStartServiceLocked(r, app);
9157 return true;
9158 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009159 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 }
9161
9162 // If a dead object exception was thrown -- fall through to
9163 // restart the application.
9164 }
9165
Dianne Hackborn36124872009-10-08 16:22:03 -07009166 // Not running -- get it started, and enqueue this service record
9167 // to be executed when the app comes up.
9168 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9169 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009170 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009171 + r.appInfo.packageName + "/"
9172 + r.appInfo.uid + " for service "
9173 + r.intent.getIntent() + ": process is bad");
9174 bringDownServiceLocked(r, true);
9175 return false;
9176 }
9177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 mPendingServices.add(r);
9180 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 return true;
9183 }
9184
9185 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009186 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 //r.dump(" ");
9188
9189 // Does it still need to run?
9190 if (!force && r.startRequested) {
9191 return;
9192 }
9193 if (r.connections.size() > 0) {
9194 if (!force) {
9195 // XXX should probably keep a count of the number of auto-create
9196 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009197 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009198 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009199 ArrayList<ConnectionRecord> cr = it.next();
9200 for (int i=0; i<cr.size(); i++) {
9201 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9202 return;
9203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 }
9205 }
9206 }
9207
9208 // Report to all of the connections that the service is no longer
9209 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009210 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009212 ArrayList<ConnectionRecord> c = it.next();
9213 for (int i=0; i<c.size(); i++) {
9214 try {
9215 c.get(i).conn.connected(r.name, null);
9216 } catch (Exception e) {
9217 Slog.w(TAG, "Failure disconnecting service " + r.name +
9218 " to connection " + c.get(i).conn.asBinder() +
9219 " (in " + c.get(i).binding.client.processName + ")", e);
9220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 }
9222 }
9223 }
9224
9225 // Tell the service that it has been unbound.
9226 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9227 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9228 while (it.hasNext()) {
9229 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009230 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 + ": hasBound=" + ibr.hasBound);
9232 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9233 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009234 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 updateOomAdjLocked(r.app);
9236 ibr.hasBound = false;
9237 r.app.thread.scheduleUnbindService(r,
9238 ibr.intent.getIntent());
9239 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009240 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 + r.shortName, e);
9242 serviceDoneExecutingLocked(r, true);
9243 }
9244 }
9245 }
9246 }
9247
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009248 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009249 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 System.identityHashCode(r), r.shortName,
9251 (r.app != null) ? r.app.pid : -1);
9252
9253 mServices.remove(r.name);
9254 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009255 r.totalRestartCount = 0;
9256 unscheduleServiceRestartLocked(r);
9257
9258 // Also make sure it is not on the pending list.
9259 int N = mPendingServices.size();
9260 for (int i=0; i<N; i++) {
9261 if (mPendingServices.get(i) == r) {
9262 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009263 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 i--;
9265 N--;
9266 }
9267 }
9268
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009269 r.cancelNotification();
9270 r.isForeground = false;
9271 r.foregroundId = 0;
9272 r.foregroundNoti = null;
9273
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009274 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009275 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009276 r.pendingStarts.clear();
9277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 if (r.app != null) {
9279 synchronized (r.stats.getBatteryStats()) {
9280 r.stats.stopLaunchedLocked();
9281 }
9282 r.app.services.remove(r);
9283 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009284 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009285 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 mStoppingServices.add(r);
9287 updateOomAdjLocked(r.app);
9288 r.app.thread.scheduleStopService(r);
9289 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009290 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 + r.shortName, e);
9292 serviceDoneExecutingLocked(r, true);
9293 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009294 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009296 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009297 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009298 }
9299 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009300 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009301 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 }
9303 }
9304
9305 ComponentName startServiceLocked(IApplicationThread caller,
9306 Intent service, String resolvedType,
9307 int callingPid, int callingUid) {
9308 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009309 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 + " type=" + resolvedType + " args=" + service.getExtras());
9311
9312 if (caller != null) {
9313 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9314 if (callerApp == null) {
9315 throw new SecurityException(
9316 "Unable to find app for caller " + caller
9317 + " (pid=" + Binder.getCallingPid()
9318 + ") when starting service " + service);
9319 }
9320 }
9321
9322 ServiceLookupResult res =
9323 retrieveServiceLocked(service, resolvedType,
9324 callingPid, callingUid);
9325 if (res == null) {
9326 return null;
9327 }
9328 if (res.record == null) {
9329 return new ComponentName("!", res.permission != null
9330 ? res.permission : "private to package");
9331 }
9332 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009333 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9334 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009336 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 }
9338 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009339 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 r.lastStartId++;
9341 if (r.lastStartId < 1) {
9342 r.lastStartId = 1;
9343 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009344 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9345 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 r.lastActivity = SystemClock.uptimeMillis();
9347 synchronized (r.stats.getBatteryStats()) {
9348 r.stats.startRunningLocked();
9349 }
9350 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9351 return new ComponentName("!", "Service process is bad");
9352 }
9353 return r.name;
9354 }
9355 }
9356
9357 public ComponentName startService(IApplicationThread caller, Intent service,
9358 String resolvedType) {
9359 // Refuse possible leaked file descriptors
9360 if (service != null && service.hasFileDescriptors() == true) {
9361 throw new IllegalArgumentException("File descriptors passed in Intent");
9362 }
9363
9364 synchronized(this) {
9365 final int callingPid = Binder.getCallingPid();
9366 final int callingUid = Binder.getCallingUid();
9367 final long origId = Binder.clearCallingIdentity();
9368 ComponentName res = startServiceLocked(caller, service,
9369 resolvedType, callingPid, callingUid);
9370 Binder.restoreCallingIdentity(origId);
9371 return res;
9372 }
9373 }
9374
9375 ComponentName startServiceInPackage(int uid,
9376 Intent service, String resolvedType) {
9377 synchronized(this) {
9378 final long origId = Binder.clearCallingIdentity();
9379 ComponentName res = startServiceLocked(null, service,
9380 resolvedType, -1, uid);
9381 Binder.restoreCallingIdentity(origId);
9382 return res;
9383 }
9384 }
9385
9386 public int stopService(IApplicationThread caller, Intent service,
9387 String resolvedType) {
9388 // Refuse possible leaked file descriptors
9389 if (service != null && service.hasFileDescriptors() == true) {
9390 throw new IllegalArgumentException("File descriptors passed in Intent");
9391 }
9392
9393 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009394 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 + " type=" + resolvedType);
9396
9397 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9398 if (caller != null && callerApp == null) {
9399 throw new SecurityException(
9400 "Unable to find app for caller " + caller
9401 + " (pid=" + Binder.getCallingPid()
9402 + ") when stopping service " + service);
9403 }
9404
9405 // If this service is active, make sure it is stopped.
9406 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9407 if (r != null) {
9408 if (r.record != null) {
9409 synchronized (r.record.stats.getBatteryStats()) {
9410 r.record.stats.stopRunningLocked();
9411 }
9412 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009413 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009414 final long origId = Binder.clearCallingIdentity();
9415 bringDownServiceLocked(r.record, false);
9416 Binder.restoreCallingIdentity(origId);
9417 return 1;
9418 }
9419 return -1;
9420 }
9421 }
9422
9423 return 0;
9424 }
9425
9426 public IBinder peekService(Intent service, String resolvedType) {
9427 // Refuse possible leaked file descriptors
9428 if (service != null && service.hasFileDescriptors() == true) {
9429 throw new IllegalArgumentException("File descriptors passed in Intent");
9430 }
9431
9432 IBinder ret = null;
9433
9434 synchronized(this) {
9435 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9436
9437 if (r != null) {
9438 // r.record is null if findServiceLocked() failed the caller permission check
9439 if (r.record == null) {
9440 throw new SecurityException(
9441 "Permission Denial: Accessing service " + r.record.name
9442 + " from pid=" + Binder.getCallingPid()
9443 + ", uid=" + Binder.getCallingUid()
9444 + " requires " + r.permission);
9445 }
9446 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9447 if (ib != null) {
9448 ret = ib.binder;
9449 }
9450 }
9451 }
9452
9453 return ret;
9454 }
9455
9456 public boolean stopServiceToken(ComponentName className, IBinder token,
9457 int startId) {
9458 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009459 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460 + " " + token + " startId=" + startId);
9461 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009462 if (r != null) {
9463 if (startId >= 0) {
9464 // Asked to only stop if done with all work. Note that
9465 // to avoid leaks, we will take this as dropping all
9466 // start items up to and including this one.
9467 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9468 if (si != null) {
9469 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009470 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9471 cur.removeUriPermissionsLocked();
9472 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009473 break;
9474 }
9475 }
9476 }
9477
9478 if (r.lastStartId != startId) {
9479 return false;
9480 }
9481
9482 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009483 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009484 + " is last, but have " + r.deliveredStarts.size()
9485 + " remaining args");
9486 }
9487 }
9488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 synchronized (r.stats.getBatteryStats()) {
9490 r.stats.stopRunningLocked();
9491 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009492 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 }
9494 final long origId = Binder.clearCallingIdentity();
9495 bringDownServiceLocked(r, false);
9496 Binder.restoreCallingIdentity(origId);
9497 return true;
9498 }
9499 }
9500 return false;
9501 }
9502
9503 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009504 int id, Notification notification, boolean removeNotification) {
9505 final long origId = Binder.clearCallingIdentity();
9506 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 synchronized(this) {
9508 ServiceRecord r = findServiceLocked(className, token);
9509 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009510 if (id != 0) {
9511 if (notification == null) {
9512 throw new IllegalArgumentException("null notification");
9513 }
9514 if (r.foregroundId != id) {
9515 r.cancelNotification();
9516 r.foregroundId = id;
9517 }
9518 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9519 r.foregroundNoti = notification;
9520 r.isForeground = true;
9521 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 if (r.app != null) {
9523 updateServiceForegroundLocked(r.app, true);
9524 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009525 } else {
9526 if (r.isForeground) {
9527 r.isForeground = false;
9528 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009529 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009530 updateServiceForegroundLocked(r.app, true);
9531 }
9532 }
9533 if (removeNotification) {
9534 r.cancelNotification();
9535 r.foregroundId = 0;
9536 r.foregroundNoti = null;
9537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009538 }
9539 }
9540 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009541 } finally {
9542 Binder.restoreCallingIdentity(origId);
9543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 }
9545
9546 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9547 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009548 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009549 if (sr.isForeground) {
9550 anyForeground = true;
9551 break;
9552 }
9553 }
9554 if (anyForeground != proc.foregroundServices) {
9555 proc.foregroundServices = anyForeground;
9556 if (oomAdj) {
9557 updateOomAdjLocked();
9558 }
9559 }
9560 }
9561
9562 public int bindService(IApplicationThread caller, IBinder token,
9563 Intent service, String resolvedType,
9564 IServiceConnection connection, int flags) {
9565 // Refuse possible leaked file descriptors
9566 if (service != null && service.hasFileDescriptors() == true) {
9567 throw new IllegalArgumentException("File descriptors passed in Intent");
9568 }
9569
9570 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009571 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 + " type=" + resolvedType + " conn=" + connection.asBinder()
9573 + " flags=0x" + Integer.toHexString(flags));
9574 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9575 if (callerApp == null) {
9576 throw new SecurityException(
9577 "Unable to find app for caller " + caller
9578 + " (pid=" + Binder.getCallingPid()
9579 + ") when binding service " + service);
9580 }
9581
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009582 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009583 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009584 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009586 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 return 0;
9588 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009589 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 }
9591
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009592 int clientLabel = 0;
9593 PendingIntent clientIntent = null;
9594
9595 if (callerApp.info.uid == Process.SYSTEM_UID) {
9596 // Hacky kind of thing -- allow system stuff to tell us
9597 // what they are, so we can report this elsewhere for
9598 // others to know why certain services are running.
9599 try {
9600 clientIntent = (PendingIntent)service.getParcelableExtra(
9601 Intent.EXTRA_CLIENT_INTENT);
9602 } catch (RuntimeException e) {
9603 }
9604 if (clientIntent != null) {
9605 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9606 if (clientLabel != 0) {
9607 // There are no useful extras in the intent, trash them.
9608 // System code calling with this stuff just needs to know
9609 // this will happen.
9610 service = service.cloneFilter();
9611 }
9612 }
9613 }
9614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 ServiceLookupResult res =
9616 retrieveServiceLocked(service, resolvedType,
9617 Binder.getCallingPid(), Binder.getCallingUid());
9618 if (res == null) {
9619 return 0;
9620 }
9621 if (res.record == null) {
9622 return -1;
9623 }
9624 ServiceRecord s = res.record;
9625
9626 final long origId = Binder.clearCallingIdentity();
9627
9628 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009629 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009630 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009631 }
9632
9633 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9634 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009635 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009636
9637 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009638 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9639 if (clist == null) {
9640 clist = new ArrayList<ConnectionRecord>();
9641 s.connections.put(binder, clist);
9642 }
9643 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 b.connections.add(c);
9645 if (activity != null) {
9646 if (activity.connections == null) {
9647 activity.connections = new HashSet<ConnectionRecord>();
9648 }
9649 activity.connections.add(c);
9650 }
9651 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009652 clist = mServiceConnections.get(binder);
9653 if (clist == null) {
9654 clist = new ArrayList<ConnectionRecord>();
9655 mServiceConnections.put(binder, clist);
9656 }
9657 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658
9659 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9660 s.lastActivity = SystemClock.uptimeMillis();
9661 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9662 return 0;
9663 }
9664 }
9665
9666 if (s.app != null) {
9667 // This could have made the service more important.
9668 updateOomAdjLocked(s.app);
9669 }
9670
Joe Onorato8a9b2202010-02-26 18:56:32 -08009671 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 + ": received=" + b.intent.received
9673 + " apps=" + b.intent.apps.size()
9674 + " doRebind=" + b.intent.doRebind);
9675
9676 if (s.app != null && b.intent.received) {
9677 // Service is already running, so we can immediately
9678 // publish the connection.
9679 try {
9680 c.conn.connected(s.name, b.intent.binder);
9681 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009682 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 + " to connection " + c.conn.asBinder()
9684 + " (in " + c.binding.client.processName + ")", e);
9685 }
9686
9687 // If this is the first app connected back to this binding,
9688 // and the service had previously asked to be told when
9689 // rebound, then do so.
9690 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9691 requestServiceBindingLocked(s, b.intent, true);
9692 }
9693 } else if (!b.intent.requested) {
9694 requestServiceBindingLocked(s, b.intent, false);
9695 }
9696
9697 Binder.restoreCallingIdentity(origId);
9698 }
9699
9700 return 1;
9701 }
9702
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009703 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009704 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 IBinder binder = c.conn.asBinder();
9706 AppBindRecord b = c.binding;
9707 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009708 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9709 if (clist != null) {
9710 clist.remove(c);
9711 if (clist.size() == 0) {
9712 s.connections.remove(binder);
9713 }
9714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 b.connections.remove(c);
9716 if (c.activity != null && c.activity != skipAct) {
9717 if (c.activity.connections != null) {
9718 c.activity.connections.remove(c);
9719 }
9720 }
9721 if (b.client != skipApp) {
9722 b.client.connections.remove(c);
9723 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009724 clist = mServiceConnections.get(binder);
9725 if (clist != null) {
9726 clist.remove(c);
9727 if (clist.size() == 0) {
9728 mServiceConnections.remove(binder);
9729 }
9730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731
9732 if (b.connections.size() == 0) {
9733 b.intent.apps.remove(b.client);
9734 }
9735
Joe Onorato8a9b2202010-02-26 18:56:32 -08009736 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009737 + ": shouldUnbind=" + b.intent.hasBound);
9738 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9739 && b.intent.hasBound) {
9740 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009741 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 updateOomAdjLocked(s.app);
9743 b.intent.hasBound = false;
9744 // Assume the client doesn't want to know about a rebind;
9745 // we will deal with that later if it asks for one.
9746 b.intent.doRebind = false;
9747 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9748 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009749 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 serviceDoneExecutingLocked(s, true);
9751 }
9752 }
9753
9754 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9755 bringDownServiceLocked(s, false);
9756 }
9757 }
9758
9759 public boolean unbindService(IServiceConnection connection) {
9760 synchronized (this) {
9761 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009762 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009763 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9764 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009765 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 + connection.asBinder());
9767 return false;
9768 }
9769
9770 final long origId = Binder.clearCallingIdentity();
9771
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009772 while (clist.size() > 0) {
9773 ConnectionRecord r = clist.get(0);
9774 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009776 if (r.binding.service.app != null) {
9777 // This could have made the service less important.
9778 updateOomAdjLocked(r.binding.service.app);
9779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 }
9781
9782 Binder.restoreCallingIdentity(origId);
9783 }
9784
9785 return true;
9786 }
9787
9788 public void publishService(IBinder token, Intent intent, IBinder service) {
9789 // Refuse possible leaked file descriptors
9790 if (intent != null && intent.hasFileDescriptors() == true) {
9791 throw new IllegalArgumentException("File descriptors passed in Intent");
9792 }
9793
9794 synchronized(this) {
9795 if (!(token instanceof ServiceRecord)) {
9796 throw new IllegalArgumentException("Invalid service token");
9797 }
9798 ServiceRecord r = (ServiceRecord)token;
9799
9800 final long origId = Binder.clearCallingIdentity();
9801
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009802 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009803 + " " + intent + ": " + service);
9804 if (r != null) {
9805 Intent.FilterComparison filter
9806 = new Intent.FilterComparison(intent);
9807 IntentBindRecord b = r.bindings.get(filter);
9808 if (b != null && !b.received) {
9809 b.binder = service;
9810 b.requested = true;
9811 b.received = true;
9812 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009813 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009814 = r.connections.values().iterator();
9815 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009816 ArrayList<ConnectionRecord> clist = it.next();
9817 for (int i=0; i<clist.size(); i++) {
9818 ConnectionRecord c = clist.get(i);
9819 if (!filter.equals(c.binding.intent.intent)) {
9820 if (DEBUG_SERVICE) Slog.v(
9821 TAG, "Not publishing to: " + c);
9822 if (DEBUG_SERVICE) Slog.v(
9823 TAG, "Bound intent: " + c.binding.intent.intent);
9824 if (DEBUG_SERVICE) Slog.v(
9825 TAG, "Published intent: " + intent);
9826 continue;
9827 }
9828 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9829 try {
9830 c.conn.connected(r.name, service);
9831 } catch (Exception e) {
9832 Slog.w(TAG, "Failure sending service " + r.name +
9833 " to connection " + c.conn.asBinder() +
9834 " (in " + c.binding.client.processName + ")", e);
9835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009836 }
9837 }
9838 }
9839 }
9840
9841 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9842
9843 Binder.restoreCallingIdentity(origId);
9844 }
9845 }
9846 }
9847
9848 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9849 // Refuse possible leaked file descriptors
9850 if (intent != null && intent.hasFileDescriptors() == true) {
9851 throw new IllegalArgumentException("File descriptors passed in Intent");
9852 }
9853
9854 synchronized(this) {
9855 if (!(token instanceof ServiceRecord)) {
9856 throw new IllegalArgumentException("Invalid service token");
9857 }
9858 ServiceRecord r = (ServiceRecord)token;
9859
9860 final long origId = Binder.clearCallingIdentity();
9861
9862 if (r != null) {
9863 Intent.FilterComparison filter
9864 = new Intent.FilterComparison(intent);
9865 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009866 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009867 + " at " + b + ": apps="
9868 + (b != null ? b.apps.size() : 0));
9869 if (b != null) {
9870 if (b.apps.size() > 0) {
9871 // Applications have already bound since the last
9872 // unbind, so just rebind right here.
9873 requestServiceBindingLocked(r, b, true);
9874 } else {
9875 // Note to tell the service the next time there is
9876 // a new client.
9877 b.doRebind = true;
9878 }
9879 }
9880
9881 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9882
9883 Binder.restoreCallingIdentity(origId);
9884 }
9885 }
9886 }
9887
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009888 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 synchronized(this) {
9890 if (!(token instanceof ServiceRecord)) {
9891 throw new IllegalArgumentException("Invalid service token");
9892 }
9893 ServiceRecord r = (ServiceRecord)token;
9894 boolean inStopping = mStoppingServices.contains(token);
9895 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009897 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 + " with incorrect token: given " + token
9899 + ", expected " + r);
9900 return;
9901 }
9902
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009903 if (type == 1) {
9904 // This is a call from a service start... take care of
9905 // book-keeping.
9906 r.callStart = true;
9907 switch (res) {
9908 case Service.START_STICKY_COMPATIBILITY:
9909 case Service.START_STICKY: {
9910 // We are done with the associated start arguments.
9911 r.findDeliveredStart(startId, true);
9912 // Don't stop if killed.
9913 r.stopIfKilled = false;
9914 break;
9915 }
9916 case Service.START_NOT_STICKY: {
9917 // We are done with the associated start arguments.
9918 r.findDeliveredStart(startId, true);
9919 if (r.lastStartId == startId) {
9920 // There is no more work, and this service
9921 // doesn't want to hang around if killed.
9922 r.stopIfKilled = true;
9923 }
9924 break;
9925 }
9926 case Service.START_REDELIVER_INTENT: {
9927 // We'll keep this item until they explicitly
9928 // call stop for it, but keep track of the fact
9929 // that it was delivered.
9930 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9931 if (si != null) {
9932 si.deliveryCount = 0;
9933 si.doneExecutingCount++;
9934 // Don't stop if killed.
9935 r.stopIfKilled = true;
9936 }
9937 break;
9938 }
9939 default:
9940 throw new IllegalArgumentException(
9941 "Unknown service start result: " + res);
9942 }
9943 if (res == Service.START_STICKY_COMPATIBILITY) {
9944 r.callStart = false;
9945 }
9946 }
9947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009948 final long origId = Binder.clearCallingIdentity();
9949 serviceDoneExecutingLocked(r, inStopping);
9950 Binder.restoreCallingIdentity(origId);
9951 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009952 Slog.w(TAG, "Done executing unknown service from pid "
9953 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009954 }
9955 }
9956 }
9957
9958 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009959 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9960 + ": nesting=" + r.executeNesting
9961 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009962 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 r.executeNesting--;
9964 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009965 if (DEBUG_SERVICE) Slog.v(TAG,
9966 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 r.app.executingServices.remove(r);
9968 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009969 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9970 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9972 }
9973 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009974 if (DEBUG_SERVICE) Slog.v(TAG,
9975 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 mStoppingServices.remove(r);
9977 }
9978 updateOomAdjLocked(r.app);
9979 }
9980 }
9981
9982 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009983 String anrMessage = null;
9984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 synchronized(this) {
9986 if (proc.executingServices.size() == 0 || proc.thread == null) {
9987 return;
9988 }
9989 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9990 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9991 ServiceRecord timeout = null;
9992 long nextTime = 0;
9993 while (it.hasNext()) {
9994 ServiceRecord sr = it.next();
9995 if (sr.executingStart < maxTime) {
9996 timeout = sr;
9997 break;
9998 }
9999 if (sr.executingStart > nextTime) {
10000 nextTime = sr.executingStart;
10001 }
10002 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010003 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010004 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010005 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 } else {
10007 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10008 msg.obj = proc;
10009 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10010 }
10011 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010012
10013 if (anrMessage != null) {
10014 appNotResponding(proc, null, null, anrMessage);
10015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016 }
10017
10018 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010019 // BACKUP AND RESTORE
10020 // =========================================================
10021
10022 // Cause the target app to be launched if necessary and its backup agent
10023 // instantiated. The backup agent will invoke backupAgentCreated() on the
10024 // activity manager to announce its creation.
10025 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010026 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010027 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10028
10029 synchronized(this) {
10030 // !!! TODO: currently no check here that we're already bound
10031 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10032 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10033 synchronized (stats) {
10034 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10035 }
10036
10037 BackupRecord r = new BackupRecord(ss, app, backupMode);
10038 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10039 // startProcessLocked() returns existing proc's record if it's already running
10040 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010041 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010042 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010043 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010044 return false;
10045 }
10046
10047 r.app = proc;
10048 mBackupTarget = r;
10049 mBackupAppName = app.packageName;
10050
Christopher Tate6fa95972009-06-05 18:43:55 -070010051 // Try not to kill the process during backup
10052 updateOomAdjLocked(proc);
10053
Christopher Tate181fafa2009-05-14 11:12:14 -070010054 // If the process is already attached, schedule the creation of the backup agent now.
10055 // If it is not yet live, this will be done when it attaches to the framework.
10056 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010057 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010058 try {
10059 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10060 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010061 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010062 }
10063 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010064 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010065 }
10066 // Invariants: at this point, the target app process exists and the application
10067 // is either already running or in the process of coming up. mBackupTarget and
10068 // mBackupAppName describe the app, so that when it binds back to the AM we
10069 // know that it's scheduled for a backup-agent operation.
10070 }
10071
10072 return true;
10073 }
10074
10075 // A backup agent has just come up
10076 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010077 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010078 + " = " + agent);
10079
10080 synchronized(this) {
10081 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010082 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010083 return;
10084 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010085 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010086
Dianne Hackborn06740692010-09-22 22:46:21 -070010087 long oldIdent = Binder.clearCallingIdentity();
10088 try {
10089 IBackupManager bm = IBackupManager.Stub.asInterface(
10090 ServiceManager.getService(Context.BACKUP_SERVICE));
10091 bm.agentConnected(agentPackageName, agent);
10092 } catch (RemoteException e) {
10093 // can't happen; the backup manager service is local
10094 } catch (Exception e) {
10095 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10096 e.printStackTrace();
10097 } finally {
10098 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010099 }
10100 }
10101
10102 // done with this agent
10103 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010104 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010105 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010106 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010107 return;
10108 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010109
10110 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010111 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010112 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010113 return;
10114 }
10115
Christopher Tate181fafa2009-05-14 11:12:14 -070010116 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010117 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010118 return;
10119 }
10120
Christopher Tate6fa95972009-06-05 18:43:55 -070010121 ProcessRecord proc = mBackupTarget.app;
10122 mBackupTarget = null;
10123 mBackupAppName = null;
10124
10125 // Not backing this app up any more; reset its OOM adjustment
10126 updateOomAdjLocked(proc);
10127
Christopher Tatec7b31e32009-06-10 15:49:30 -070010128 // If the app crashed during backup, 'thread' will be null here
10129 if (proc.thread != null) {
10130 try {
10131 proc.thread.scheduleDestroyBackupAgent(appInfo);
10132 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010133 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010134 e.printStackTrace();
10135 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010136 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010137 }
10138 }
10139 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 // BROADCASTS
10141 // =========================================================
10142
Josh Bartel7f208742010-02-25 11:01:44 -060010143 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010144 List cur) {
10145 final ContentResolver resolver = mContext.getContentResolver();
10146 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10147 if (list == null) {
10148 return cur;
10149 }
10150 int N = list.size();
10151 for (int i=0; i<N; i++) {
10152 Intent intent = list.get(i);
10153 if (filter.match(resolver, intent, true, TAG) >= 0) {
10154 if (cur == null) {
10155 cur = new ArrayList<Intent>();
10156 }
10157 cur.add(intent);
10158 }
10159 }
10160 return cur;
10161 }
10162
10163 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010164 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 + mBroadcastsScheduled);
10166
10167 if (mBroadcastsScheduled) {
10168 return;
10169 }
10170 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10171 mBroadcastsScheduled = true;
10172 }
10173
10174 public Intent registerReceiver(IApplicationThread caller,
10175 IIntentReceiver receiver, IntentFilter filter, String permission) {
10176 synchronized(this) {
10177 ProcessRecord callerApp = null;
10178 if (caller != null) {
10179 callerApp = getRecordForAppLocked(caller);
10180 if (callerApp == null) {
10181 throw new SecurityException(
10182 "Unable to find app for caller " + caller
10183 + " (pid=" + Binder.getCallingPid()
10184 + ") when registering receiver " + receiver);
10185 }
10186 }
10187
10188 List allSticky = null;
10189
10190 // Look for any matching sticky broadcasts...
10191 Iterator actions = filter.actionsIterator();
10192 if (actions != null) {
10193 while (actions.hasNext()) {
10194 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010195 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 }
10197 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010198 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010199 }
10200
10201 // The first sticky in the list is returned directly back to
10202 // the client.
10203 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10204
Joe Onorato8a9b2202010-02-26 18:56:32 -080010205 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 + ": " + sticky);
10207
10208 if (receiver == null) {
10209 return sticky;
10210 }
10211
10212 ReceiverList rl
10213 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10214 if (rl == null) {
10215 rl = new ReceiverList(this, callerApp,
10216 Binder.getCallingPid(),
10217 Binder.getCallingUid(), receiver);
10218 if (rl.app != null) {
10219 rl.app.receivers.add(rl);
10220 } else {
10221 try {
10222 receiver.asBinder().linkToDeath(rl, 0);
10223 } catch (RemoteException e) {
10224 return sticky;
10225 }
10226 rl.linkedToDeath = true;
10227 }
10228 mRegisteredReceivers.put(receiver.asBinder(), rl);
10229 }
10230 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10231 rl.add(bf);
10232 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010233 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 }
10235 mReceiverResolver.addFilter(bf);
10236
10237 // Enqueue broadcasts for all existing stickies that match
10238 // this filter.
10239 if (allSticky != null) {
10240 ArrayList receivers = new ArrayList();
10241 receivers.add(bf);
10242
10243 int N = allSticky.size();
10244 for (int i=0; i<N; i++) {
10245 Intent intent = (Intent)allSticky.get(i);
10246 BroadcastRecord r = new BroadcastRecord(intent, null,
10247 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010248 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 if (mParallelBroadcasts.size() == 0) {
10250 scheduleBroadcastsLocked();
10251 }
10252 mParallelBroadcasts.add(r);
10253 }
10254 }
10255
10256 return sticky;
10257 }
10258 }
10259
10260 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010261 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262
10263 boolean doNext = false;
10264
10265 synchronized(this) {
10266 ReceiverList rl
10267 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10268 if (rl != null) {
10269 if (rl.curBroadcast != null) {
10270 BroadcastRecord r = rl.curBroadcast;
10271 doNext = finishReceiverLocked(
10272 receiver.asBinder(), r.resultCode, r.resultData,
10273 r.resultExtras, r.resultAbort, true);
10274 }
10275
10276 if (rl.app != null) {
10277 rl.app.receivers.remove(rl);
10278 }
10279 removeReceiverLocked(rl);
10280 if (rl.linkedToDeath) {
10281 rl.linkedToDeath = false;
10282 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10283 }
10284 }
10285 }
10286
10287 if (!doNext) {
10288 return;
10289 }
10290
10291 final long origId = Binder.clearCallingIdentity();
10292 processNextBroadcast(false);
10293 trimApplications();
10294 Binder.restoreCallingIdentity(origId);
10295 }
10296
10297 void removeReceiverLocked(ReceiverList rl) {
10298 mRegisteredReceivers.remove(rl.receiver.asBinder());
10299 int N = rl.size();
10300 for (int i=0; i<N; i++) {
10301 mReceiverResolver.removeFilter(rl.get(i));
10302 }
10303 }
10304
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010305 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10306 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10307 ProcessRecord r = mLruProcesses.get(i);
10308 if (r.thread != null) {
10309 try {
10310 r.thread.dispatchPackageBroadcast(cmd, packages);
10311 } catch (RemoteException ex) {
10312 }
10313 }
10314 }
10315 }
10316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 private final int broadcastIntentLocked(ProcessRecord callerApp,
10318 String callerPackage, Intent intent, String resolvedType,
10319 IIntentReceiver resultTo, int resultCode, String resultData,
10320 Bundle map, String requiredPermission,
10321 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10322 intent = new Intent(intent);
10323
Joe Onorato8a9b2202010-02-26 18:56:32 -080010324 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010325 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10326 + " ordered=" + ordered);
10327 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010328 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 }
10330
10331 // Handle special intents: if this broadcast is from the package
10332 // manager about a package being removed, we need to remove all of
10333 // its activities from the history stack.
10334 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10335 intent.getAction());
10336 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10337 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010338 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 || uidRemoved) {
10340 if (checkComponentPermission(
10341 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10342 callingPid, callingUid, -1)
10343 == PackageManager.PERMISSION_GRANTED) {
10344 if (uidRemoved) {
10345 final Bundle intentExtras = intent.getExtras();
10346 final int uid = intentExtras != null
10347 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10348 if (uid >= 0) {
10349 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10350 synchronized (bs) {
10351 bs.removeUidStatsLocked(uid);
10352 }
10353 }
10354 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010355 // If resources are unvailble just force stop all
10356 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010357 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010358 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10359 if (list != null && (list.length > 0)) {
10360 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010361 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010362 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010363 sendPackageBroadcastLocked(
10364 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010365 }
10366 } else {
10367 Uri data = intent.getData();
10368 String ssp;
10369 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10370 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10371 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010372 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010373 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010374 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10375 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10376 new String[] {ssp});
10377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 }
10379 }
10380 }
10381 } else {
10382 String msg = "Permission Denial: " + intent.getAction()
10383 + " broadcast from " + callerPackage + " (pid=" + callingPid
10384 + ", uid=" + callingUid + ")"
10385 + " requires "
10386 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010387 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 throw new SecurityException(msg);
10389 }
10390 }
10391
10392 /*
10393 * If this is the time zone changed action, queue up a message that will reset the timezone
10394 * of all currently running processes. This message will get queued up before the broadcast
10395 * happens.
10396 */
10397 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10398 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10399 }
10400
Robert Greenwalt03595d02010-11-02 14:08:23 -070010401 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10402 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10403 }
10404
Dianne Hackborn854060af2009-07-09 18:14:31 -070010405 /*
10406 * Prevent non-system code (defined here to be non-persistent
10407 * processes) from sending protected broadcasts.
10408 */
10409 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10410 || callingUid == Process.SHELL_UID || callingUid == 0) {
10411 // Always okay.
10412 } else if (callerApp == null || !callerApp.persistent) {
10413 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010414 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010415 intent.getAction())) {
10416 String msg = "Permission Denial: not allowed to send broadcast "
10417 + intent.getAction() + " from pid="
10418 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010419 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010420 throw new SecurityException(msg);
10421 }
10422 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010423 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010424 return BROADCAST_SUCCESS;
10425 }
10426 }
10427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 // Add to the sticky list if requested.
10429 if (sticky) {
10430 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10431 callingPid, callingUid)
10432 != PackageManager.PERMISSION_GRANTED) {
10433 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10434 + callingPid + ", uid=" + callingUid
10435 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010436 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 throw new SecurityException(msg);
10438 }
10439 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010440 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010441 + " and enforce permission " + requiredPermission);
10442 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10443 }
10444 if (intent.getComponent() != null) {
10445 throw new SecurityException(
10446 "Sticky broadcasts can't target a specific component");
10447 }
10448 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10449 if (list == null) {
10450 list = new ArrayList<Intent>();
10451 mStickyBroadcasts.put(intent.getAction(), list);
10452 }
10453 int N = list.size();
10454 int i;
10455 for (i=0; i<N; i++) {
10456 if (intent.filterEquals(list.get(i))) {
10457 // This sticky already exists, replace it.
10458 list.set(i, new Intent(intent));
10459 break;
10460 }
10461 }
10462 if (i >= N) {
10463 list.add(new Intent(intent));
10464 }
10465 }
10466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 // Figure out who all will receive this broadcast.
10468 List receivers = null;
10469 List<BroadcastFilter> registeredReceivers = null;
10470 try {
10471 if (intent.getComponent() != null) {
10472 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010473 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010474 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 if (ai != null) {
10476 receivers = new ArrayList();
10477 ResolveInfo ri = new ResolveInfo();
10478 ri.activityInfo = ai;
10479 receivers.add(ri);
10480 }
10481 } else {
10482 // Need to resolve the intent to interested receivers...
10483 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10484 == 0) {
10485 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010486 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010487 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010488 }
Mihai Preda074edef2009-05-18 17:13:31 +020010489 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 }
10491 } catch (RemoteException ex) {
10492 // pm is in same process, this will never happen.
10493 }
10494
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010495 final boolean replacePending =
10496 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10497
Joe Onorato8a9b2202010-02-26 18:56:32 -080010498 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010499 + " replacePending=" + replacePending);
10500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10502 if (!ordered && NR > 0) {
10503 // If we are not serializing this broadcast, then send the
10504 // registered receivers separately so they don't wait for the
10505 // components to be launched.
10506 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10507 callerPackage, callingPid, callingUid, requiredPermission,
10508 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010509 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010510 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010511 TAG, "Enqueueing parallel broadcast " + r
10512 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010513 boolean replaced = false;
10514 if (replacePending) {
10515 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10516 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010517 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010518 "***** DROPPING PARALLEL: " + intent);
10519 mParallelBroadcasts.set(i, r);
10520 replaced = true;
10521 break;
10522 }
10523 }
10524 }
10525 if (!replaced) {
10526 mParallelBroadcasts.add(r);
10527 scheduleBroadcastsLocked();
10528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529 registeredReceivers = null;
10530 NR = 0;
10531 }
10532
10533 // Merge into one list.
10534 int ir = 0;
10535 if (receivers != null) {
10536 // A special case for PACKAGE_ADDED: do not allow the package
10537 // being added to see this broadcast. This prevents them from
10538 // using this as a back door to get run as soon as they are
10539 // installed. Maybe in the future we want to have a special install
10540 // broadcast or such for apps, but we'd like to deliberately make
10541 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010542 String skipPackages[] = null;
10543 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10544 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10545 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10546 Uri data = intent.getData();
10547 if (data != null) {
10548 String pkgName = data.getSchemeSpecificPart();
10549 if (pkgName != null) {
10550 skipPackages = new String[] { pkgName };
10551 }
10552 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010553 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010554 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010555 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010556 if (skipPackages != null && (skipPackages.length > 0)) {
10557 for (String skipPackage : skipPackages) {
10558 if (skipPackage != null) {
10559 int NT = receivers.size();
10560 for (int it=0; it<NT; it++) {
10561 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10562 if (curt.activityInfo.packageName.equals(skipPackage)) {
10563 receivers.remove(it);
10564 it--;
10565 NT--;
10566 }
10567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 }
10569 }
10570 }
10571
10572 int NT = receivers != null ? receivers.size() : 0;
10573 int it = 0;
10574 ResolveInfo curt = null;
10575 BroadcastFilter curr = null;
10576 while (it < NT && ir < NR) {
10577 if (curt == null) {
10578 curt = (ResolveInfo)receivers.get(it);
10579 }
10580 if (curr == null) {
10581 curr = registeredReceivers.get(ir);
10582 }
10583 if (curr.getPriority() >= curt.priority) {
10584 // Insert this broadcast record into the final list.
10585 receivers.add(it, curr);
10586 ir++;
10587 curr = null;
10588 it++;
10589 NT++;
10590 } else {
10591 // Skip to the next ResolveInfo in the final list.
10592 it++;
10593 curt = null;
10594 }
10595 }
10596 }
10597 while (ir < NR) {
10598 if (receivers == null) {
10599 receivers = new ArrayList();
10600 }
10601 receivers.add(registeredReceivers.get(ir));
10602 ir++;
10603 }
10604
10605 if ((receivers != null && receivers.size() > 0)
10606 || resultTo != null) {
10607 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10608 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010609 receivers, resultTo, resultCode, resultData, map, ordered,
10610 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 TAG, "Enqueueing ordered broadcast " + r
10613 + ": prev had " + mOrderedBroadcasts.size());
10614 if (DEBUG_BROADCAST) {
10615 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010616 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010617 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010618 boolean replaced = false;
10619 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010620 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010621 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010622 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010623 "***** DROPPING ORDERED: " + intent);
10624 mOrderedBroadcasts.set(i, r);
10625 replaced = true;
10626 break;
10627 }
10628 }
10629 }
10630 if (!replaced) {
10631 mOrderedBroadcasts.add(r);
10632 scheduleBroadcastsLocked();
10633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010634 }
10635
10636 return BROADCAST_SUCCESS;
10637 }
10638
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010639 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 // Refuse possible leaked file descriptors
10641 if (intent != null && intent.hasFileDescriptors() == true) {
10642 throw new IllegalArgumentException("File descriptors passed in Intent");
10643 }
10644
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010645 int flags = intent.getFlags();
10646
10647 if (!mProcessesReady) {
10648 // if the caller really truly claims to know what they're doing, go
10649 // ahead and allow the broadcast without launching any receivers
10650 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10651 intent = new Intent(intent);
10652 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10653 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10654 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10655 + " before boot completion");
10656 throw new IllegalStateException("Cannot broadcast before boot completed");
10657 }
10658 }
10659
10660 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10661 throw new IllegalArgumentException(
10662 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10663 }
10664
10665 return intent;
10666 }
10667
10668 public final int broadcastIntent(IApplicationThread caller,
10669 Intent intent, String resolvedType, IIntentReceiver resultTo,
10670 int resultCode, String resultData, Bundle map,
10671 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010672 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010673 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010675 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10676 final int callingPid = Binder.getCallingPid();
10677 final int callingUid = Binder.getCallingUid();
10678 final long origId = Binder.clearCallingIdentity();
10679 int res = broadcastIntentLocked(callerApp,
10680 callerApp != null ? callerApp.info.packageName : null,
10681 intent, resolvedType, resultTo,
10682 resultCode, resultData, map, requiredPermission, serialized,
10683 sticky, callingPid, callingUid);
10684 Binder.restoreCallingIdentity(origId);
10685 return res;
10686 }
10687 }
10688
10689 int broadcastIntentInPackage(String packageName, int uid,
10690 Intent intent, String resolvedType, IIntentReceiver resultTo,
10691 int resultCode, String resultData, Bundle map,
10692 String requiredPermission, boolean serialized, boolean sticky) {
10693 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010694 intent = verifyBroadcastLocked(intent);
10695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 final long origId = Binder.clearCallingIdentity();
10697 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10698 resultTo, resultCode, resultData, map, requiredPermission,
10699 serialized, sticky, -1, uid);
10700 Binder.restoreCallingIdentity(origId);
10701 return res;
10702 }
10703 }
10704
10705 public final void unbroadcastIntent(IApplicationThread caller,
10706 Intent intent) {
10707 // Refuse possible leaked file descriptors
10708 if (intent != null && intent.hasFileDescriptors() == true) {
10709 throw new IllegalArgumentException("File descriptors passed in Intent");
10710 }
10711
10712 synchronized(this) {
10713 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10714 != PackageManager.PERMISSION_GRANTED) {
10715 String msg = "Permission Denial: unbroadcastIntent() from pid="
10716 + Binder.getCallingPid()
10717 + ", uid=" + Binder.getCallingUid()
10718 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010719 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 throw new SecurityException(msg);
10721 }
10722 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10723 if (list != null) {
10724 int N = list.size();
10725 int i;
10726 for (i=0; i<N; i++) {
10727 if (intent.filterEquals(list.get(i))) {
10728 list.remove(i);
10729 break;
10730 }
10731 }
10732 }
10733 }
10734 }
10735
10736 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10737 String resultData, Bundle resultExtras, boolean resultAbort,
10738 boolean explicit) {
10739 if (mOrderedBroadcasts.size() == 0) {
10740 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010741 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010742 }
10743 return false;
10744 }
10745 BroadcastRecord r = mOrderedBroadcasts.get(0);
10746 if (r.receiver == null) {
10747 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010748 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010749 }
10750 return false;
10751 }
10752 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010753 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 return false;
10755 }
10756 int state = r.state;
10757 r.state = r.IDLE;
10758 if (state == r.IDLE) {
10759 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010760 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 }
10762 }
10763 r.receiver = null;
10764 r.intent.setComponent(null);
10765 if (r.curApp != null) {
10766 r.curApp.curReceiver = null;
10767 }
10768 if (r.curFilter != null) {
10769 r.curFilter.receiverList.curBroadcast = null;
10770 }
10771 r.curFilter = null;
10772 r.curApp = null;
10773 r.curComponent = null;
10774 r.curReceiver = null;
10775 mPendingBroadcast = null;
10776
10777 r.resultCode = resultCode;
10778 r.resultData = resultData;
10779 r.resultExtras = resultExtras;
10780 r.resultAbort = resultAbort;
10781
10782 // We will process the next receiver right now if this is finishing
10783 // an app receiver (which is always asynchronous) or after we have
10784 // come back from calling a receiver.
10785 return state == BroadcastRecord.APP_RECEIVE
10786 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10787 }
10788
10789 public void finishReceiver(IBinder who, int resultCode, String resultData,
10790 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010791 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792
10793 // Refuse possible leaked file descriptors
10794 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10795 throw new IllegalArgumentException("File descriptors passed in Bundle");
10796 }
10797
10798 boolean doNext;
10799
10800 final long origId = Binder.clearCallingIdentity();
10801
10802 synchronized(this) {
10803 doNext = finishReceiverLocked(
10804 who, resultCode, resultData, resultExtras, resultAbort, true);
10805 }
10806
10807 if (doNext) {
10808 processNextBroadcast(false);
10809 }
10810 trimApplications();
10811
10812 Binder.restoreCallingIdentity(origId);
10813 }
10814
Jeff Brown4d94a762010-09-23 11:33:28 -070010815 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 if (r.nextReceiver > 0) {
10817 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10818 if (curReceiver instanceof BroadcastFilter) {
10819 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010820 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 System.identityHashCode(r),
10822 r.intent.getAction(),
10823 r.nextReceiver - 1,
10824 System.identityHashCode(bf));
10825 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010826 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 System.identityHashCode(r),
10828 r.intent.getAction(),
10829 r.nextReceiver - 1,
10830 ((ResolveInfo)curReceiver).toString());
10831 }
10832 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010833 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010835 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 System.identityHashCode(r),
10837 r.intent.getAction(),
10838 r.nextReceiver,
10839 "NONE");
10840 }
10841 }
10842
Jeff Brown4d94a762010-09-23 11:33:28 -070010843 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10844 if (! mPendingBroadcastTimeoutMessage) {
10845 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10846 mHandler.sendMessageAtTime(msg, timeoutTime);
10847 mPendingBroadcastTimeoutMessage = true;
10848 }
10849 }
10850
10851 private final void cancelBroadcastTimeoutLocked() {
10852 if (mPendingBroadcastTimeoutMessage) {
10853 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10854 mPendingBroadcastTimeoutMessage = false;
10855 }
10856 }
10857
10858 private final void broadcastTimeoutLocked(boolean fromMsg) {
10859 if (fromMsg) {
10860 mPendingBroadcastTimeoutMessage = false;
10861 }
10862
10863 if (mOrderedBroadcasts.size() == 0) {
10864 return;
10865 }
10866
10867 long now = SystemClock.uptimeMillis();
10868 BroadcastRecord r = mOrderedBroadcasts.get(0);
10869 if (fromMsg) {
10870 if (mDidDexOpt) {
10871 // Delay timeouts until dexopt finishes.
10872 mDidDexOpt = false;
10873 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10874 setBroadcastTimeoutLocked(timeoutTime);
10875 return;
10876 }
10877 if (! mProcessesReady) {
10878 // Only process broadcast timeouts if the system is ready. That way
10879 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10880 // to do heavy lifting for system up.
10881 return;
10882 }
10883
10884 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10885 if (timeoutTime > now) {
10886 // We can observe premature timeouts because we do not cancel and reset the
10887 // broadcast timeout message after each receiver finishes. Instead, we set up
10888 // an initial timeout then kick it down the road a little further as needed
10889 // when it expires.
10890 if (DEBUG_BROADCAST) Slog.v(TAG,
10891 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10892 + timeoutTime);
10893 setBroadcastTimeoutLocked(timeoutTime);
10894 return;
10895 }
10896 }
10897
10898 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10899 + ", started " + (now - r.receiverTime) + "ms ago");
10900 r.receiverTime = now;
10901 r.anrCount++;
10902
10903 // Current receiver has passed its expiration date.
10904 if (r.nextReceiver <= 0) {
10905 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10906 return;
10907 }
10908
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010909 ProcessRecord app = null;
10910 String anrMessage = null;
10911
Jeff Brown4d94a762010-09-23 11:33:28 -070010912 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10913 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10914 logBroadcastReceiverDiscardLocked(r);
10915 if (curReceiver instanceof BroadcastFilter) {
10916 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10917 if (bf.receiverList.pid != 0
10918 && bf.receiverList.pid != MY_PID) {
10919 synchronized (this.mPidsSelfLocked) {
10920 app = this.mPidsSelfLocked.get(
10921 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010924 } else {
10925 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010927
Jeff Brown4d94a762010-09-23 11:33:28 -070010928 if (app != null) {
10929 anrMessage = "Broadcast of " + r.intent.toString();
10930 }
10931
10932 if (mPendingBroadcast == r) {
10933 mPendingBroadcast = null;
10934 }
10935
10936 // Move on to the next receiver.
10937 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10938 r.resultExtras, r.resultAbort, true);
10939 scheduleBroadcastsLocked();
10940
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010941 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010942 // Post the ANR to the handler since we do not want to process ANRs while
10943 // potentially holding our lock.
10944 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 }
10947
10948 private final void processCurBroadcastLocked(BroadcastRecord r,
10949 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010950 if (DEBUG_BROADCAST) Slog.v(TAG,
10951 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 if (app.thread == null) {
10953 throw new RemoteException();
10954 }
10955 r.receiver = app.thread.asBinder();
10956 r.curApp = app;
10957 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010958 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959
10960 // Tell the application to launch this receiver.
10961 r.intent.setComponent(r.curComponent);
10962
10963 boolean started = false;
10964 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010965 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 "Delivering to component " + r.curComponent
10967 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010968 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10970 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010971 if (DEBUG_BROADCAST) Slog.v(TAG,
10972 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 started = true;
10974 } finally {
10975 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010976 if (DEBUG_BROADCAST) Slog.v(TAG,
10977 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 r.receiver = null;
10979 r.curApp = null;
10980 app.curReceiver = null;
10981 }
10982 }
10983
10984 }
10985
Jeff Brown4d94a762010-09-23 11:33:28 -070010986 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010987 Intent intent, int resultCode, String data, Bundle extras,
10988 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010989 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 if (app != null && app.thread != null) {
10991 // If we have an app thread, do the call through that so it is
10992 // correctly ordered with other one-way calls.
10993 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010994 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010996 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 }
10998 }
10999
Jeff Brown4d94a762010-09-23 11:33:28 -070011000 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 BroadcastFilter filter, boolean ordered) {
11002 boolean skip = false;
11003 if (filter.requiredPermission != null) {
11004 int perm = checkComponentPermission(filter.requiredPermission,
11005 r.callingPid, r.callingUid, -1);
11006 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 + r.intent.toString()
11009 + " from " + r.callerPackage + " (pid="
11010 + r.callingPid + ", uid=" + r.callingUid + ")"
11011 + " requires " + filter.requiredPermission
11012 + " due to registered receiver " + filter);
11013 skip = true;
11014 }
11015 }
11016 if (r.requiredPermission != null) {
11017 int perm = checkComponentPermission(r.requiredPermission,
11018 filter.receiverList.pid, filter.receiverList.uid, -1);
11019 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011020 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 + r.intent.toString()
11022 + " to " + filter.receiverList.app
11023 + " (pid=" + filter.receiverList.pid
11024 + ", uid=" + filter.receiverList.uid + ")"
11025 + " requires " + r.requiredPermission
11026 + " due to sender " + r.callerPackage
11027 + " (uid " + r.callingUid + ")");
11028 skip = true;
11029 }
11030 }
11031
11032 if (!skip) {
11033 // If this is not being sent as an ordered broadcast, then we
11034 // don't want to touch the fields that keep track of the current
11035 // state of ordered broadcasts.
11036 if (ordered) {
11037 r.receiver = filter.receiverList.receiver.asBinder();
11038 r.curFilter = filter;
11039 filter.receiverList.curBroadcast = r;
11040 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011041 if (filter.receiverList.app != null) {
11042 // Bump hosting application to no longer be in background
11043 // scheduling class. Note that we can't do that if there
11044 // isn't an app... but we can only be in that case for
11045 // things that directly call the IActivityManager API, which
11046 // are already core system stuff so don't matter for this.
11047 r.curApp = filter.receiverList.app;
11048 filter.receiverList.app.curReceiver = r;
11049 updateOomAdjLocked();
11050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 }
11052 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011053 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011055 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011056 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011058 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011060 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 if (ordered) {
11062 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11063 }
11064 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011065 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011066 if (ordered) {
11067 r.receiver = null;
11068 r.curFilter = null;
11069 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011070 if (filter.receiverList.app != null) {
11071 filter.receiverList.app.curReceiver = null;
11072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 }
11074 }
11075 }
11076 }
11077
Dianne Hackborn12527f92009-11-11 17:39:50 -080011078 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11079 if (r.callingUid < 0) {
11080 // This was from a registerReceiver() call; ignore it.
11081 return;
11082 }
11083 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11084 MAX_BROADCAST_HISTORY-1);
11085 r.finishTime = SystemClock.uptimeMillis();
11086 mBroadcastHistory[0] = r;
11087 }
11088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 private final void processNextBroadcast(boolean fromMsg) {
11090 synchronized(this) {
11091 BroadcastRecord r;
11092
Joe Onorato8a9b2202010-02-26 18:56:32 -080011093 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011095 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096
11097 updateCpuStats();
11098
11099 if (fromMsg) {
11100 mBroadcastsScheduled = false;
11101 }
11102
11103 // First, deliver any non-serialized broadcasts right away.
11104 while (mParallelBroadcasts.size() > 0) {
11105 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011106 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011108 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011109 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 for (int i=0; i<N; i++) {
11111 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011112 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011113 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011115 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011117 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011118 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011119 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 }
11121
11122 // Now take care of the next serialized one...
11123
11124 // If we are waiting for a process to come up to handle the next
11125 // broadcast, then do nothing at this point. Just in case, we
11126 // check that the process we're waiting for still exists.
11127 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011128 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011129 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011130 + mPendingBroadcast.curApp);
11131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132
11133 boolean isDead;
11134 synchronized (mPidsSelfLocked) {
11135 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11136 }
11137 if (!isDead) {
11138 // It's still alive, so keep waiting
11139 return;
11140 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011141 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011143 mPendingBroadcast.state = BroadcastRecord.IDLE;
11144 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 mPendingBroadcast = null;
11146 }
11147 }
11148
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011149 boolean looped = false;
11150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 do {
11152 if (mOrderedBroadcasts.size() == 0) {
11153 // No more broadcasts pending, so all done!
11154 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011155 if (looped) {
11156 // If we had finished the last ordered broadcast, then
11157 // make sure all processes have correct oom and sched
11158 // adjustments.
11159 updateOomAdjLocked();
11160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 return;
11162 }
11163 r = mOrderedBroadcasts.get(0);
11164 boolean forceReceive = false;
11165
11166 // Ensure that even if something goes awry with the timeout
11167 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011168 // and continue to make progress.
11169 //
11170 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011171 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011172 // one time heavy lifting after system upgrades and can take
11173 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011174 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011175 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011176 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 if ((numReceivers > 0) &&
11178 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011179 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 + " now=" + now
11181 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011182 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 + " intent=" + r.intent
11184 + " numReceivers=" + numReceivers
11185 + " nextReceiver=" + r.nextReceiver
11186 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011187 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 forceReceive = true;
11189 r.state = BroadcastRecord.IDLE;
11190 }
11191 }
11192
11193 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011194 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011195 "processNextBroadcast() called when not idle (state="
11196 + r.state + ")");
11197 return;
11198 }
11199
11200 if (r.receivers == null || r.nextReceiver >= numReceivers
11201 || r.resultAbort || forceReceive) {
11202 // No more receivers for this broadcast! Send the final
11203 // result if requested...
11204 if (r.resultTo != null) {
11205 try {
11206 if (DEBUG_BROADCAST) {
11207 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011208 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209 + " seq=" + seq + " app=" + r.callerApp);
11210 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011211 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011213 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011215 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216 }
11217 }
11218
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011220 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221
Joe Onorato8a9b2202010-02-26 18:56:32 -080011222 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011223 + r);
11224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011225 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011226 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 mOrderedBroadcasts.remove(0);
11228 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011229 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 continue;
11231 }
11232 } while (r == null);
11233
11234 // Get the next receiver...
11235 int recIdx = r.nextReceiver++;
11236
11237 // Keep track of when this receiver started, and make sure there
11238 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011239 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011241 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242
Joe Onorato8a9b2202010-02-26 18:56:32 -080011243 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011244 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011245 }
11246 if (! mPendingBroadcastTimeoutMessage) {
11247 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011248 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011249 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11250 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 }
11252
11253 Object nextReceiver = r.receivers.get(recIdx);
11254 if (nextReceiver instanceof BroadcastFilter) {
11255 // Simple case: this is a registered receiver who gets
11256 // a direct call.
11257 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011258 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011259 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011261 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 if (r.receiver == null || !r.ordered) {
11263 // The receiver has already finished, so schedule to
11264 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011265 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11266 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 r.state = BroadcastRecord.IDLE;
11268 scheduleBroadcastsLocked();
11269 }
11270 return;
11271 }
11272
11273 // Hard case: need to instantiate the receiver, possibly
11274 // starting its application process to host it.
11275
11276 ResolveInfo info =
11277 (ResolveInfo)nextReceiver;
11278
11279 boolean skip = false;
11280 int perm = checkComponentPermission(info.activityInfo.permission,
11281 r.callingPid, r.callingUid,
11282 info.activityInfo.exported
11283 ? -1 : info.activityInfo.applicationInfo.uid);
11284 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011285 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 + r.intent.toString()
11287 + " from " + r.callerPackage + " (pid=" + r.callingPid
11288 + ", uid=" + r.callingUid + ")"
11289 + " requires " + info.activityInfo.permission
11290 + " due to receiver " + info.activityInfo.packageName
11291 + "/" + info.activityInfo.name);
11292 skip = true;
11293 }
11294 if (r.callingUid != Process.SYSTEM_UID &&
11295 r.requiredPermission != null) {
11296 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011297 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 checkPermission(r.requiredPermission,
11299 info.activityInfo.applicationInfo.packageName);
11300 } catch (RemoteException e) {
11301 perm = PackageManager.PERMISSION_DENIED;
11302 }
11303 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011304 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011305 + r.intent + " to "
11306 + info.activityInfo.applicationInfo.packageName
11307 + " requires " + r.requiredPermission
11308 + " due to sender " + r.callerPackage
11309 + " (uid " + r.callingUid + ")");
11310 skip = true;
11311 }
11312 }
11313 if (r.curApp != null && r.curApp.crashing) {
11314 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011315 if (DEBUG_BROADCAST) Slog.v(TAG,
11316 "Skipping deliver ordered " + r + " to " + r.curApp
11317 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 skip = true;
11319 }
11320
11321 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011322 if (DEBUG_BROADCAST) Slog.v(TAG,
11323 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 r.receiver = null;
11325 r.curFilter = null;
11326 r.state = BroadcastRecord.IDLE;
11327 scheduleBroadcastsLocked();
11328 return;
11329 }
11330
11331 r.state = BroadcastRecord.APP_RECEIVE;
11332 String targetProcess = info.activityInfo.processName;
11333 r.curComponent = new ComponentName(
11334 info.activityInfo.applicationInfo.packageName,
11335 info.activityInfo.name);
11336 r.curReceiver = info.activityInfo;
11337
11338 // Is this receiver's application already running?
11339 ProcessRecord app = getProcessRecordLocked(targetProcess,
11340 info.activityInfo.applicationInfo.uid);
11341 if (app != null && app.thread != null) {
11342 try {
11343 processCurBroadcastLocked(r, app);
11344 return;
11345 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011346 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 + r.curComponent, e);
11348 }
11349
11350 // If a dead object exception was thrown -- fall through to
11351 // restart the application.
11352 }
11353
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011354 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011355 if (DEBUG_BROADCAST) Slog.v(TAG,
11356 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 if ((r.curApp=startProcessLocked(targetProcess,
11358 info.activityInfo.applicationInfo, true,
11359 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011360 "broadcast", r.curComponent,
11361 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11362 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 // Ah, this recipient is unavailable. Finish it if necessary,
11364 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011365 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 + info.activityInfo.applicationInfo.packageName + "/"
11367 + info.activityInfo.applicationInfo.uid + " for broadcast "
11368 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011369 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11371 r.resultExtras, r.resultAbort, true);
11372 scheduleBroadcastsLocked();
11373 r.state = BroadcastRecord.IDLE;
11374 return;
11375 }
11376
11377 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011378 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 }
11380 }
11381
11382 // =========================================================
11383 // INSTRUMENTATION
11384 // =========================================================
11385
11386 public boolean startInstrumentation(ComponentName className,
11387 String profileFile, int flags, Bundle arguments,
11388 IInstrumentationWatcher watcher) {
11389 // Refuse possible leaked file descriptors
11390 if (arguments != null && arguments.hasFileDescriptors()) {
11391 throw new IllegalArgumentException("File descriptors passed in Bundle");
11392 }
11393
11394 synchronized(this) {
11395 InstrumentationInfo ii = null;
11396 ApplicationInfo ai = null;
11397 try {
11398 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011399 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011401 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 } catch (PackageManager.NameNotFoundException e) {
11403 }
11404 if (ii == null) {
11405 reportStartInstrumentationFailure(watcher, className,
11406 "Unable to find instrumentation info for: " + className);
11407 return false;
11408 }
11409 if (ai == null) {
11410 reportStartInstrumentationFailure(watcher, className,
11411 "Unable to find instrumentation target package: " + ii.targetPackage);
11412 return false;
11413 }
11414
11415 int match = mContext.getPackageManager().checkSignatures(
11416 ii.targetPackage, ii.packageName);
11417 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11418 String msg = "Permission Denial: starting instrumentation "
11419 + className + " from pid="
11420 + Binder.getCallingPid()
11421 + ", uid=" + Binder.getCallingPid()
11422 + " not allowed because package " + ii.packageName
11423 + " does not have a signature matching the target "
11424 + ii.targetPackage;
11425 reportStartInstrumentationFailure(watcher, className, msg);
11426 throw new SecurityException(msg);
11427 }
11428
11429 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011430 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011431 ProcessRecord app = addAppLocked(ai);
11432 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011433 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 app.instrumentationProfileFile = profileFile;
11435 app.instrumentationArguments = arguments;
11436 app.instrumentationWatcher = watcher;
11437 app.instrumentationResultClass = className;
11438 Binder.restoreCallingIdentity(origId);
11439 }
11440
11441 return true;
11442 }
11443
11444 /**
11445 * Report errors that occur while attempting to start Instrumentation. Always writes the
11446 * error to the logs, but if somebody is watching, send the report there too. This enables
11447 * the "am" command to report errors with more information.
11448 *
11449 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11450 * @param cn The component name of the instrumentation.
11451 * @param report The error report.
11452 */
11453 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11454 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011455 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 try {
11457 if (watcher != null) {
11458 Bundle results = new Bundle();
11459 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11460 results.putString("Error", report);
11461 watcher.instrumentationStatus(cn, -1, results);
11462 }
11463 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011464 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011465 }
11466 }
11467
11468 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11469 if (app.instrumentationWatcher != null) {
11470 try {
11471 // NOTE: IInstrumentationWatcher *must* be oneway here
11472 app.instrumentationWatcher.instrumentationFinished(
11473 app.instrumentationClass,
11474 resultCode,
11475 results);
11476 } catch (RemoteException e) {
11477 }
11478 }
11479 app.instrumentationWatcher = null;
11480 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011481 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 app.instrumentationProfileFile = null;
11483 app.instrumentationArguments = null;
11484
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011485 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 }
11487
11488 public void finishInstrumentation(IApplicationThread target,
11489 int resultCode, Bundle results) {
11490 // Refuse possible leaked file descriptors
11491 if (results != null && results.hasFileDescriptors()) {
11492 throw new IllegalArgumentException("File descriptors passed in Intent");
11493 }
11494
11495 synchronized(this) {
11496 ProcessRecord app = getRecordForAppLocked(target);
11497 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011498 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499 return;
11500 }
11501 final long origId = Binder.clearCallingIdentity();
11502 finishInstrumentationLocked(app, resultCode, results);
11503 Binder.restoreCallingIdentity(origId);
11504 }
11505 }
11506
11507 // =========================================================
11508 // CONFIGURATION
11509 // =========================================================
11510
11511 public ConfigurationInfo getDeviceConfigurationInfo() {
11512 ConfigurationInfo config = new ConfigurationInfo();
11513 synchronized (this) {
11514 config.reqTouchScreen = mConfiguration.touchscreen;
11515 config.reqKeyboardType = mConfiguration.keyboard;
11516 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011517 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11518 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11520 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011521 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11522 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011523 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11524 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011525 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 }
11527 return config;
11528 }
11529
11530 public Configuration getConfiguration() {
11531 Configuration ci;
11532 synchronized(this) {
11533 ci = new Configuration(mConfiguration);
11534 }
11535 return ci;
11536 }
11537
11538 public void updateConfiguration(Configuration values) {
11539 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11540 "updateConfiguration()");
11541
11542 synchronized(this) {
11543 if (values == null && mWindowManager != null) {
11544 // sentinel: fetch the current configuration from the window manager
11545 values = mWindowManager.computeNewConfiguration();
11546 }
11547
11548 final long origId = Binder.clearCallingIdentity();
11549 updateConfigurationLocked(values, null);
11550 Binder.restoreCallingIdentity(origId);
11551 }
11552 }
11553
11554 /**
11555 * Do either or both things: (1) change the current configuration, and (2)
11556 * make sure the given activity is running with the (now) current
11557 * configuration. Returns true if the activity has been left running, or
11558 * false if <var>starting</var> is being destroyed to match the new
11559 * configuration.
11560 */
11561 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011562 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 int changes = 0;
11564
11565 boolean kept = true;
11566
11567 if (values != null) {
11568 Configuration newConfig = new Configuration(mConfiguration);
11569 changes = newConfig.updateFrom(values);
11570 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011571 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011572 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 }
11574
Doug Zongker2bec3d42009-12-04 12:52:44 -080011575 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576
11577 if (values.locale != null) {
11578 saveLocaleLocked(values.locale,
11579 !values.locale.equals(mConfiguration.locale),
11580 values.userSetLocale);
11581 }
11582
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011583 mConfigurationSeq++;
11584 if (mConfigurationSeq <= 0) {
11585 mConfigurationSeq = 1;
11586 }
11587 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011589 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011590
11591 AttributeCache ac = AttributeCache.instance();
11592 if (ac != null) {
11593 ac.updateConfiguration(mConfiguration);
11594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011596 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11597 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11598 msg.obj = new Configuration(mConfiguration);
11599 mHandler.sendMessage(msg);
11600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011601
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011602 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11603 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 try {
11605 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011606 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011607 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608 app.thread.scheduleConfigurationChanged(mConfiguration);
11609 }
11610 } catch (Exception e) {
11611 }
11612 }
11613 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011614 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11615 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11617 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011618 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11619 broadcastIntentLocked(null, null,
11620 new Intent(Intent.ACTION_LOCALE_CHANGED),
11621 null, null, 0, null, null,
11622 null, false, false, MY_PID, Process.SYSTEM_UID);
11623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 }
11625 }
11626
11627 if (changes != 0 && starting == null) {
11628 // If the configuration changed, and the caller is not already
11629 // in the process of starting an activity, then find the top
11630 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011631 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 }
11633
11634 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011635 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 if (kept) {
11637 // If this didn't result in the starting activity being
11638 // destroyed, then we need to make sure at this point that all
11639 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011640 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011642 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 }
11644 }
11645
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011646 if (values != null && mWindowManager != null) {
11647 mWindowManager.setNewConfiguration(mConfiguration);
11648 }
11649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 return kept;
11651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652
11653 /**
11654 * Save the locale. You must be inside a synchronized (this) block.
11655 */
11656 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11657 if(isDiff) {
11658 SystemProperties.set("user.language", l.getLanguage());
11659 SystemProperties.set("user.region", l.getCountry());
11660 }
11661
11662 if(isPersist) {
11663 SystemProperties.set("persist.sys.language", l.getLanguage());
11664 SystemProperties.set("persist.sys.country", l.getCountry());
11665 SystemProperties.set("persist.sys.localevar", l.getVariant());
11666 }
11667 }
11668
11669 // =========================================================
11670 // LIFETIME MANAGEMENT
11671 // =========================================================
11672
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011673 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11674 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011675 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011676 // This adjustment has already been computed. If we are calling
11677 // from the top, we may have already computed our adjustment with
11678 // an earlier hidden adjustment that isn't really for us... if
11679 // so, use the new hidden adjustment.
11680 if (!recursed && app.hidden) {
11681 app.curAdj = hiddenAdj;
11682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 return app.curAdj;
11684 }
11685
11686 if (app.thread == null) {
11687 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011688 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 return (app.curAdj=EMPTY_APP_ADJ);
11690 }
11691
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011692 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11693 // The max adjustment doesn't allow this app to be anything
11694 // below foreground, so it is not worth doing work for it.
11695 app.adjType = "fixed";
11696 app.adjSeq = mAdjSeq;
11697 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011698 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011699 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11700 return (app.curAdj=app.maxAdj);
11701 }
11702
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011703 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011704 app.adjSource = null;
11705 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011706 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011707 app.empty = false;
11708 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011709
The Android Open Source Project4df24232009-03-05 14:34:35 -080011710 // Determine the importance of the process, starting with most
11711 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011713 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011714 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011715 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 // The last app on the list is the foreground app.
11717 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011718 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011719 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011720 } else if (app.instrumentationClass != null) {
11721 // Don't want to kill running instrumentation.
11722 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011723 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011724 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011725 } else if (app.curReceiver != null ||
11726 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11727 // An app that is currently receiving a broadcast also
11728 // counts as being in the foreground.
11729 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011730 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011731 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011732 } else if (app.executingServices.size() > 0) {
11733 // An app that is currently executing a service callback also
11734 // counts as being in the foreground.
11735 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011736 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011737 app.adjType = "exec-service";
11738 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011740 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011741 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011742 app.adjType = "foreground-service";
11743 } else if (app.forcingToForeground != null) {
11744 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011745 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011746 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011747 app.adjType = "force-foreground";
11748 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011749 } else if (app == mHeavyWeightProcess) {
11750 // We don't want to kill the current heavy-weight process.
11751 adj = HEAVY_WEIGHT_APP_ADJ;
11752 schedGroup = Process.THREAD_GROUP_DEFAULT;
11753 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011754 } else if (app == mHomeProcess) {
11755 // This process is hosting what we currently consider to be the
11756 // home app, so we don't want to let it go into the background.
11757 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011758 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011759 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011760 } else if ((N=app.activities.size()) != 0) {
11761 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011762 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011764 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011765 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011766 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011768 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011770 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011772 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011773 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774 break;
11775 }
11776 }
11777 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011778 // A very not-needed process. If this is lower in the lru list,
11779 // we will push it in to the empty bucket.
11780 app.hidden = true;
11781 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011782 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011783 adj = hiddenAdj;
11784 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 }
11786
Joe Onorato8a9b2202010-02-26 18:56:32 -080011787 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011788
The Android Open Source Project4df24232009-03-05 14:34:35 -080011789 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 // there are applications dependent on our services or providers, but
11791 // this gives us a baseline and makes sure we don't get into an
11792 // infinite recursion.
11793 app.adjSeq = mAdjSeq;
11794 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011795
Christopher Tate6fa95972009-06-05 18:43:55 -070011796 if (mBackupTarget != null && app == mBackupTarget.app) {
11797 // If possible we want to avoid killing apps while they're being backed up
11798 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011799 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011800 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011801 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011802 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011803 }
11804 }
11805
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011806 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11807 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 final long now = SystemClock.uptimeMillis();
11809 // This process is more important if the top activity is
11810 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011811 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011812 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011813 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011814 if (s.startRequested) {
11815 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11816 // This service has seen some activity within
11817 // recent memory, so we will keep its process ahead
11818 // of the background processes.
11819 if (adj > SECONDARY_SERVER_ADJ) {
11820 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011821 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011822 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 }
11824 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011825 // If we have let the service slide into the background
11826 // state, still have some text describing what it is doing
11827 // even though the service no longer has an impact.
11828 if (adj > SECONDARY_SERVER_ADJ) {
11829 app.adjType = "started-bg-services";
11830 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011831 // Don't kill this process because it is doing work; it
11832 // has said it is doing work.
11833 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011835 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11836 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011837 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 = s.connections.values().iterator();
11839 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011840 ArrayList<ConnectionRecord> clist = kt.next();
11841 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11842 // XXX should compute this based on the max of
11843 // all connected clients.
11844 ConnectionRecord cr = clist.get(i);
11845 if (cr.binding.client == app) {
11846 // Binding to ourself is not interesting.
11847 continue;
11848 }
11849 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11850 ProcessRecord client = cr.binding.client;
11851 int myHiddenAdj = hiddenAdj;
11852 if (myHiddenAdj > client.hiddenAdj) {
11853 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11854 myHiddenAdj = client.hiddenAdj;
11855 } else {
11856 myHiddenAdj = VISIBLE_APP_ADJ;
11857 }
11858 }
11859 int clientAdj = computeOomAdjLocked(
11860 client, myHiddenAdj, TOP_APP, true);
11861 if (adj > clientAdj) {
11862 adj = clientAdj >= VISIBLE_APP_ADJ
11863 ? clientAdj : VISIBLE_APP_ADJ;
11864 if (!client.hidden) {
11865 app.hidden = false;
11866 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011867 if (client.keeping) {
11868 app.keeping = true;
11869 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011870 app.adjType = "service";
11871 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11872 .REASON_SERVICE_IN_USE;
11873 app.adjSource = cr.binding.client;
11874 app.adjTarget = s.name;
11875 }
11876 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11877 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11878 schedGroup = Process.THREAD_GROUP_DEFAULT;
11879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 }
11881 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011882 ActivityRecord a = cr.activity;
11883 //if (a != null) {
11884 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11885 //}
11886 if (a != null && adj > FOREGROUND_APP_ADJ &&
11887 (a.state == ActivityState.RESUMED
11888 || a.state == ActivityState.PAUSING)) {
11889 adj = FOREGROUND_APP_ADJ;
11890 schedGroup = Process.THREAD_GROUP_DEFAULT;
11891 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011892 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011893 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11894 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011895 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011896 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011898 }
11899 }
11900 }
11901 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011902
Dianne Hackborn287952c2010-09-22 22:34:31 -070011903 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011904 // would like to avoid killing it unless it would prevent the current
11905 // application from running. By default we put the process in
11906 // with the rest of the background processes; as we scan through
11907 // its services we may bump it up from there.
11908 if (adj > hiddenAdj) {
11909 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011910 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011911 app.adjType = "bg-services";
11912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 }
11914
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011915 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11916 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011917 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011918 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11919 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011920 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 if (cpr.clients.size() != 0) {
11922 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11923 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11924 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011925 if (client == app) {
11926 // Being our own client is not interesting.
11927 continue;
11928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 int myHiddenAdj = hiddenAdj;
11930 if (myHiddenAdj > client.hiddenAdj) {
11931 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11932 myHiddenAdj = client.hiddenAdj;
11933 } else {
11934 myHiddenAdj = FOREGROUND_APP_ADJ;
11935 }
11936 }
11937 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011938 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011939 if (adj > clientAdj) {
11940 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011941 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011942 if (!client.hidden) {
11943 app.hidden = false;
11944 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011945 if (client.keeping) {
11946 app.keeping = true;
11947 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011948 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011949 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11950 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011951 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011952 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011953 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011954 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11955 schedGroup = Process.THREAD_GROUP_DEFAULT;
11956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957 }
11958 }
11959 // If the provider has external (non-framework) process
11960 // dependencies, ensure that its adjustment is at least
11961 // FOREGROUND_APP_ADJ.
11962 if (cpr.externals != 0) {
11963 if (adj > FOREGROUND_APP_ADJ) {
11964 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011965 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011966 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011967 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011968 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011969 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011970 }
11971 }
11972 }
11973 }
11974
11975 app.curRawAdj = adj;
11976
Joe Onorato8a9b2202010-02-26 18:56:32 -080011977 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11979 if (adj > app.maxAdj) {
11980 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011981 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011982 schedGroup = Process.THREAD_GROUP_DEFAULT;
11983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011984 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011985 if (adj < HIDDEN_APP_MIN_ADJ) {
11986 app.keeping = true;
11987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988
11989 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011990 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011992 return adj;
11993 }
11994
11995 /**
11996 * Ask a given process to GC right now.
11997 */
11998 final void performAppGcLocked(ProcessRecord app) {
11999 try {
12000 app.lastRequestedGc = SystemClock.uptimeMillis();
12001 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012002 if (app.reportLowMemory) {
12003 app.reportLowMemory = false;
12004 app.thread.scheduleLowMemory();
12005 } else {
12006 app.thread.processInBackground();
12007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008 }
12009 } catch (Exception e) {
12010 // whatever.
12011 }
12012 }
12013
12014 /**
12015 * Returns true if things are idle enough to perform GCs.
12016 */
Josh Bartel7f208742010-02-25 11:01:44 -060012017 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018 return mParallelBroadcasts.size() == 0
12019 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012020 && (mSleeping || (mMainStack.mResumedActivity != null &&
12021 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 }
12023
12024 /**
12025 * Perform GCs on all processes that are waiting for it, but only
12026 * if things are idle.
12027 */
12028 final void performAppGcsLocked() {
12029 final int N = mProcessesToGc.size();
12030 if (N <= 0) {
12031 return;
12032 }
Josh Bartel7f208742010-02-25 11:01:44 -060012033 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012034 while (mProcessesToGc.size() > 0) {
12035 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012036 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012037 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12038 <= SystemClock.uptimeMillis()) {
12039 // To avoid spamming the system, we will GC processes one
12040 // at a time, waiting a few seconds between each.
12041 performAppGcLocked(proc);
12042 scheduleAppGcsLocked();
12043 return;
12044 } else {
12045 // It hasn't been long enough since we last GCed this
12046 // process... put it in the list to wait for its time.
12047 addProcessToGcListLocked(proc);
12048 break;
12049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012050 }
12051 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012052
12053 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012054 }
12055 }
12056
12057 /**
12058 * If all looks good, perform GCs on all processes waiting for them.
12059 */
12060 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012061 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012062 performAppGcsLocked();
12063 return;
12064 }
12065 // Still not idle, wait some more.
12066 scheduleAppGcsLocked();
12067 }
12068
12069 /**
12070 * Schedule the execution of all pending app GCs.
12071 */
12072 final void scheduleAppGcsLocked() {
12073 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012074
12075 if (mProcessesToGc.size() > 0) {
12076 // Schedule a GC for the time to the next process.
12077 ProcessRecord proc = mProcessesToGc.get(0);
12078 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12079
12080 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12081 long now = SystemClock.uptimeMillis();
12082 if (when < (now+GC_TIMEOUT)) {
12083 when = now + GC_TIMEOUT;
12084 }
12085 mHandler.sendMessageAtTime(msg, when);
12086 }
12087 }
12088
12089 /**
12090 * Add a process to the array of processes waiting to be GCed. Keeps the
12091 * list in sorted order by the last GC time. The process can't already be
12092 * on the list.
12093 */
12094 final void addProcessToGcListLocked(ProcessRecord proc) {
12095 boolean added = false;
12096 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12097 if (mProcessesToGc.get(i).lastRequestedGc <
12098 proc.lastRequestedGc) {
12099 added = true;
12100 mProcessesToGc.add(i+1, proc);
12101 break;
12102 }
12103 }
12104 if (!added) {
12105 mProcessesToGc.add(0, proc);
12106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107 }
12108
12109 /**
12110 * Set up to ask a process to GC itself. This will either do it
12111 * immediately, or put it on the list of processes to gc the next
12112 * time things are idle.
12113 */
12114 final void scheduleAppGcLocked(ProcessRecord app) {
12115 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012116 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012117 return;
12118 }
12119 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012120 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012121 scheduleAppGcsLocked();
12122 }
12123 }
12124
Dianne Hackborn287952c2010-09-22 22:34:31 -070012125 final void checkExcessivePowerUsageLocked(boolean doKills) {
12126 updateCpuStatsNow();
12127
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012128 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012129 boolean doWakeKills = doKills;
12130 boolean doCpuKills = doKills;
12131 if (mLastPowerCheckRealtime == 0) {
12132 doWakeKills = false;
12133 }
12134 if (mLastPowerCheckUptime == 0) {
12135 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012136 }
12137 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012138 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012139 }
12140 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012141 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12142 final long curUptime = SystemClock.uptimeMillis();
12143 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12144 mLastPowerCheckRealtime = curRealtime;
12145 mLastPowerCheckUptime = curUptime;
12146 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12147 doWakeKills = false;
12148 }
12149 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12150 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012151 }
12152 int i = mLruProcesses.size();
12153 while (i > 0) {
12154 i--;
12155 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012156 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012157 long wtime;
12158 synchronized (stats) {
12159 wtime = stats.getProcessWakeTime(app.info.uid,
12160 app.pid, curRealtime);
12161 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012162 long wtimeUsed = wtime - app.lastWakeTime;
12163 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12164 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012165 StringBuilder sb = new StringBuilder(128);
12166 sb.append("Wake for ");
12167 app.toShortString(sb);
12168 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012169 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012170 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012171 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012172 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012173 sb.append((wtimeUsed*100)/realtimeSince);
12174 sb.append("%)");
12175 Slog.i(TAG, sb.toString());
12176 sb.setLength(0);
12177 sb.append("CPU for ");
12178 app.toShortString(sb);
12179 sb.append(": over ");
12180 TimeUtils.formatDuration(uptimeSince, sb);
12181 sb.append(" used ");
12182 TimeUtils.formatDuration(cputimeUsed, sb);
12183 sb.append(" (");
12184 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012185 sb.append("%)");
12186 Slog.i(TAG, sb.toString());
12187 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012188 // If a process has held a wake lock for more
12189 // than 50% of the time during this period,
12190 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012191 if (doWakeKills && realtimeSince > 0
12192 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12193 synchronized (stats) {
12194 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12195 realtimeSince, wtimeUsed);
12196 }
12197 Slog.w(TAG, "Excessive wake lock in " + app.processName
12198 + " (pid " + app.pid + "): held " + wtimeUsed
12199 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012200 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12201 app.processName, app.setAdj, "excessive wake lock");
12202 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012203 } else if (doCpuKills && uptimeSince > 0
12204 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12205 synchronized (stats) {
12206 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12207 uptimeSince, cputimeUsed);
12208 }
12209 Slog.w(TAG, "Excessive CPU in " + app.processName
12210 + " (pid " + app.pid + "): used " + cputimeUsed
12211 + " during " + uptimeSince);
12212 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12213 app.processName, app.setAdj, "excessive cpu");
12214 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012215 } else {
12216 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012217 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012218 }
12219 }
12220 }
12221 }
12222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 private final boolean updateOomAdjLocked(
12224 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12225 app.hiddenAdj = hiddenAdj;
12226
12227 if (app.thread == null) {
12228 return true;
12229 }
12230
Dianne Hackborn287952c2010-09-22 22:34:31 -070012231 final boolean wasKeeping = app.keeping;
12232
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012233 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012235 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012236 if (app.curRawAdj != app.setRawAdj) {
12237 if (app.curRawAdj > FOREGROUND_APP_ADJ
12238 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12239 // If this app is transitioning from foreground to
12240 // non-foreground, have it do a gc.
12241 scheduleAppGcLocked(app);
12242 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12243 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12244 // Likewise do a gc when an app is moving in to the
12245 // background (such as a service stopping).
12246 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012247 }
12248
12249 if (wasKeeping && !app.keeping) {
12250 // This app is no longer something we want to keep. Note
12251 // its current wake lock time to later know to kill it if
12252 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012253 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12254 synchronized (stats) {
12255 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12256 app.pid, SystemClock.elapsedRealtime());
12257 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012258 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012259 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012261 app.setRawAdj = app.curRawAdj;
12262 }
12263 if (adj != app.setAdj) {
12264 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012265 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012266 TAG, "Set app " + app.processName +
12267 " oom adj to " + adj);
12268 app.setAdj = adj;
12269 } else {
12270 return false;
12271 }
12272 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012273 if (app.setSchedGroup != app.curSchedGroup) {
12274 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012275 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012276 "Setting process group of " + app.processName
12277 + " to " + app.curSchedGroup);
12278 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012279 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012280 try {
12281 Process.setProcessGroup(app.pid, app.curSchedGroup);
12282 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012283 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012284 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012285 e.printStackTrace();
12286 } finally {
12287 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012288 }
12289 }
12290 if (false) {
12291 if (app.thread != null) {
12292 try {
12293 app.thread.setSchedulingGroup(app.curSchedGroup);
12294 } catch (RemoteException e) {
12295 }
12296 }
12297 }
12298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012299 }
12300
12301 return true;
12302 }
12303
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012304 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012305 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012306 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012307 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012309 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012310 }
12311 }
12312 return resumedActivity;
12313 }
12314
12315 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012316 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012317 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12318 int curAdj = app.curAdj;
12319 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12320 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12321
12322 mAdjSeq++;
12323
12324 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12325 if (res) {
12326 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12327 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12328 if (nowHidden != wasHidden) {
12329 // Changed to/from hidden state, so apps after it in the LRU
12330 // list may also be changed.
12331 updateOomAdjLocked();
12332 }
12333 }
12334 return res;
12335 }
12336
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012337 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012339 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012340 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12341
12342 if (false) {
12343 RuntimeException e = new RuntimeException();
12344 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012345 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 }
12347
12348 mAdjSeq++;
12349
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012350 // Let's determine how many processes we have running vs.
12351 // how many slots we have for background processes; we may want
12352 // to put multiple processes in a slot of there are enough of
12353 // them.
12354 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12355 int factor = (mLruProcesses.size()-4)/numSlots;
12356 if (factor < 1) factor = 1;
12357 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012358 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 // First try updating the OOM adjustment for each of the
12361 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012362 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12364 while (i > 0) {
12365 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012366 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012367 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012368 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012369 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012370 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012371 step++;
12372 if (step >= factor) {
12373 step = 0;
12374 curHiddenAdj++;
12375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012376 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012377 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012378 if (!app.killedBackground) {
12379 numHidden++;
12380 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012381 Slog.i(TAG, "No longer want " + app.processName
12382 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012383 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12384 app.processName, app.setAdj, "too many background");
12385 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012386 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012387 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012388 }
12389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012390 } else {
12391 didOomAdj = false;
12392 }
12393 }
12394
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012395 // If we return false, we will fall back on killing processes to
12396 // have a fixed limit. Do this if a limit has been requested; else
12397 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012398 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12399 }
12400
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012401 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402 synchronized (this) {
12403 int i;
12404
12405 // First remove any unused application processes whose package
12406 // has been removed.
12407 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12408 final ProcessRecord app = mRemovedProcesses.get(i);
12409 if (app.activities.size() == 0
12410 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012411 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012412 TAG, "Exiting empty application process "
12413 + app.processName + " ("
12414 + (app.thread != null ? app.thread.asBinder() : null)
12415 + ")\n");
12416 if (app.pid > 0 && app.pid != MY_PID) {
12417 Process.killProcess(app.pid);
12418 } else {
12419 try {
12420 app.thread.scheduleExit();
12421 } catch (Exception e) {
12422 // Ignore exceptions.
12423 }
12424 }
12425 cleanUpApplicationRecordLocked(app, false, -1);
12426 mRemovedProcesses.remove(i);
12427
12428 if (app.persistent) {
12429 if (app.persistent) {
12430 addAppLocked(app.info);
12431 }
12432 }
12433 }
12434 }
12435
12436 // Now try updating the OOM adjustment for each of the
12437 // application processes based on their current state.
12438 // If the setOomAdj() API is not supported, then go with our
12439 // back-up plan...
12440 if (!updateOomAdjLocked()) {
12441
12442 // Count how many processes are running services.
12443 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012444 for (i=mLruProcesses.size()-1; i>=0; i--) {
12445 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446
12447 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012448 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012449 // Don't count processes holding services against our
12450 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012451 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 TAG, "Not trimming app " + app + " with services: "
12453 + app.services);
12454 numServiceProcs++;
12455 }
12456 }
12457
12458 int curMaxProcs = mProcessLimit;
12459 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12460 if (mAlwaysFinishActivities) {
12461 curMaxProcs = 1;
12462 }
12463 curMaxProcs += numServiceProcs;
12464
12465 // Quit as many processes as we can to get down to the desired
12466 // process count. First remove any processes that no longer
12467 // have activites running in them.
12468 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012469 i<mLruProcesses.size()
12470 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012472 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012473 // Quit an application only if it is not currently
12474 // running any activities.
12475 if (!app.persistent && app.activities.size() == 0
12476 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012477 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012478 TAG, "Exiting empty application process "
12479 + app.processName + " ("
12480 + (app.thread != null ? app.thread.asBinder() : null)
12481 + ")\n");
12482 if (app.pid > 0 && app.pid != MY_PID) {
12483 Process.killProcess(app.pid);
12484 } else {
12485 try {
12486 app.thread.scheduleExit();
12487 } catch (Exception e) {
12488 // Ignore exceptions.
12489 }
12490 }
12491 // todo: For now we assume the application is not buggy
12492 // or evil, and will quit as a result of our request.
12493 // Eventually we need to drive this off of the death
12494 // notification, and kill the process if it takes too long.
12495 cleanUpApplicationRecordLocked(app, false, i);
12496 i--;
12497 }
12498 }
12499
12500 // If we still have too many processes, now from the least
12501 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012502 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012503 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 " of " + curMaxProcs + " processes");
12505 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012506 i<mLruProcesses.size()
12507 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012509 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012510 // Quit the application only if we have a state saved for
12511 // all of its activities.
12512 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012513 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012514 int NUMA = app.activities.size();
12515 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012516 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012517 TAG, "Looking to quit " + app.processName);
12518 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012519 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012520 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012521 TAG, " " + r.intent.getComponent().flattenToShortString()
12522 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12523 canQuit = (r.haveState || !r.stateNotNeeded)
12524 && !r.visible && r.stopped;
12525 }
12526 if (canQuit) {
12527 // Finish all of the activities, and then the app itself.
12528 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012529 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012530 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012531 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 }
12533 r.resultTo = null;
12534 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012535 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012536 + app.processName + " ("
12537 + (app.thread != null ? app.thread.asBinder() : null)
12538 + ")\n");
12539 if (app.pid > 0 && app.pid != MY_PID) {
12540 Process.killProcess(app.pid);
12541 } else {
12542 try {
12543 app.thread.scheduleExit();
12544 } catch (Exception e) {
12545 // Ignore exceptions.
12546 }
12547 }
12548 // todo: For now we assume the application is not buggy
12549 // or evil, and will quit as a result of our request.
12550 // Eventually we need to drive this off of the death
12551 // notification, and kill the process if it takes too long.
12552 cleanUpApplicationRecordLocked(app, false, i);
12553 i--;
12554 //dump();
12555 }
12556 }
12557
12558 }
12559
12560 int curMaxActivities = MAX_ACTIVITIES;
12561 if (mAlwaysFinishActivities) {
12562 curMaxActivities = 1;
12563 }
12564
12565 // Finally, if there are too many activities now running, try to
12566 // finish as many as we can to get back down to the limit.
12567 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012568 i<mMainStack.mLRUActivities.size()
12569 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012571 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012572 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012573
12574 // We can finish this one if we have its icicle saved and
12575 // it is not persistent.
12576 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012577 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012578 final int origSize = mMainStack.mLRUActivities.size();
12579 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012580
12581 // This will remove it from the LRU list, so keep
12582 // our index at the same value. Note that this check to
12583 // see if the size changes is just paranoia -- if
12584 // something unexpected happens, we don't want to end up
12585 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012586 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012587 i--;
12588 }
12589 }
12590 }
12591 }
12592 }
12593
12594 /** This method sends the specified signal to each of the persistent apps */
12595 public void signalPersistentProcesses(int sig) throws RemoteException {
12596 if (sig != Process.SIGNAL_USR1) {
12597 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12598 }
12599
12600 synchronized (this) {
12601 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12602 != PackageManager.PERMISSION_GRANTED) {
12603 throw new SecurityException("Requires permission "
12604 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12605 }
12606
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012607 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12608 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012609 if (r.thread != null && r.persistent) {
12610 Process.sendSignal(r.pid, sig);
12611 }
12612 }
12613 }
12614 }
12615
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012616 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012617 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012618
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012619 try {
12620 synchronized (this) {
12621 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12622 // its own permission.
12623 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12624 != PackageManager.PERMISSION_GRANTED) {
12625 throw new SecurityException("Requires permission "
12626 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012627 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012628
12629 if (start && fd == null) {
12630 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012631 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012632
12633 ProcessRecord proc = null;
12634 try {
12635 int pid = Integer.parseInt(process);
12636 synchronized (mPidsSelfLocked) {
12637 proc = mPidsSelfLocked.get(pid);
12638 }
12639 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012640 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012641
12642 if (proc == null) {
12643 HashMap<String, SparseArray<ProcessRecord>> all
12644 = mProcessNames.getMap();
12645 SparseArray<ProcessRecord> procs = all.get(process);
12646 if (procs != null && procs.size() > 0) {
12647 proc = procs.valueAt(0);
12648 }
12649 }
12650
12651 if (proc == null || proc.thread == null) {
12652 throw new IllegalArgumentException("Unknown process: " + process);
12653 }
12654
12655 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12656 if (isSecure) {
12657 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12658 throw new SecurityException("Process not debuggable: " + proc);
12659 }
12660 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012661
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012662 proc.thread.profilerControl(start, path, fd);
12663 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012664 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012665 }
12666 } catch (RemoteException e) {
12667 throw new IllegalStateException("Process disappeared");
12668 } finally {
12669 if (fd != null) {
12670 try {
12671 fd.close();
12672 } catch (IOException e) {
12673 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012674 }
12675 }
12676 }
Andy McFadden824c5102010-07-09 16:26:57 -070012677
12678 public boolean dumpHeap(String process, boolean managed,
12679 String path, ParcelFileDescriptor fd) throws RemoteException {
12680
12681 try {
12682 synchronized (this) {
12683 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12684 // its own permission (same as profileControl).
12685 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12686 != PackageManager.PERMISSION_GRANTED) {
12687 throw new SecurityException("Requires permission "
12688 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12689 }
12690
12691 if (fd == null) {
12692 throw new IllegalArgumentException("null fd");
12693 }
12694
12695 ProcessRecord proc = null;
12696 try {
12697 int pid = Integer.parseInt(process);
12698 synchronized (mPidsSelfLocked) {
12699 proc = mPidsSelfLocked.get(pid);
12700 }
12701 } catch (NumberFormatException e) {
12702 }
12703
12704 if (proc == null) {
12705 HashMap<String, SparseArray<ProcessRecord>> all
12706 = mProcessNames.getMap();
12707 SparseArray<ProcessRecord> procs = all.get(process);
12708 if (procs != null && procs.size() > 0) {
12709 proc = procs.valueAt(0);
12710 }
12711 }
12712
12713 if (proc == null || proc.thread == null) {
12714 throw new IllegalArgumentException("Unknown process: " + process);
12715 }
12716
12717 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12718 if (isSecure) {
12719 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12720 throw new SecurityException("Process not debuggable: " + proc);
12721 }
12722 }
12723
12724 proc.thread.dumpHeap(managed, path, fd);
12725 fd = null;
12726 return true;
12727 }
12728 } catch (RemoteException e) {
12729 throw new IllegalStateException("Process disappeared");
12730 } finally {
12731 if (fd != null) {
12732 try {
12733 fd.close();
12734 } catch (IOException e) {
12735 }
12736 }
12737 }
12738 }
12739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12741 public void monitor() {
12742 synchronized (this) { }
12743 }
12744}