blob: 60b2b67d1cb6a15c0bcb1989365a6c821b450912 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962
963 AlertDialog mUidAlert;
964
965 final Handler mHandler = new Handler() {
966 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800967 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 //}
969
970 public void handleMessage(Message msg) {
971 switch (msg.what) {
972 case SHOW_ERROR_MSG: {
973 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 synchronized (ActivityManagerService.this) {
975 ProcessRecord proc = (ProcessRecord)data.get("app");
976 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 return;
979 }
980 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700981 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800982 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 d.show();
984 proc.crashDialog = d;
985 } else {
986 // The device is asleep, so just pretend that the user
987 // saw a crash dialog and hit "force quit".
988 res.set(0);
989 }
990 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700991
992 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } break;
994 case SHOW_NOT_RESPONDING_MSG: {
995 synchronized (ActivityManagerService.this) {
996 HashMap data = (HashMap) msg.obj;
997 ProcessRecord proc = (ProcessRecord)data.get("app");
998 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 return;
1001 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001002
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001003 Intent intent = new Intent("android.intent.action.ANR");
1004 if (!mProcessesReady) {
1005 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1006 }
1007 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001008 null, null, 0, null, null, null,
1009 false, false, MY_PID, Process.SYSTEM_UID);
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001012 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 d.show();
1014 proc.anrDialog = d;
1015 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001016
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001019 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1020 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1021 synchronized (ActivityManagerService.this) {
1022 ProcessRecord proc = (ProcessRecord) data.get("app");
1023 if (proc == null) {
1024 Slog.e(TAG, "App not found when showing strict mode dialog.");
1025 break;
1026 }
1027 if (proc.crashDialog != null) {
1028 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1029 return;
1030 }
1031 AppErrorResult res = (AppErrorResult) data.get("result");
1032 if (!mSleeping && !mShuttingDown) {
1033 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1034 d.show();
1035 proc.crashDialog = d;
1036 } else {
1037 // The device is asleep, so just pretend that the user
1038 // saw a crash dialog and hit "force quit".
1039 res.set(0);
1040 }
1041 }
1042 ensureBootCompleted();
1043 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 case SHOW_FACTORY_ERROR_MSG: {
1045 Dialog d = new FactoryErrorDialog(
1046 mContext, msg.getData().getCharSequence("msg"));
1047 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001048 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 } break;
1050 case UPDATE_CONFIGURATION_MSG: {
1051 final ContentResolver resolver = mContext.getContentResolver();
1052 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1053 } break;
1054 case GC_BACKGROUND_PROCESSES_MSG: {
1055 synchronized (ActivityManagerService.this) {
1056 performAppGcsIfAppropriateLocked();
1057 }
1058 } break;
1059 case WAIT_FOR_DEBUGGER_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 ProcessRecord app = (ProcessRecord)msg.obj;
1062 if (msg.arg1 != 0) {
1063 if (!app.waitedForDebugger) {
1064 Dialog d = new AppWaitingForDebuggerDialog(
1065 ActivityManagerService.this,
1066 mContext, app);
1067 app.waitDialog = d;
1068 app.waitedForDebugger = true;
1069 d.show();
1070 }
1071 } else {
1072 if (app.waitDialog != null) {
1073 app.waitDialog.dismiss();
1074 app.waitDialog = null;
1075 }
1076 }
1077 }
1078 } break;
1079 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 TAG, "Received BROADCAST_INTENT_MSG");
1082 processNextBroadcast(true);
1083 } break;
1084 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001085 synchronized (ActivityManagerService.this) {
1086 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001090 if (mDidDexOpt) {
1091 mDidDexOpt = false;
1092 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1093 nmsg.obj = msg.obj;
1094 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1095 return;
1096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 serviceTimeout((ProcessRecord)msg.obj);
1098 } break;
1099 case UPDATE_TIME_ZONE: {
1100 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001101 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1102 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (r.thread != null) {
1104 try {
1105 r.thread.updateTimeZone();
1106 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 }
1109 }
1110 }
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 case SHOW_UID_ERROR_MSG: {
1114 // XXX This is a temporary dialog, no need to localize.
1115 AlertDialog d = new BaseErrorDialog(mContext);
1116 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1117 d.setCancelable(false);
1118 d.setTitle("System UIDs Inconsistent");
1119 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 +02001120 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1122 mUidAlert = d;
1123 d.show();
1124 } break;
1125 case IM_FEELING_LUCKY_MSG: {
1126 if (mUidAlert != null) {
1127 mUidAlert.dismiss();
1128 mUidAlert = null;
1129 }
1130 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001132 if (mDidDexOpt) {
1133 mDidDexOpt = false;
1134 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1135 nmsg.obj = msg.obj;
1136 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1137 return;
1138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 ProcessRecord app = (ProcessRecord)msg.obj;
1140 synchronized (ActivityManagerService.this) {
1141 processStartTimedOutLocked(app);
1142 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001143 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001144 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1145 synchronized (ActivityManagerService.this) {
1146 doPendingActivityLaunchesLocked(true);
1147 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001148 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001149 case KILL_APPLICATION_MSG: {
1150 synchronized (ActivityManagerService.this) {
1151 int uid = msg.arg1;
1152 boolean restart = (msg.arg2 == 1);
1153 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001154 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001155 }
1156 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001157 case FINALIZE_PENDING_INTENT_MSG: {
1158 ((PendingIntentRecord)msg.obj).completeFinalize();
1159 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001160 case POST_HEAVY_NOTIFICATION_MSG: {
1161 INotificationManager inm = NotificationManager.getService();
1162 if (inm == null) {
1163 return;
1164 }
1165
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001166 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001167 ProcessRecord process = root.app;
1168 if (process == null) {
1169 return;
1170 }
1171
1172 try {
1173 Context context = mContext.createPackageContext(process.info.packageName, 0);
1174 String text = mContext.getString(R.string.heavy_weight_notification,
1175 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1176 Notification notification = new Notification();
1177 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1178 notification.when = 0;
1179 notification.flags = Notification.FLAG_ONGOING_EVENT;
1180 notification.tickerText = text;
1181 notification.defaults = 0; // please be quiet
1182 notification.sound = null;
1183 notification.vibrate = null;
1184 notification.setLatestEventInfo(context, text,
1185 mContext.getText(R.string.heavy_weight_notification_detail),
1186 PendingIntent.getActivity(mContext, 0, root.intent,
1187 PendingIntent.FLAG_CANCEL_CURRENT));
1188
1189 try {
1190 int[] outId = new int[1];
1191 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1192 notification, outId);
1193 } catch (RuntimeException e) {
1194 Slog.w(ActivityManagerService.TAG,
1195 "Error showing notification for heavy-weight app", e);
1196 } catch (RemoteException e) {
1197 }
1198 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001199 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001200 }
1201 } break;
1202 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1203 INotificationManager inm = NotificationManager.getService();
1204 if (inm == null) {
1205 return;
1206 }
1207 try {
1208 inm.cancelNotification("android",
1209 R.string.heavy_weight_notification);
1210 } catch (RuntimeException e) {
1211 Slog.w(ActivityManagerService.TAG,
1212 "Error canceling notification for service", e);
1213 } catch (RemoteException e) {
1214 }
1215 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001216 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1217 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001218 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001219 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001220 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1221 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001222 }
1223 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 }
1226 };
1227
1228 public static void setSystemProcess() {
1229 try {
1230 ActivityManagerService m = mSelf;
1231
1232 ServiceManager.addService("activity", m);
1233 ServiceManager.addService("meminfo", new MemBinder(m));
1234 if (MONITOR_CPU_USAGE) {
1235 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 ServiceManager.addService("permission", new PermissionController(m));
1238
1239 ApplicationInfo info =
1240 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001241 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001242 mSystemThread.installSystemApplicationInfo(info);
1243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 synchronized (mSelf) {
1245 ProcessRecord app = mSelf.newProcessRecordLocked(
1246 mSystemThread.getApplicationThread(), info,
1247 info.processName);
1248 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001249 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 app.maxAdj = SYSTEM_ADJ;
1251 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1252 synchronized (mSelf.mPidsSelfLocked) {
1253 mSelf.mPidsSelfLocked.put(app.pid, app);
1254 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001255 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 }
1257 } catch (PackageManager.NameNotFoundException e) {
1258 throw new RuntimeException(
1259 "Unable to find android system package", e);
1260 }
1261 }
1262
1263 public void setWindowManager(WindowManagerService wm) {
1264 mWindowManager = wm;
1265 }
1266
1267 public static final Context main(int factoryTest) {
1268 AThread thr = new AThread();
1269 thr.start();
1270
1271 synchronized (thr) {
1272 while (thr.mService == null) {
1273 try {
1274 thr.wait();
1275 } catch (InterruptedException e) {
1276 }
1277 }
1278 }
1279
1280 ActivityManagerService m = thr.mService;
1281 mSelf = m;
1282 ActivityThread at = ActivityThread.systemMain();
1283 mSystemThread = at;
1284 Context context = at.getSystemContext();
1285 m.mContext = context;
1286 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001287 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288
1289 m.mBatteryStatsService.publish(context);
1290 m.mUsageStatsService.publish(context);
1291
1292 synchronized (thr) {
1293 thr.mReady = true;
1294 thr.notifyAll();
1295 }
1296
1297 m.startRunning(null, null, null, null);
1298
1299 return context;
1300 }
1301
1302 public static ActivityManagerService self() {
1303 return mSelf;
1304 }
1305
1306 static class AThread extends Thread {
1307 ActivityManagerService mService;
1308 boolean mReady = false;
1309
1310 public AThread() {
1311 super("ActivityManager");
1312 }
1313
1314 public void run() {
1315 Looper.prepare();
1316
1317 android.os.Process.setThreadPriority(
1318 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001319 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320
1321 ActivityManagerService m = new ActivityManagerService();
1322
1323 synchronized (this) {
1324 mService = m;
1325 notifyAll();
1326 }
1327
1328 synchronized (this) {
1329 while (!mReady) {
1330 try {
1331 wait();
1332 } catch (InterruptedException e) {
1333 }
1334 }
1335 }
1336
1337 Looper.loop();
1338 }
1339 }
1340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 static class MemBinder extends Binder {
1342 ActivityManagerService mActivityManagerService;
1343 MemBinder(ActivityManagerService activityManagerService) {
1344 mActivityManagerService = activityManagerService;
1345 }
1346
1347 @Override
1348 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1349 ActivityManagerService service = mActivityManagerService;
1350 ArrayList<ProcessRecord> procs;
1351 synchronized (mActivityManagerService) {
1352 if (args != null && args.length > 0
1353 && args[0].charAt(0) != '-') {
1354 procs = new ArrayList<ProcessRecord>();
1355 int pid = -1;
1356 try {
1357 pid = Integer.parseInt(args[0]);
1358 } catch (NumberFormatException e) {
1359
1360 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001361 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1362 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 if (proc.pid == pid) {
1364 procs.add(proc);
1365 } else if (proc.processName.equals(args[0])) {
1366 procs.add(proc);
1367 }
1368 }
1369 if (procs.size() <= 0) {
1370 pw.println("No process found for: " + args[0]);
1371 return;
1372 }
1373 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001374 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376 }
1377 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1378 }
1379 }
1380
1381 static class CpuBinder extends Binder {
1382 ActivityManagerService mActivityManagerService;
1383 CpuBinder(ActivityManagerService activityManagerService) {
1384 mActivityManagerService = activityManagerService;
1385 }
1386
1387 @Override
1388 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1389 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001390 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1391 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1392 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 }
1395 }
1396
1397 private ActivityManagerService() {
1398 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1399 if (v != null && Integer.getInteger(v) != 0) {
1400 mSimpleProcessManagement = true;
1401 }
1402 v = System.getenv("ANDROID_DEBUG_APP");
1403 if (v != null) {
1404 mSimpleProcessManagement = true;
1405 }
1406
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 File dataDir = Environment.getDataDirectory();
1410 File systemDir = new File(dataDir, "system");
1411 systemDir.mkdirs();
1412 mBatteryStatsService = new BatteryStatsService(new File(
1413 systemDir, "batterystats.bin").toString());
1414 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001415 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001416 mOnBattery = DEBUG_POWER ? true
1417 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001418 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001420 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001421 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422
Jack Palevichb90d28c2009-07-22 15:35:24 -07001423 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1424 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1425
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001426 mConfiguration.setToDefaults();
1427 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 mProcessStats.init();
1429
1430 // Add ourself to the Watchdog monitors.
1431 Watchdog.getInstance().addMonitor(this);
1432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 mProcessStatsThread = new Thread("ProcessStats") {
1434 public void run() {
1435 while (true) {
1436 try {
1437 try {
1438 synchronized(this) {
1439 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001440 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001442 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 // + ", write delay=" + nextWriteDelay);
1444 if (nextWriteDelay < nextCpuDelay) {
1445 nextCpuDelay = nextWriteDelay;
1446 }
1447 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001448 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 this.wait(nextCpuDelay);
1450 }
1451 }
1452 } catch (InterruptedException e) {
1453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 updateCpuStatsNow();
1455 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001456 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 }
1458 }
1459 }
1460 };
1461 mProcessStatsThread.start();
1462 }
1463
1464 @Override
1465 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1466 throws RemoteException {
1467 try {
1468 return super.onTransact(code, data, reply, flags);
1469 } catch (RuntimeException e) {
1470 // The activity manager only throws security exceptions, so let's
1471 // log all others.
1472 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001473 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 }
1475 throw e;
1476 }
1477 }
1478
1479 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001480 final long now = SystemClock.uptimeMillis();
1481 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1482 return;
1483 }
1484 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1485 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 mProcessStatsThread.notify();
1487 }
1488 }
1489 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 void updateCpuStatsNow() {
1492 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001493 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 final long now = SystemClock.uptimeMillis();
1495 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001498 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1499 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 haveNewCpuStats = true;
1501 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001502 //Slog.i(TAG, mProcessStats.printCurrentState());
1503 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 // + mProcessStats.getTotalCpuPercent() + "%");
1505
Joe Onorato8a9b2202010-02-26 18:56:32 -08001506 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 if ("true".equals(SystemProperties.get("events.cpu"))) {
1508 int user = mProcessStats.getLastUserTime();
1509 int system = mProcessStats.getLastSystemTime();
1510 int iowait = mProcessStats.getLastIoWaitTime();
1511 int irq = mProcessStats.getLastIrqTime();
1512 int softIrq = mProcessStats.getLastSoftIrqTime();
1513 int idle = mProcessStats.getLastIdleTime();
1514
1515 int total = user + system + iowait + irq + softIrq + idle;
1516 if (total == 0) total = 1;
1517
Doug Zongker2bec3d42009-12-04 12:52:44 -08001518 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 ((user+system+iowait+irq+softIrq) * 100) / total,
1520 (user * 100) / total,
1521 (system * 100) / total,
1522 (iowait * 100) / total,
1523 (irq * 100) / total,
1524 (softIrq * 100) / total);
1525 }
1526 }
1527
Amith Yamasanie43530a2009-08-21 13:11:37 -07001528 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001529 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 synchronized(mPidsSelfLocked) {
1532 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001533 if (mOnBattery) {
1534 int perc = bstats.startAddingCpuLocked();
1535 int totalUTime = 0;
1536 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001537 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001539 ProcessStats.Stats st = mProcessStats.getStats(i);
1540 if (!st.working) {
1541 continue;
1542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001544 int otherUTime = (st.rel_utime*perc)/100;
1545 int otherSTime = (st.rel_stime*perc)/100;
1546 totalUTime += otherUTime;
1547 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (pr != null) {
1549 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001550 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1551 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001552 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001553 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001554 } else {
1555 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001556 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001557 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001558 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1559 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001560 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 }
1563 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001564 bstats.finishAddingCpuLocked(perc, totalUTime,
1565 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 }
1567 }
1568 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1571 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001572 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 }
1574 }
1575 }
1576 }
1577
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001578 @Override
1579 public void batteryNeedsCpuUpdate() {
1580 updateCpuStatsNow();
1581 }
1582
1583 @Override
1584 public void batteryPowerChanged(boolean onBattery) {
1585 // When plugging in, update the CPU stats first before changing
1586 // the plug state.
1587 updateCpuStatsNow();
1588 synchronized (this) {
1589 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001590 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001591 }
1592 }
1593 }
1594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 /**
1596 * Initialize the application bind args. These are passed to each
1597 * process when the bindApplication() IPC is sent to the process. They're
1598 * lazily setup to make sure the services are running when they're asked for.
1599 */
1600 private HashMap<String, IBinder> getCommonServicesLocked() {
1601 if (mAppBindArgs == null) {
1602 mAppBindArgs = new HashMap<String, IBinder>();
1603
1604 // Setup the application init args
1605 mAppBindArgs.put("package", ServiceManager.getService("package"));
1606 mAppBindArgs.put("window", ServiceManager.getService("window"));
1607 mAppBindArgs.put(Context.ALARM_SERVICE,
1608 ServiceManager.getService(Context.ALARM_SERVICE));
1609 }
1610 return mAppBindArgs;
1611 }
1612
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001613 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 if (mFocusedActivity != r) {
1615 mFocusedActivity = r;
1616 mWindowManager.setFocusedApp(r, true);
1617 }
1618 }
1619
Dianne Hackborn906497c2010-05-10 15:57:38 -07001620 private final void updateLruProcessInternalLocked(ProcessRecord app,
1621 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001623 int lrui = mLruProcesses.indexOf(app);
1624 if (lrui >= 0) mLruProcesses.remove(lrui);
1625
1626 int i = mLruProcesses.size()-1;
1627 int skipTop = 0;
1628
Dianne Hackborn906497c2010-05-10 15:57:38 -07001629 app.lruSeq = mLruSeq;
1630
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001631 // compute the new weight for this process.
1632 if (updateActivityTime) {
1633 app.lastActivityTime = SystemClock.uptimeMillis();
1634 }
1635 if (app.activities.size() > 0) {
1636 // If this process has activities, we more strongly want to keep
1637 // it around.
1638 app.lruWeight = app.lastActivityTime;
1639 } else if (app.pubProviders.size() > 0) {
1640 // If this process contains content providers, we want to keep
1641 // it a little more strongly.
1642 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1643 // Also don't let it kick out the first few "real" hidden processes.
1644 skipTop = MIN_HIDDEN_APPS;
1645 } else {
1646 // If this process doesn't have activities, we less strongly
1647 // want to keep it around, and generally want to avoid getting
1648 // in front of any very recently used activities.
1649 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1650 // Also don't let it kick out the first few "real" hidden processes.
1651 skipTop = MIN_HIDDEN_APPS;
1652 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001653
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001654 while (i >= 0) {
1655 ProcessRecord p = mLruProcesses.get(i);
1656 // If this app shouldn't be in front of the first N background
1657 // apps, then skip over that many that are currently hidden.
1658 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1659 skipTop--;
1660 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001661 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001662 mLruProcesses.add(i+1, app);
1663 break;
1664 }
1665 i--;
1666 }
1667 if (i < 0) {
1668 mLruProcesses.add(0, app);
1669 }
1670
Dianne Hackborn906497c2010-05-10 15:57:38 -07001671 // If the app is currently using a content provider or service,
1672 // bump those processes as well.
1673 if (app.connections.size() > 0) {
1674 for (ConnectionRecord cr : app.connections) {
1675 if (cr.binding != null && cr.binding.service != null
1676 && cr.binding.service.app != null
1677 && cr.binding.service.app.lruSeq != mLruSeq) {
1678 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1679 updateActivityTime, i+1);
1680 }
1681 }
1682 }
1683 if (app.conProviders.size() > 0) {
1684 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1685 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1686 updateLruProcessInternalLocked(cpr.app, oomAdj,
1687 updateActivityTime, i+1);
1688 }
1689 }
1690 }
1691
Joe Onorato8a9b2202010-02-26 18:56:32 -08001692 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 if (oomAdj) {
1694 updateOomAdjLocked();
1695 }
1696 }
1697
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001698 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001699 boolean oomAdj, boolean updateActivityTime) {
1700 mLruSeq++;
1701 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1702 }
1703
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001704 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 String processName, int uid) {
1706 if (uid == Process.SYSTEM_UID) {
1707 // The system gets to run in any process. If there are multiple
1708 // processes with the same uid, just pick the first (this
1709 // should never happen).
1710 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1711 processName);
1712 return procs != null ? procs.valueAt(0) : null;
1713 }
1714 ProcessRecord proc = mProcessNames.get(processName, uid);
1715 return proc;
1716 }
1717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001718 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001719 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001720 try {
1721 if (pm.performDexOpt(packageName)) {
1722 mDidDexOpt = true;
1723 }
1724 } catch (RemoteException e) {
1725 }
1726 }
1727
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001728 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 int transit = mWindowManager.getPendingAppTransition();
1730 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1731 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1732 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1733 }
1734
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001735 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001737 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1739 // We don't have to do anything more if:
1740 // (1) There is an existing application record; and
1741 // (2) The caller doesn't think it is dead, OR there is no thread
1742 // object attached to it so we know it couldn't have crashed; and
1743 // (3) There is a pid assigned to it, so it is either starting or
1744 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001745 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 + " app=" + app + " knownToBeDead=" + knownToBeDead
1747 + " thread=" + (app != null ? app.thread : null)
1748 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001749 if (app != null && app.pid > 0) {
1750 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001751 // We already have the app running, or are waiting for it to
1752 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001753 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001754 return app;
1755 } else {
1756 // An application record is attached to a previous process,
1757 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001758 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001759 handleAppDiedLocked(app, true);
1760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 String hostingNameStr = hostingName != null
1764 ? hostingName.flattenToShortString() : null;
1765
1766 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1767 // If we are in the background, then check to see if this process
1768 // is bad. If so, we will just silently fail.
1769 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001770 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1771 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 return null;
1773 }
1774 } else {
1775 // When the user is explicitly starting a process, then clear its
1776 // crash count so that we won't make it bad until they see at
1777 // least one crash dialog again, and make the process good again
1778 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001779 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1780 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 mProcessCrashTimes.remove(info.processName, info.uid);
1782 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001783 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 info.processName);
1785 mBadProcesses.remove(info.processName, info.uid);
1786 if (app != null) {
1787 app.bad = false;
1788 }
1789 }
1790 }
1791
1792 if (app == null) {
1793 app = newProcessRecordLocked(null, info, processName);
1794 mProcessNames.put(processName, info.uid, app);
1795 } else {
1796 // If this is a new package in the process, add the package to the list
1797 app.addPackage(info.packageName);
1798 }
1799
1800 // If the system is not ready yet, then hold off on starting this
1801 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001802 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001803 && !isAllowedWhileBooting(info)
1804 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 if (!mProcessesOnHold.contains(app)) {
1806 mProcessesOnHold.add(app);
1807 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001808 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 return app;
1810 }
1811
1812 startProcessLocked(app, hostingType, hostingNameStr);
1813 return (app.pid != 0) ? app : null;
1814 }
1815
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001816 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1817 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1818 }
1819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 private final void startProcessLocked(ProcessRecord app,
1821 String hostingType, String hostingNameStr) {
1822 if (app.pid > 0 && app.pid != MY_PID) {
1823 synchronized (mPidsSelfLocked) {
1824 mPidsSelfLocked.remove(app.pid);
1825 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1826 }
1827 app.pid = 0;
1828 }
1829
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001830 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1831 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 mProcessesOnHold.remove(app);
1833
1834 updateCpuStats();
1835
1836 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1837 mProcDeaths[0] = 0;
1838
1839 try {
1840 int uid = app.info.uid;
1841 int[] gids = null;
1842 try {
1843 gids = mContext.getPackageManager().getPackageGids(
1844 app.info.packageName);
1845 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001846 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 }
1848 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1849 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1850 && mTopComponent != null
1851 && app.processName.equals(mTopComponent.getPackageName())) {
1852 uid = 0;
1853 }
1854 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1855 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1856 uid = 0;
1857 }
1858 }
1859 int debugFlags = 0;
1860 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1861 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1862 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001863 // Run the app in safe mode if its manifest requests so or the
1864 // system is booted in safe mode.
1865 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1866 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001867 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1870 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1871 }
1872 if ("1".equals(SystemProperties.get("debug.assert"))) {
1873 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1874 }
1875 int pid = Process.start("android.app.ActivityThread",
1876 mSimpleProcessManagement ? app.processName : null, uid, uid,
1877 gids, debugFlags, null);
1878 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1879 synchronized (bs) {
1880 if (bs.isOnBattery()) {
1881 app.batteryStats.incStartsLocked();
1882 }
1883 }
1884
Doug Zongker2bec3d42009-12-04 12:52:44 -08001885 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 app.processName, hostingType,
1887 hostingNameStr != null ? hostingNameStr : "");
1888
1889 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001890 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 }
1892
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001893 StringBuilder buf = mStringBuilder;
1894 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 buf.append("Start proc ");
1896 buf.append(app.processName);
1897 buf.append(" for ");
1898 buf.append(hostingType);
1899 if (hostingNameStr != null) {
1900 buf.append(" ");
1901 buf.append(hostingNameStr);
1902 }
1903 buf.append(": pid=");
1904 buf.append(pid);
1905 buf.append(" uid=");
1906 buf.append(uid);
1907 buf.append(" gids={");
1908 if (gids != null) {
1909 for (int gi=0; gi<gids.length; gi++) {
1910 if (gi != 0) buf.append(", ");
1911 buf.append(gids[gi]);
1912
1913 }
1914 }
1915 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001916 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if (pid == 0 || pid == MY_PID) {
1918 // Processes are being emulated with threads.
1919 app.pid = MY_PID;
1920 app.removed = false;
1921 mStartingProcesses.add(app);
1922 } else if (pid > 0) {
1923 app.pid = pid;
1924 app.removed = false;
1925 synchronized (mPidsSelfLocked) {
1926 this.mPidsSelfLocked.put(pid, app);
1927 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1928 msg.obj = app;
1929 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1930 }
1931 } else {
1932 app.pid = 0;
1933 RuntimeException e = new RuntimeException(
1934 "Failure starting process " + app.processName
1935 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001936 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 }
1938 } catch (RuntimeException e) {
1939 // XXX do better error recovery.
1940 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001941 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 }
1943 }
1944
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001945 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 if (resumed) {
1947 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1948 } else {
1949 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1950 }
1951 }
1952
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001953 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001954 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1955 && mTopAction == null) {
1956 // We are running in factory test mode, but unable to find
1957 // the factory test app, so just sit around displaying the
1958 // error message and don't try to start anything.
1959 return false;
1960 }
1961 Intent intent = new Intent(
1962 mTopAction,
1963 mTopData != null ? Uri.parse(mTopData) : null);
1964 intent.setComponent(mTopComponent);
1965 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1966 intent.addCategory(Intent.CATEGORY_HOME);
1967 }
1968 ActivityInfo aInfo =
1969 intent.resolveActivityInfo(mContext.getPackageManager(),
1970 STOCK_PM_FLAGS);
1971 if (aInfo != null) {
1972 intent.setComponent(new ComponentName(
1973 aInfo.applicationInfo.packageName, aInfo.name));
1974 // Don't do this if the home app is currently being
1975 // instrumented.
1976 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1977 aInfo.applicationInfo.uid);
1978 if (app == null || app.instrumentationClass == null) {
1979 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001980 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001981 null, null, 0, 0, 0, false, false);
1982 }
1983 }
1984
1985
1986 return true;
1987 }
1988
1989 /**
1990 * Starts the "new version setup screen" if appropriate.
1991 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001992 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001993 // Only do this once per boot.
1994 if (mCheckedForSetup) {
1995 return;
1996 }
1997
1998 // We will show this screen if the current one is a different
1999 // version than the last one shown, and we are not running in
2000 // low-level factory test mode.
2001 final ContentResolver resolver = mContext.getContentResolver();
2002 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2003 Settings.Secure.getInt(resolver,
2004 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2005 mCheckedForSetup = true;
2006
2007 // See if we should be showing the platform update setup UI.
2008 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2009 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2010 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2011
2012 // We don't allow third party apps to replace this.
2013 ResolveInfo ri = null;
2014 for (int i=0; ris != null && i<ris.size(); i++) {
2015 if ((ris.get(i).activityInfo.applicationInfo.flags
2016 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2017 ri = ris.get(i);
2018 break;
2019 }
2020 }
2021
2022 if (ri != null) {
2023 String vers = ri.activityInfo.metaData != null
2024 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2025 : null;
2026 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2027 vers = ri.activityInfo.applicationInfo.metaData.getString(
2028 Intent.METADATA_SETUP_VERSION);
2029 }
2030 String lastVers = Settings.Secure.getString(
2031 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2032 if (vers != null && !vers.equals(lastVers)) {
2033 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2034 intent.setComponent(new ComponentName(
2035 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002037 null, null, 0, 0, 0, false, false);
2038 }
2039 }
2040 }
2041 }
2042
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002043 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002044 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002045
2046 final int identHash = System.identityHashCode(r);
2047 updateUsageStats(r, true);
2048
2049 int i = mWatchers.beginBroadcast();
2050 while (i > 0) {
2051 i--;
2052 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2053 if (w != null) {
2054 try {
2055 w.activityResuming(identHash);
2056 } catch (RemoteException e) {
2057 }
2058 }
2059 }
2060 mWatchers.finishBroadcast();
2061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002064 final int N = mPendingActivityLaunches.size();
2065 if (N <= 0) {
2066 return;
2067 }
2068 for (int i=0; i<N; i++) {
2069 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002071 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2072 doResume && i == (N-1));
2073 }
2074 mPendingActivityLaunches.clear();
2075 }
2076
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002077 public final int startActivity(IApplicationThread caller,
2078 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2079 int grantedMode, IBinder resultTo,
2080 String resultWho, int requestCode, boolean onlyIfNeeded,
2081 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002082 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002083 grantedUriPermissions, grantedMode, resultTo, resultWho,
2084 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002085 }
2086
2087 public final WaitResult startActivityAndWait(IApplicationThread caller,
2088 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2089 int grantedMode, IBinder resultTo,
2090 String resultWho, int requestCode, boolean onlyIfNeeded,
2091 boolean debug) {
2092 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002093 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002094 grantedUriPermissions, grantedMode, resultTo, resultWho,
2095 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002096 return res;
2097 }
2098
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002099 public final int startActivityWithConfig(IApplicationThread caller,
2100 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2101 int grantedMode, IBinder resultTo,
2102 String resultWho, int requestCode, boolean onlyIfNeeded,
2103 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002104 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002105 grantedUriPermissions, grantedMode, resultTo, resultWho,
2106 requestCode, onlyIfNeeded, debug, null, config);
2107 }
2108
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002109 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002110 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002111 IBinder resultTo, String resultWho, int requestCode,
2112 int flagsMask, int flagsValues) {
2113 // Refuse possible leaked file descriptors
2114 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2115 throw new IllegalArgumentException("File descriptors passed in Intent");
2116 }
2117
2118 IIntentSender sender = intent.getTarget();
2119 if (!(sender instanceof PendingIntentRecord)) {
2120 throw new IllegalArgumentException("Bad PendingIntent object");
2121 }
2122
2123 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002124
2125 synchronized (this) {
2126 // If this is coming from the currently resumed activity, it is
2127 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002128 if (mMainStack.mResumedActivity != null
2129 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002130 Binder.getCallingUid()) {
2131 mAppSwitchesAllowedTime = 0;
2132 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002133 }
2134
2135 return pir.sendInner(0, fillInIntent, resolvedType,
2136 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2137 }
2138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 public boolean startNextMatchingActivity(IBinder callingActivity,
2140 Intent intent) {
2141 // Refuse possible leaked file descriptors
2142 if (intent != null && intent.hasFileDescriptors() == true) {
2143 throw new IllegalArgumentException("File descriptors passed in Intent");
2144 }
2145
2146 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002147 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 if (index < 0) {
2149 return false;
2150 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002151 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 if (r.app == null || r.app.thread == null) {
2153 // The caller is not running... d'oh!
2154 return false;
2155 }
2156 intent = new Intent(intent);
2157 // The caller is not allowed to change the data.
2158 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2159 // And we are resetting to find the next component...
2160 intent.setComponent(null);
2161
2162 ActivityInfo aInfo = null;
2163 try {
2164 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002165 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002167 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168
2169 // Look for the original activity in the list...
2170 final int N = resolves != null ? resolves.size() : 0;
2171 for (int i=0; i<N; i++) {
2172 ResolveInfo rInfo = resolves.get(i);
2173 if (rInfo.activityInfo.packageName.equals(r.packageName)
2174 && rInfo.activityInfo.name.equals(r.info.name)) {
2175 // We found the current one... the next matching is
2176 // after it.
2177 i++;
2178 if (i<N) {
2179 aInfo = resolves.get(i).activityInfo;
2180 }
2181 break;
2182 }
2183 }
2184 } catch (RemoteException e) {
2185 }
2186
2187 if (aInfo == null) {
2188 // Nobody who is next!
2189 return false;
2190 }
2191
2192 intent.setComponent(new ComponentName(
2193 aInfo.applicationInfo.packageName, aInfo.name));
2194 intent.setFlags(intent.getFlags()&~(
2195 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2196 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2197 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2198 Intent.FLAG_ACTIVITY_NEW_TASK));
2199
2200 // Okay now we need to start the new activity, replacing the
2201 // currently running activity. This is a little tricky because
2202 // we want to start the new one as if the current one is finished,
2203 // but not finish the current one first so that there is no flicker.
2204 // And thus...
2205 final boolean wasFinishing = r.finishing;
2206 r.finishing = true;
2207
2208 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002209 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 final String resultWho = r.resultWho;
2211 final int requestCode = r.requestCode;
2212 r.resultTo = null;
2213 if (resultTo != null) {
2214 resultTo.removeResultsLocked(r, resultWho, requestCode);
2215 }
2216
2217 final long origId = Binder.clearCallingIdentity();
2218 // XXX we are not dealing with propagating grantedUriPermissions...
2219 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002220 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002222 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 Binder.restoreCallingIdentity(origId);
2224
2225 r.finishing = wasFinishing;
2226 if (res != START_SUCCESS) {
2227 return false;
2228 }
2229 return true;
2230 }
2231 }
2232
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002233 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 Intent intent, String resolvedType, IBinder resultTo,
2235 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002236
2237 // This is so super not safe, that only the system (or okay root)
2238 // can do it.
2239 final int callingUid = Binder.getCallingUid();
2240 if (callingUid != 0 && callingUid != Process.myUid()) {
2241 throw new SecurityException(
2242 "startActivityInPackage only available to the system");
2243 }
2244
The Android Open Source Project4df24232009-03-05 14:34:35 -08002245 final boolean componentSpecified = intent.getComponent() != null;
2246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 // Don't modify the client's object!
2248 intent = new Intent(intent);
2249
2250 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 ActivityInfo aInfo;
2252 try {
2253 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002254 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002256 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 aInfo = rInfo != null ? rInfo.activityInfo : null;
2258 } catch (RemoteException e) {
2259 aInfo = null;
2260 }
2261
2262 if (aInfo != null) {
2263 // Store the found target back into the intent, because now that
2264 // we have it we never want to do this again. For example, if the
2265 // user navigates back to this point in the history, we should
2266 // always restart the exact same activity.
2267 intent.setComponent(new ComponentName(
2268 aInfo.applicationInfo.packageName, aInfo.name));
2269 }
2270
2271 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002272 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002274 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 }
2276 }
2277
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002278 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 // Remove any existing entries that are the same kind of task.
2280 int N = mRecentTasks.size();
2281 for (int i=0; i<N; i++) {
2282 TaskRecord tr = mRecentTasks.get(i);
2283 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2284 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2285 mRecentTasks.remove(i);
2286 i--;
2287 N--;
2288 if (task.intent == null) {
2289 // If the new recent task we are adding is not fully
2290 // specified, then replace it with the existing recent task.
2291 task = tr;
2292 }
2293 }
2294 }
2295 if (N >= MAX_RECENT_TASKS) {
2296 mRecentTasks.remove(N-1);
2297 }
2298 mRecentTasks.add(0, task);
2299 }
2300
2301 public void setRequestedOrientation(IBinder token,
2302 int requestedOrientation) {
2303 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002304 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 if (index < 0) {
2306 return;
2307 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002308 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 final long origId = Binder.clearCallingIdentity();
2310 mWindowManager.setAppOrientation(r, requestedOrientation);
2311 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002312 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 r.mayFreezeScreenLocked(r.app) ? r : null);
2314 if (config != null) {
2315 r.frozenBeforeDestroy = true;
2316 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002317 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 }
2319 }
2320 Binder.restoreCallingIdentity(origId);
2321 }
2322 }
2323
2324 public int getRequestedOrientation(IBinder token) {
2325 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002326 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 if (index < 0) {
2328 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2329 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002330 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 return mWindowManager.getAppOrientation(r);
2332 }
2333 }
2334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 /**
2336 * This is the internal entry point for handling Activity.finish().
2337 *
2338 * @param token The Binder token referencing the Activity we want to finish.
2339 * @param resultCode Result code, if any, from this Activity.
2340 * @param resultData Result data (Intent), if any, from this Activity.
2341 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002342 * @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 -08002343 */
2344 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2345 // Refuse possible leaked file descriptors
2346 if (resultData != null && resultData.hasFileDescriptors() == true) {
2347 throw new IllegalArgumentException("File descriptors passed in Intent");
2348 }
2349
2350 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002351 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 if (next != null) {
2355 // ask watcher if this is allowed
2356 boolean resumeOK = true;
2357 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002358 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002360 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 }
2362
2363 if (!resumeOK) {
2364 return false;
2365 }
2366 }
2367 }
2368 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002369 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 resultData, "app-request");
2371 Binder.restoreCallingIdentity(origId);
2372 return res;
2373 }
2374 }
2375
Dianne Hackborn860755f2010-06-03 18:47:52 -07002376 public final void finishHeavyWeightApp() {
2377 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2378 != PackageManager.PERMISSION_GRANTED) {
2379 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2380 + Binder.getCallingPid()
2381 + ", uid=" + Binder.getCallingUid()
2382 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2383 Slog.w(TAG, msg);
2384 throw new SecurityException(msg);
2385 }
2386
2387 synchronized(this) {
2388 if (mHeavyWeightProcess == null) {
2389 return;
2390 }
2391
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002392 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002393 mHeavyWeightProcess.activities);
2394 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002395 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002396 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002397 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002398 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002399 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002400 null, "finish-heavy");
2401 }
2402 }
2403 }
2404
2405 mHeavyWeightProcess = null;
2406 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2407 }
2408 }
2409
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002410 public void crashApplication(int uid, int initialPid, String packageName,
2411 String message) {
2412 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2413 != PackageManager.PERMISSION_GRANTED) {
2414 String msg = "Permission Denial: crashApplication() from pid="
2415 + Binder.getCallingPid()
2416 + ", uid=" + Binder.getCallingUid()
2417 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2418 Slog.w(TAG, msg);
2419 throw new SecurityException(msg);
2420 }
2421
2422 synchronized(this) {
2423 ProcessRecord proc = null;
2424
2425 // Figure out which process to kill. We don't trust that initialPid
2426 // still has any relation to current pids, so must scan through the
2427 // list.
2428 synchronized (mPidsSelfLocked) {
2429 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2430 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2431 if (p.info.uid != uid) {
2432 continue;
2433 }
2434 if (p.pid == initialPid) {
2435 proc = p;
2436 break;
2437 }
2438 for (String str : p.pkgList) {
2439 if (str.equals(packageName)) {
2440 proc = p;
2441 }
2442 }
2443 }
2444 }
2445
2446 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002447 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002448 + " initialPid=" + initialPid
2449 + " packageName=" + packageName);
2450 return;
2451 }
2452
2453 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002454 if (proc.pid == Process.myPid()) {
2455 Log.w(TAG, "crashApplication: trying to crash self!");
2456 return;
2457 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002458 long ident = Binder.clearCallingIdentity();
2459 try {
2460 proc.thread.scheduleCrash(message);
2461 } catch (RemoteException e) {
2462 }
2463 Binder.restoreCallingIdentity(ident);
2464 }
2465 }
2466 }
2467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 public final void finishSubActivity(IBinder token, String resultWho,
2469 int requestCode) {
2470 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 if (index < 0) {
2473 return;
2474 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002475 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476
2477 final long origId = Binder.clearCallingIdentity();
2478
2479 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002480 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2481 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 if (r.resultTo == self && r.requestCode == requestCode) {
2483 if ((r.resultWho == null && resultWho == null) ||
2484 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002485 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 Activity.RESULT_CANCELED, null, "request-sub");
2487 }
2488 }
2489 }
2490
2491 Binder.restoreCallingIdentity(origId);
2492 }
2493 }
2494
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002495 public boolean willActivityBeVisible(IBinder token) {
2496 synchronized(this) {
2497 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002498 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2499 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002500 if (r == token) {
2501 return true;
2502 }
2503 if (r.fullscreen && !r.finishing) {
2504 return false;
2505 }
2506 }
2507 return true;
2508 }
2509 }
2510
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002511 public void overridePendingTransition(IBinder token, String packageName,
2512 int enterAnim, int exitAnim) {
2513 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002515 if (index < 0) {
2516 return;
2517 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002519
2520 final long origId = Binder.clearCallingIdentity();
2521
2522 if (self.state == ActivityState.RESUMED
2523 || self.state == ActivityState.PAUSING) {
2524 mWindowManager.overridePendingAppTransition(packageName,
2525 enterAnim, exitAnim);
2526 }
2527
2528 Binder.restoreCallingIdentity(origId);
2529 }
2530 }
2531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 * Main function for removing an existing process from the activity manager
2534 * as a result of that process going away. Clears out all connections
2535 * to the process.
2536 */
2537 private final void handleAppDiedLocked(ProcessRecord app,
2538 boolean restarting) {
2539 cleanUpApplicationRecordLocked(app, restarting, -1);
2540 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002541 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 }
2543
2544 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002545 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2546 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2547 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002549 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2550 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 }
2552
2553 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002554 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555
2556 boolean atTop = true;
2557 boolean hasVisibleActivities = false;
2558
2559 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 TAG, "Removing app " + app + " from history with " + i + " entries");
2563 while (i > 0) {
2564 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002565 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002566 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2568 if (r.app == app) {
2569 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002570 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 TAG, "Removing this entry! frozen=" + r.haveState
2572 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002573 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574
2575 r.inHistory = false;
2576 mWindowManager.removeAppToken(r);
2577 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002578 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581
2582 } else {
2583 // We have the current state for this activity, so
2584 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002585 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 TAG, "Keeping entry, setting app to null");
2587 if (r.visible) {
2588 hasVisibleActivities = true;
2589 }
2590 r.app = null;
2591 r.nowVisible = false;
2592 if (!r.haveState) {
2593 r.icicle = null;
2594 }
2595 }
2596
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002597 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 r.state = ActivityState.STOPPED;
2599 }
2600 atTop = false;
2601 }
2602
2603 app.activities.clear();
2604
2605 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002606 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 + " running instrumentation " + app.instrumentationClass);
2608 Bundle info = new Bundle();
2609 info.putString("shortMsg", "Process crashed.");
2610 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2611 }
2612
2613 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002614 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 // If there was nothing to resume, and we are not already
2616 // restarting this process, but there is a visible activity that
2617 // is hosted by the process... then make sure all visible
2618 // activities are running, taking care of restarting this
2619 // process.
2620 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
2623 }
2624 }
2625 }
2626
2627 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2628 IBinder threadBinder = thread.asBinder();
2629
2630 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002631 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2632 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2634 return i;
2635 }
2636 }
2637 return -1;
2638 }
2639
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002640 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 IApplicationThread thread) {
2642 if (thread == null) {
2643 return null;
2644 }
2645
2646 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002647 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 }
2649
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002650 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 IApplicationThread thread) {
2652
2653 mProcDeaths[0]++;
2654
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002655 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2656 synchronized (stats) {
2657 stats.noteProcessDiedLocked(app.info.uid, pid);
2658 }
2659
Magnus Edlund7bb25812010-02-24 15:45:06 +01002660 // Clean up already done if the process has been re-started.
2661 if (app.pid == pid && app.thread != null &&
2662 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002663 if (!app.killedBackground) {
2664 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2665 + ") has died.");
2666 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002667 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002668 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 TAG, "Dying app: " + app + ", pid: " + pid
2670 + ", thread: " + thread.asBinder());
2671 boolean doLowMem = app.instrumentationClass == null;
2672 handleAppDiedLocked(app, false);
2673
2674 if (doLowMem) {
2675 // If there are no longer any background processes running,
2676 // and the app that died was not running instrumentation,
2677 // then tell everyone we are now low on memory.
2678 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002679 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2680 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2682 haveBg = true;
2683 break;
2684 }
2685 }
2686
2687 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002688 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002689 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002690 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002691 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2692 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002693 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002694 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2695 // The low memory report is overriding any current
2696 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002697 // heavy/important/visible/foreground processes first.
2698 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002699 rec.lastRequestedGc = 0;
2700 } else {
2701 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002703 rec.reportLowMemory = true;
2704 rec.lastLowMemory = now;
2705 mProcessesToGc.remove(rec);
2706 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 }
2708 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002709 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 }
2711 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002712 } else if (app.pid != pid) {
2713 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002714 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002715 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002716 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002717 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002718 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 + thread.asBinder());
2720 }
2721 }
2722
Dan Egnor42471dd2010-01-07 17:25:22 -08002723 /**
2724 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002725 * @param clearTraces causes the dump file to be erased prior to the new
2726 * traces being written, if true; when false, the new traces will be
2727 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002728 * @param firstPids of dalvik VM processes to dump stack traces for first
2729 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002730 * @return file containing stack traces, or null if no dump file is configured
2731 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002732 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2733 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002734 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2735 if (tracesPath == null || tracesPath.length() == 0) {
2736 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002738
2739 File tracesFile = new File(tracesPath);
2740 try {
2741 File tracesDir = tracesFile.getParentFile();
2742 if (!tracesDir.exists()) tracesFile.mkdirs();
2743 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2744
Christopher Tate6ee412d2010-05-28 12:01:56 -07002745 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002746 tracesFile.createNewFile();
2747 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2748 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002749 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002750 return null;
2751 }
2752
2753 // Use a FileObserver to detect when traces finish writing.
2754 // The order of traces is considered important to maintain for legibility.
2755 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2756 public synchronized void onEvent(int event, String path) { notify(); }
2757 };
2758
2759 try {
2760 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002761
2762 // First collect all of the stacks of the most important pids.
2763 try {
2764 int num = firstPids.size();
2765 for (int i = 0; i < num; i++) {
2766 synchronized (observer) {
2767 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2768 observer.wait(200); // Wait for write-close, give up after 200msec
2769 }
2770 }
2771 } catch (InterruptedException e) {
2772 Log.wtf(TAG, e);
2773 }
2774
2775 // Next measure CPU usage.
2776 if (processStats != null) {
2777 processStats.init();
2778 System.gc();
2779 processStats.update();
2780 try {
2781 synchronized (processStats) {
2782 processStats.wait(500); // measure over 1/2 second.
2783 }
2784 } catch (InterruptedException e) {
2785 }
2786 processStats.update();
2787
2788 // We'll take the stack crawls of just the top apps using CPU.
2789 final int N = processStats.countWorkingStats();
2790 int numProcs = 0;
2791 for (int i=0; i<N && numProcs<5; i++) {
2792 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2793 if (lastPids.indexOfKey(stats.pid) >= 0) {
2794 numProcs++;
2795 try {
2796 synchronized (observer) {
2797 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2798 observer.wait(200); // Wait for write-close, give up after 200msec
2799 }
2800 } catch (InterruptedException e) {
2801 Log.wtf(TAG, e);
2802 }
2803
2804 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002805 }
2806 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002807
2808 return tracesFile;
2809
Dan Egnor42471dd2010-01-07 17:25:22 -08002810 } finally {
2811 observer.stopWatching();
2812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 }
2814
Jeff Brown4d94a762010-09-23 11:33:28 -07002815 private final class AppNotResponding implements Runnable {
2816 private final ProcessRecord mApp;
2817 private final String mAnnotation;
2818
2819 public AppNotResponding(ProcessRecord app, String annotation) {
2820 mApp = app;
2821 mAnnotation = annotation;
2822 }
2823
2824 @Override
2825 public void run() {
2826 appNotResponding(mApp, null, null, mAnnotation);
2827 }
2828 }
2829
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002830 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2831 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002832 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2833 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2834
Dianne Hackborn287952c2010-09-22 22:34:31 -07002835 if (mController != null) {
2836 try {
2837 // 0 == continue, -1 = kill process immediately
2838 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2839 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2840 } catch (RemoteException e) {
2841 mController = null;
2842 }
2843 }
2844
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002845 long anrTime = SystemClock.uptimeMillis();
2846 if (MONITOR_CPU_USAGE) {
2847 updateCpuStatsNow();
2848 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002849
2850 synchronized (this) {
2851 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2852 if (mShuttingDown) {
2853 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2854 return;
2855 } else if (app.notResponding) {
2856 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2857 return;
2858 } else if (app.crashing) {
2859 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2860 return;
2861 }
2862
2863 // In case we come through here for the same app before completing
2864 // this one, mark as anring now so we will bail out.
2865 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002866
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002867 // Log the ANR to the event log.
2868 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2869 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002870
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002871 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002872 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002873
2874 int parentPid = app.pid;
2875 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002876 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002877
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002878 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002879
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002880 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2881 ProcessRecord r = mLruProcesses.get(i);
2882 if (r != null && r.thread != null) {
2883 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002884 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2885 if (r.persistent) {
2886 firstPids.add(pid);
2887 } else {
2888 lastPids.put(pid, Boolean.TRUE);
2889 }
2890 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
2893 }
2894
Dan Egnor42471dd2010-01-07 17:25:22 -08002895 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002896 StringBuilder info = mStringBuilder;
2897 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002898 info.append("ANR in ").append(app.processName);
2899 if (activity != null && activity.shortComponentName != null) {
2900 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002901 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002902 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002904 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002906 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002907 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909
Dianne Hackborn287952c2010-09-22 22:34:31 -07002910 final ProcessStats processStats = new ProcessStats(true);
2911
2912 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2913
Dan Egnor42471dd2010-01-07 17:25:22 -08002914 String cpuInfo = null;
2915 if (MONITOR_CPU_USAGE) {
2916 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002917 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002918 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002920 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002921 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 }
2923
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002924 info.append(processStats.printCurrentState(anrTime));
2925
Joe Onorato8a9b2202010-02-26 18:56:32 -08002926 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002927 if (tracesFile == null) {
2928 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2929 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2930 }
2931
2932 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2933
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002934 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002936 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2937 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002939 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2940 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 }
2942 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002943 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 }
2945 }
2946
Dan Egnor42471dd2010-01-07 17:25:22 -08002947 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2948 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2949 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002950
2951 synchronized (this) {
2952 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2953 Process.killProcess(app.pid);
2954 return;
2955 }
2956
2957 // Set the app's notResponding state, and look up the errorReportReceiver
2958 makeAppNotRespondingLocked(app,
2959 activity != null ? activity.shortComponentName : null,
2960 annotation != null ? "ANR " + annotation : "ANR",
2961 info.toString());
2962
2963 // Bring up the infamous App Not Responding dialog
2964 Message msg = Message.obtain();
2965 HashMap map = new HashMap();
2966 msg.what = SHOW_NOT_RESPONDING_MSG;
2967 msg.obj = map;
2968 map.put("app", app);
2969 if (activity != null) {
2970 map.put("activity", activity);
2971 }
2972
2973 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 }
2976
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002977 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2978 if (!mLaunchWarningShown) {
2979 mLaunchWarningShown = true;
2980 mHandler.post(new Runnable() {
2981 @Override
2982 public void run() {
2983 synchronized (ActivityManagerService.this) {
2984 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2985 d.show();
2986 mHandler.postDelayed(new Runnable() {
2987 @Override
2988 public void run() {
2989 synchronized (ActivityManagerService.this) {
2990 d.dismiss();
2991 mLaunchWarningShown = false;
2992 }
2993 }
2994 }, 4000);
2995 }
2996 }
2997 });
2998 }
2999 }
3000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 public boolean clearApplicationUserData(final String packageName,
3002 final IPackageDataObserver observer) {
3003 int uid = Binder.getCallingUid();
3004 int pid = Binder.getCallingPid();
3005 long callingId = Binder.clearCallingIdentity();
3006 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003007 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 int pkgUid = -1;
3009 synchronized(this) {
3010 try {
3011 pkgUid = pm.getPackageUid(packageName);
3012 } catch (RemoteException e) {
3013 }
3014 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003015 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 return false;
3017 }
3018 if (uid == pkgUid || checkComponentPermission(
3019 android.Manifest.permission.CLEAR_APP_USER_DATA,
3020 pid, uid, -1)
3021 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003022 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 } else {
3024 throw new SecurityException(pid+" does not have permission:"+
3025 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3026 "for process:"+packageName);
3027 }
3028 }
3029
3030 try {
3031 //clear application user data
3032 pm.clearApplicationUserData(packageName, observer);
3033 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3034 Uri.fromParts("package", packageName, null));
3035 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003036 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3037 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 } catch (RemoteException e) {
3039 }
3040 } finally {
3041 Binder.restoreCallingIdentity(callingId);
3042 }
3043 return true;
3044 }
3045
Dianne Hackborn03abb812010-01-04 18:43:19 -08003046 public void killBackgroundProcesses(final String packageName) {
3047 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3048 != PackageManager.PERMISSION_GRANTED &&
3049 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3050 != PackageManager.PERMISSION_GRANTED) {
3051 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 + Binder.getCallingPid()
3053 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003054 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003055 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 throw new SecurityException(msg);
3057 }
3058
3059 long callingId = Binder.clearCallingIdentity();
3060 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003061 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 int pkgUid = -1;
3063 synchronized(this) {
3064 try {
3065 pkgUid = pm.getPackageUid(packageName);
3066 } catch (RemoteException e) {
3067 }
3068 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003069 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 return;
3071 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003072 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003073 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003074 }
3075 } finally {
3076 Binder.restoreCallingIdentity(callingId);
3077 }
3078 }
3079
3080 public void forceStopPackage(final String packageName) {
3081 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3082 != PackageManager.PERMISSION_GRANTED) {
3083 String msg = "Permission Denial: forceStopPackage() from pid="
3084 + Binder.getCallingPid()
3085 + ", uid=" + Binder.getCallingUid()
3086 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003087 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003088 throw new SecurityException(msg);
3089 }
3090
3091 long callingId = Binder.clearCallingIdentity();
3092 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003093 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003094 int pkgUid = -1;
3095 synchronized(this) {
3096 try {
3097 pkgUid = pm.getPackageUid(packageName);
3098 } catch (RemoteException e) {
3099 }
3100 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003101 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003102 return;
3103 }
3104 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 }
3106 } finally {
3107 Binder.restoreCallingIdentity(callingId);
3108 }
3109 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003110
3111 /*
3112 * The pkg name and uid have to be specified.
3113 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3114 */
3115 public void killApplicationWithUid(String pkg, int uid) {
3116 if (pkg == null) {
3117 return;
3118 }
3119 // Make sure the uid is valid.
3120 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003121 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003122 return;
3123 }
3124 int callerUid = Binder.getCallingUid();
3125 // Only the system server can kill an application
3126 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003127 // Post an aysnc message to kill the application
3128 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3129 msg.arg1 = uid;
3130 msg.arg2 = 0;
3131 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003132 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003133 } else {
3134 throw new SecurityException(callerUid + " cannot kill pkg: " +
3135 pkg);
3136 }
3137 }
3138
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003139 public void closeSystemDialogs(String reason) {
3140 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003141 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003142 if (reason != null) {
3143 intent.putExtra("reason", reason);
3144 }
3145
3146 final int uid = Binder.getCallingUid();
3147 final long origId = Binder.clearCallingIdentity();
3148 synchronized (this) {
3149 int i = mWatchers.beginBroadcast();
3150 while (i > 0) {
3151 i--;
3152 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3153 if (w != null) {
3154 try {
3155 w.closingSystemDialogs(reason);
3156 } catch (RemoteException e) {
3157 }
3158 }
3159 }
3160 mWatchers.finishBroadcast();
3161
Dianne Hackbornffa42482009-09-23 22:20:11 -07003162 mWindowManager.closeSystemDialogs(reason);
3163
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003164 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3165 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003166 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003167 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003168 Activity.RESULT_CANCELED, null, "close-sys");
3169 }
3170 }
3171
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003172 broadcastIntentLocked(null, null, intent, null,
3173 null, 0, null, null, null, false, false, -1, uid);
3174 }
3175 Binder.restoreCallingIdentity(origId);
3176 }
3177
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003178 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003179 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003180 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3181 for (int i=pids.length-1; i>=0; i--) {
3182 infos[i] = new Debug.MemoryInfo();
3183 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003184 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003185 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003186 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003187
3188 public void killApplicationProcess(String processName, int uid) {
3189 if (processName == null) {
3190 return;
3191 }
3192
3193 int callerUid = Binder.getCallingUid();
3194 // Only the system server can kill an application
3195 if (callerUid == Process.SYSTEM_UID) {
3196 synchronized (this) {
3197 ProcessRecord app = getProcessRecordLocked(processName, uid);
3198 if (app != null) {
3199 try {
3200 app.thread.scheduleSuicide();
3201 } catch (RemoteException e) {
3202 // If the other end already died, then our work here is done.
3203 }
3204 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003205 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003206 + processName + " / " + uid);
3207 }
3208 }
3209 } else {
3210 throw new SecurityException(callerUid + " cannot kill app process: " +
3211 processName);
3212 }
3213 }
3214
Dianne Hackborn03abb812010-01-04 18:43:19 -08003215 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003216 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3218 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003219 if (!mProcessesReady) {
3220 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 intent.putExtra(Intent.EXTRA_UID, uid);
3223 broadcastIntentLocked(null, null, intent,
3224 null, null, 0, null, null, null,
3225 false, false, MY_PID, Process.SYSTEM_UID);
3226 }
3227
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003228 private final boolean killPackageProcessesLocked(String packageName, int uid,
3229 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003230 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231
Dianne Hackborn03abb812010-01-04 18:43:19 -08003232 // Remove all processes this package may have touched: all with the
3233 // same UID (except for the system or root user), and all whose name
3234 // matches the package name.
3235 final String procNamePrefix = packageName + ":";
3236 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3237 final int NA = apps.size();
3238 for (int ia=0; ia<NA; ia++) {
3239 ProcessRecord app = apps.valueAt(ia);
3240 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003241 if (doit) {
3242 procs.add(app);
3243 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003244 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3245 || app.processName.equals(packageName)
3246 || app.processName.startsWith(procNamePrefix)) {
3247 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003248 if (!doit) {
3249 return true;
3250 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003251 app.removed = true;
3252 procs.add(app);
3253 }
3254 }
3255 }
3256 }
3257
3258 int N = procs.size();
3259 for (int i=0; i<N; i++) {
3260 removeProcessLocked(procs.get(i), callerWillRestart);
3261 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003262 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003263 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003264
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003265 private final boolean forceStopPackageLocked(String name, int uid,
3266 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 int i, N;
3268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 if (uid < 0) {
3270 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003271 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003272 } catch (RemoteException e) {
3273 }
3274 }
3275
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003276 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003277 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003278
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003279 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3280 while (badApps.hasNext()) {
3281 SparseArray<Long> ba = badApps.next();
3282 if (ba.get(uid) != null) {
3283 badApps.remove();
3284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 }
3286 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003287
3288 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3289 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003291 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3292 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003294 if (!doit) {
3295 return true;
3296 }
3297 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003298 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 if (r.app != null) {
3300 r.app.removed = true;
3301 }
3302 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003303 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 }
3305 }
3306
3307 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3308 for (ServiceRecord service : mServices.values()) {
3309 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003310 if (!doit) {
3311 return true;
3312 }
3313 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003314 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 if (service.app != null) {
3316 service.app.removed = true;
3317 }
3318 service.app = null;
3319 services.add(service);
3320 }
3321 }
3322
3323 N = services.size();
3324 for (i=0; i<N; i++) {
3325 bringDownServiceLocked(services.get(i), true);
3326 }
3327
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003328 if (doit) {
3329 if (purgeCache) {
3330 AttributeCache ac = AttributeCache.instance();
3331 if (ac != null) {
3332 ac.removePackage(name);
3333 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003334 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003335 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003336 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003337
3338 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 }
3340
3341 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3342 final String name = app.processName;
3343 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003344 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 TAG, "Force removing process " + app + " (" + name
3346 + "/" + uid + ")");
3347
3348 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003349 if (mHeavyWeightProcess == app) {
3350 mHeavyWeightProcess = null;
3351 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 boolean needRestart = false;
3354 if (app.pid > 0 && app.pid != MY_PID) {
3355 int pid = app.pid;
3356 synchronized (mPidsSelfLocked) {
3357 mPidsSelfLocked.remove(pid);
3358 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3359 }
3360 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003361 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 Process.killProcess(pid);
3363
3364 if (app.persistent) {
3365 if (!callerWillRestart) {
3366 addAppLocked(app.info);
3367 } else {
3368 needRestart = true;
3369 }
3370 }
3371 } else {
3372 mRemovedProcesses.add(app);
3373 }
3374
3375 return needRestart;
3376 }
3377
3378 private final void processStartTimedOutLocked(ProcessRecord app) {
3379 final int pid = app.pid;
3380 boolean gone = false;
3381 synchronized (mPidsSelfLocked) {
3382 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3383 if (knownApp != null && knownApp.thread == null) {
3384 mPidsSelfLocked.remove(pid);
3385 gone = true;
3386 }
3387 }
3388
3389 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003390 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003391 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003392 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003394 if (mHeavyWeightProcess == app) {
3395 mHeavyWeightProcess = null;
3396 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3397 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003398 // Take care of any launching providers waiting for this process.
3399 checkAppInLaunchingProvidersLocked(app, true);
3400 // Take care of any services that are waiting for the process.
3401 for (int i=0; i<mPendingServices.size(); i++) {
3402 ServiceRecord sr = mPendingServices.get(i);
3403 if (app.info.uid == sr.appInfo.uid
3404 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003405 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003406 mPendingServices.remove(i);
3407 i--;
3408 bringDownServiceLocked(sr, true);
3409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003411 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003412 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003413 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003414 try {
3415 IBackupManager bm = IBackupManager.Stub.asInterface(
3416 ServiceManager.getService(Context.BACKUP_SERVICE));
3417 bm.agentDisconnected(app.info.packageName);
3418 } catch (RemoteException e) {
3419 // Can't happen; the backup manager is local
3420 }
3421 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003422 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003423 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003424 mPendingBroadcast.state = BroadcastRecord.IDLE;
3425 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003426 mPendingBroadcast = null;
3427 scheduleBroadcastsLocked();
3428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003430 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 }
3432 }
3433
3434 private final boolean attachApplicationLocked(IApplicationThread thread,
3435 int pid) {
3436
3437 // Find the application record that is being attached... either via
3438 // the pid if we are running in multiple processes, or just pull the
3439 // next app record if we are emulating process with anonymous threads.
3440 ProcessRecord app;
3441 if (pid != MY_PID && pid >= 0) {
3442 synchronized (mPidsSelfLocked) {
3443 app = mPidsSelfLocked.get(pid);
3444 }
3445 } else if (mStartingProcesses.size() > 0) {
3446 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003447 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 } else {
3449 app = null;
3450 }
3451
3452 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003455 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 if (pid > 0 && pid != MY_PID) {
3457 Process.killProcess(pid);
3458 } else {
3459 try {
3460 thread.scheduleExit();
3461 } catch (Exception e) {
3462 // Ignore exceptions.
3463 }
3464 }
3465 return false;
3466 }
3467
3468 // If this application record is still attached to a previous
3469 // process, clean it up now.
3470 if (app.thread != null) {
3471 handleAppDiedLocked(app, true);
3472 }
3473
3474 // Tell the process all about itself.
3475
Joe Onorato8a9b2202010-02-26 18:56:32 -08003476 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 TAG, "Binding process pid " + pid + " to record " + app);
3478
3479 String processName = app.processName;
3480 try {
3481 thread.asBinder().linkToDeath(new AppDeathRecipient(
3482 app, pid, thread), 0);
3483 } catch (RemoteException e) {
3484 app.resetPackageList();
3485 startProcessLocked(app, "link fail", processName);
3486 return false;
3487 }
3488
Doug Zongker2bec3d42009-12-04 12:52:44 -08003489 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490
3491 app.thread = thread;
3492 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003493 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3494 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 app.forcingToForeground = null;
3496 app.foregroundServices = false;
3497 app.debugging = false;
3498
3499 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3500
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003501 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003502 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003504 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003505 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003506 }
3507
Joe Onorato8a9b2202010-02-26 18:56:32 -08003508 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 TAG, "New app record " + app
3510 + " thread=" + thread.asBinder() + " pid=" + pid);
3511 try {
3512 int testMode = IApplicationThread.DEBUG_OFF;
3513 if (mDebugApp != null && mDebugApp.equals(processName)) {
3514 testMode = mWaitForDebugger
3515 ? IApplicationThread.DEBUG_WAIT
3516 : IApplicationThread.DEBUG_ON;
3517 app.debugging = true;
3518 if (mDebugTransient) {
3519 mDebugApp = mOrigDebugApp;
3520 mWaitForDebugger = mOrigWaitForDebugger;
3521 }
3522 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003523
Christopher Tate181fafa2009-05-14 11:12:14 -07003524 // If the app is being launched for restore or full backup, set it up specially
3525 boolean isRestrictedBackupMode = false;
3526 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3527 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3528 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3529 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003530
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003531 ensurePackageDexOpt(app.instrumentationInfo != null
3532 ? app.instrumentationInfo.packageName
3533 : app.info.packageName);
3534 if (app.instrumentationClass != null) {
3535 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003536 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003537 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003538 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003539 thread.bindApplication(processName, app.instrumentationInfo != null
3540 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003541 app.instrumentationClass, app.instrumentationProfileFile,
3542 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003543 isRestrictedBackupMode || !normalMode,
3544 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003545 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003546 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 } catch (Exception e) {
3548 // todo: Yikes! What should we do? For now we will try to
3549 // start another process, but that could easily get us in
3550 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003551 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552
3553 app.resetPackageList();
3554 startProcessLocked(app, "bind fail", processName);
3555 return false;
3556 }
3557
3558 // Remove this record from the list of starting applications.
3559 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003560 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3561 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 mProcessesOnHold.remove(app);
3563
3564 boolean badApp = false;
3565 boolean didSomething = false;
3566
3567 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003568 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003569 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3571 && processName.equals(hr.processName)) {
3572 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003573 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 didSomething = true;
3575 }
3576 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003577 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 + hr.intent.getComponent().flattenToShortString(), e);
3579 badApp = true;
3580 }
3581 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003582 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 }
3584 }
3585
3586 // Find any services that should be running in this process...
3587 if (!badApp && mPendingServices.size() > 0) {
3588 ServiceRecord sr = null;
3589 try {
3590 for (int i=0; i<mPendingServices.size(); i++) {
3591 sr = mPendingServices.get(i);
3592 if (app.info.uid != sr.appInfo.uid
3593 || !processName.equals(sr.processName)) {
3594 continue;
3595 }
3596
3597 mPendingServices.remove(i);
3598 i--;
3599 realStartServiceLocked(sr, app);
3600 didSomething = true;
3601 }
3602 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003603 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 + sr.shortName, e);
3605 badApp = true;
3606 }
3607 }
3608
3609 // Check if the next broadcast receiver is in this process...
3610 BroadcastRecord br = mPendingBroadcast;
3611 if (!badApp && br != null && br.curApp == app) {
3612 try {
3613 mPendingBroadcast = null;
3614 processCurBroadcastLocked(br, app);
3615 didSomething = true;
3616 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003617 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 + br.curComponent.flattenToShortString(), e);
3619 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003620 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3622 br.resultExtras, br.resultAbort, true);
3623 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003624 // We need to reset the state if we fails to start the receiver.
3625 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 }
3627 }
3628
Christopher Tate181fafa2009-05-14 11:12:14 -07003629 // Check whether the next backup agent is in this process...
3630 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003631 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003632 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003633 try {
3634 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3635 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003636 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003637 e.printStackTrace();
3638 }
3639 }
3640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 if (badApp) {
3642 // todo: Also need to kill application to deal with all
3643 // kinds of exceptions.
3644 handleAppDiedLocked(app, false);
3645 return false;
3646 }
3647
3648 if (!didSomething) {
3649 updateOomAdjLocked();
3650 }
3651
3652 return true;
3653 }
3654
3655 public final void attachApplication(IApplicationThread thread) {
3656 synchronized (this) {
3657 int callingPid = Binder.getCallingPid();
3658 final long origId = Binder.clearCallingIdentity();
3659 attachApplicationLocked(thread, callingPid);
3660 Binder.restoreCallingIdentity(origId);
3661 }
3662 }
3663
Dianne Hackborne88846e2009-09-30 21:34:25 -07003664 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003666 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 Binder.restoreCallingIdentity(origId);
3668 }
3669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003671 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003672 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 mWindowManager.enableScreenAfterBoot();
3674 }
3675
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003676 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003677 IntentFilter pkgFilter = new IntentFilter();
3678 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3679 pkgFilter.addDataScheme("package");
3680 mContext.registerReceiver(new BroadcastReceiver() {
3681 @Override
3682 public void onReceive(Context context, Intent intent) {
3683 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3684 if (pkgs != null) {
3685 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003686 synchronized (ActivityManagerService.this) {
3687 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3688 setResultCode(Activity.RESULT_OK);
3689 return;
3690 }
3691 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003692 }
3693 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003694 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003695 }, pkgFilter);
3696
3697 synchronized (this) {
3698 // Ensure that any processes we had put on hold are now started
3699 // up.
3700 final int NP = mProcessesOnHold.size();
3701 if (NP > 0) {
3702 ArrayList<ProcessRecord> procs =
3703 new ArrayList<ProcessRecord>(mProcessesOnHold);
3704 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003705 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3706 + procs.get(ip));
3707 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003708 }
3709 }
3710
3711 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003712 // Start looking for apps that are abusing wake locks.
3713 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003714 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003715 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003716 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003717 broadcastIntentLocked(null, null,
3718 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3719 null, null, 0, null, null,
3720 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3721 false, false, MY_PID, Process.SYSTEM_UID);
3722 }
3723 }
3724 }
3725
3726 final void ensureBootCompleted() {
3727 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003728 boolean enableScreen;
3729 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003730 booting = mBooting;
3731 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003732 enableScreen = !mBooted;
3733 mBooted = true;
3734 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003735
3736 if (booting) {
3737 finishBooting();
3738 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003739
3740 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003741 enableScreenAfterBoot();
3742 }
3743 }
3744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 public final void activityPaused(IBinder token, Bundle icicle) {
3746 // Refuse possible leaked file descriptors
3747 if (icicle != null && icicle.hasFileDescriptors()) {
3748 throw new IllegalArgumentException("File descriptors passed in Bundle");
3749 }
3750
3751 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003752 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 Binder.restoreCallingIdentity(origId);
3754 }
3755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 public final void activityStopped(IBinder token, Bitmap thumbnail,
3757 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003758 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 TAG, "Activity stopped: token=" + token);
3760
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003761 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762
3763 final long origId = Binder.clearCallingIdentity();
3764
3765 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003766 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003768 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 r.thumbnail = thumbnail;
3770 r.description = description;
3771 r.stopped = true;
3772 r.state = ActivityState.STOPPED;
3773 if (!r.finishing) {
3774 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003775 r.stack.destroyActivityLocked(r, true);
3776 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 }
3778 }
3779 }
3780 }
3781
3782 if (r != null) {
3783 sendPendingThumbnail(r, null, null, null, false);
3784 }
3785
3786 trimApplications();
3787
3788 Binder.restoreCallingIdentity(origId);
3789 }
3790
3791 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003792 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003793 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 }
3795
3796 public String getCallingPackage(IBinder token) {
3797 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003798 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003799 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 }
3801 }
3802
3803 public ComponentName getCallingActivity(IBinder token) {
3804 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003805 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003806 return r != null ? r.intent.getComponent() : null;
3807 }
3808 }
3809
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003810 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003811 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003813 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (r != null) {
3815 return r.resultTo;
3816 }
3817 }
3818 return null;
3819 }
3820
3821 public ComponentName getActivityClassForToken(IBinder token) {
3822 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003825 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 return r.intent.getComponent();
3827 }
3828 return null;
3829 }
3830 }
3831
3832 public String getPackageForToken(IBinder token) {
3833 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003834 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003836 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 return r.packageName;
3838 }
3839 return null;
3840 }
3841 }
3842
3843 public IIntentSender getIntentSender(int type,
3844 String packageName, IBinder token, String resultWho,
3845 int requestCode, Intent intent, String resolvedType, int flags) {
3846 // Refuse possible leaked file descriptors
3847 if (intent != null && intent.hasFileDescriptors() == true) {
3848 throw new IllegalArgumentException("File descriptors passed in Intent");
3849 }
3850
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003851 if (type == INTENT_SENDER_BROADCAST) {
3852 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3853 throw new IllegalArgumentException(
3854 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3855 }
3856 }
3857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 synchronized(this) {
3859 int callingUid = Binder.getCallingUid();
3860 try {
3861 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3862 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003863 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 .getPackageUid(packageName);
3865 if (uid != Binder.getCallingUid()) {
3866 String msg = "Permission Denial: getIntentSender() from pid="
3867 + Binder.getCallingPid()
3868 + ", uid=" + Binder.getCallingUid()
3869 + ", (need uid=" + uid + ")"
3870 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003871 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 throw new SecurityException(msg);
3873 }
3874 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003875
3876 return getIntentSenderLocked(type, packageName, callingUid,
3877 token, resultWho, requestCode, intent, resolvedType, flags);
3878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 } catch (RemoteException e) {
3880 throw new SecurityException(e);
3881 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003882 }
3883 }
3884
3885 IIntentSender getIntentSenderLocked(int type,
3886 String packageName, int callingUid, IBinder token, String resultWho,
3887 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003888 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003889 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003890 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003891 if (index < 0) {
3892 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003894 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003895 if (activity.finishing) {
3896 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003898 }
3899
3900 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3901 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3902 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3903 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3904 |PendingIntent.FLAG_UPDATE_CURRENT);
3905
3906 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3907 type, packageName, activity, resultWho,
3908 requestCode, intent, resolvedType, flags);
3909 WeakReference<PendingIntentRecord> ref;
3910 ref = mIntentSenderRecords.get(key);
3911 PendingIntentRecord rec = ref != null ? ref.get() : null;
3912 if (rec != null) {
3913 if (!cancelCurrent) {
3914 if (updateCurrent) {
3915 rec.key.requestIntent.replaceExtras(intent);
3916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 return rec;
3918 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003919 rec.canceled = true;
3920 mIntentSenderRecords.remove(key);
3921 }
3922 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 return rec;
3924 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003925 rec = new PendingIntentRecord(this, key, callingUid);
3926 mIntentSenderRecords.put(key, rec.ref);
3927 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3928 if (activity.pendingResults == null) {
3929 activity.pendingResults
3930 = new HashSet<WeakReference<PendingIntentRecord>>();
3931 }
3932 activity.pendingResults.add(rec.ref);
3933 }
3934 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 }
3936
3937 public void cancelIntentSender(IIntentSender sender) {
3938 if (!(sender instanceof PendingIntentRecord)) {
3939 return;
3940 }
3941 synchronized(this) {
3942 PendingIntentRecord rec = (PendingIntentRecord)sender;
3943 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003944 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 .getPackageUid(rec.key.packageName);
3946 if (uid != Binder.getCallingUid()) {
3947 String msg = "Permission Denial: cancelIntentSender() from pid="
3948 + Binder.getCallingPid()
3949 + ", uid=" + Binder.getCallingUid()
3950 + " is not allowed to cancel packges "
3951 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003952 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 throw new SecurityException(msg);
3954 }
3955 } catch (RemoteException e) {
3956 throw new SecurityException(e);
3957 }
3958 cancelIntentSenderLocked(rec, true);
3959 }
3960 }
3961
3962 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3963 rec.canceled = true;
3964 mIntentSenderRecords.remove(rec.key);
3965 if (cleanActivity && rec.key.activity != null) {
3966 rec.key.activity.pendingResults.remove(rec.ref);
3967 }
3968 }
3969
3970 public String getPackageForIntentSender(IIntentSender pendingResult) {
3971 if (!(pendingResult instanceof PendingIntentRecord)) {
3972 return null;
3973 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003974 try {
3975 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3976 return res.key.packageName;
3977 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 }
3979 return null;
3980 }
3981
3982 public void setProcessLimit(int max) {
3983 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3984 "setProcessLimit()");
3985 mProcessLimit = max;
3986 }
3987
3988 public int getProcessLimit() {
3989 return mProcessLimit;
3990 }
3991
3992 void foregroundTokenDied(ForegroundToken token) {
3993 synchronized (ActivityManagerService.this) {
3994 synchronized (mPidsSelfLocked) {
3995 ForegroundToken cur
3996 = mForegroundProcesses.get(token.pid);
3997 if (cur != token) {
3998 return;
3999 }
4000 mForegroundProcesses.remove(token.pid);
4001 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4002 if (pr == null) {
4003 return;
4004 }
4005 pr.forcingToForeground = null;
4006 pr.foregroundServices = false;
4007 }
4008 updateOomAdjLocked();
4009 }
4010 }
4011
4012 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4013 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4014 "setProcessForeground()");
4015 synchronized(this) {
4016 boolean changed = false;
4017
4018 synchronized (mPidsSelfLocked) {
4019 ProcessRecord pr = mPidsSelfLocked.get(pid);
4020 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004021 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 return;
4023 }
4024 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4025 if (oldToken != null) {
4026 oldToken.token.unlinkToDeath(oldToken, 0);
4027 mForegroundProcesses.remove(pid);
4028 pr.forcingToForeground = null;
4029 changed = true;
4030 }
4031 if (isForeground && token != null) {
4032 ForegroundToken newToken = new ForegroundToken() {
4033 public void binderDied() {
4034 foregroundTokenDied(this);
4035 }
4036 };
4037 newToken.pid = pid;
4038 newToken.token = token;
4039 try {
4040 token.linkToDeath(newToken, 0);
4041 mForegroundProcesses.put(pid, newToken);
4042 pr.forcingToForeground = token;
4043 changed = true;
4044 } catch (RemoteException e) {
4045 // If the process died while doing this, we will later
4046 // do the cleanup with the process death link.
4047 }
4048 }
4049 }
4050
4051 if (changed) {
4052 updateOomAdjLocked();
4053 }
4054 }
4055 }
4056
4057 // =========================================================
4058 // PERMISSIONS
4059 // =========================================================
4060
4061 static class PermissionController extends IPermissionController.Stub {
4062 ActivityManagerService mActivityManagerService;
4063 PermissionController(ActivityManagerService activityManagerService) {
4064 mActivityManagerService = activityManagerService;
4065 }
4066
4067 public boolean checkPermission(String permission, int pid, int uid) {
4068 return mActivityManagerService.checkPermission(permission, pid,
4069 uid) == PackageManager.PERMISSION_GRANTED;
4070 }
4071 }
4072
4073 /**
4074 * This can be called with or without the global lock held.
4075 */
4076 int checkComponentPermission(String permission, int pid, int uid,
4077 int reqUid) {
4078 // We might be performing an operation on behalf of an indirect binder
4079 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4080 // client identity accordingly before proceeding.
4081 Identity tlsIdentity = sCallerIdentity.get();
4082 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004083 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004084 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4085 uid = tlsIdentity.uid;
4086 pid = tlsIdentity.pid;
4087 }
4088
4089 // Root, system server and our own process get to do everything.
4090 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4091 !Process.supportsProcesses()) {
4092 return PackageManager.PERMISSION_GRANTED;
4093 }
4094 // If the target requires a specific UID, always fail for others.
4095 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004096 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 return PackageManager.PERMISSION_DENIED;
4098 }
4099 if (permission == null) {
4100 return PackageManager.PERMISSION_GRANTED;
4101 }
4102 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004103 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 .checkUidPermission(permission, uid);
4105 } catch (RemoteException e) {
4106 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004107 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 }
4109 return PackageManager.PERMISSION_DENIED;
4110 }
4111
4112 /**
4113 * As the only public entry point for permissions checking, this method
4114 * can enforce the semantic that requesting a check on a null global
4115 * permission is automatically denied. (Internally a null permission
4116 * string is used when calling {@link #checkComponentPermission} in cases
4117 * when only uid-based security is needed.)
4118 *
4119 * This can be called with or without the global lock held.
4120 */
4121 public int checkPermission(String permission, int pid, int uid) {
4122 if (permission == null) {
4123 return PackageManager.PERMISSION_DENIED;
4124 }
4125 return checkComponentPermission(permission, pid, uid, -1);
4126 }
4127
4128 /**
4129 * Binder IPC calls go through the public entry point.
4130 * This can be called with or without the global lock held.
4131 */
4132 int checkCallingPermission(String permission) {
4133 return checkPermission(permission,
4134 Binder.getCallingPid(),
4135 Binder.getCallingUid());
4136 }
4137
4138 /**
4139 * This can be called with or without the global lock held.
4140 */
4141 void enforceCallingPermission(String permission, String func) {
4142 if (checkCallingPermission(permission)
4143 == PackageManager.PERMISSION_GRANTED) {
4144 return;
4145 }
4146
4147 String msg = "Permission Denial: " + func + " from pid="
4148 + Binder.getCallingPid()
4149 + ", uid=" + Binder.getCallingUid()
4150 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004151 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 throw new SecurityException(msg);
4153 }
4154
4155 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004156 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4157 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4158 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4159 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4160 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004162 // Is the component private from the target uid?
4163 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4164
4165 // Acceptable if the there is no read permission needed from the
4166 // target or the target is holding the read permission.
4167 if (!readPerm) {
4168 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004170 == PackageManager.PERMISSION_GRANTED)) {
4171 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 }
4173 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004174
4175 // Acceptable if the there is no write permission needed from the
4176 // target or the target is holding the read permission.
4177 if (!writePerm) {
4178 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004180 == PackageManager.PERMISSION_GRANTED)) {
4181 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004182 }
4183 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004184
4185 // Acceptable if there is a path permission matching the URI that
4186 // the target holds the permission on.
4187 PathPermission[] pps = pi.pathPermissions;
4188 if (pps != null && (!readPerm || !writePerm)) {
4189 final String path = uri.getPath();
4190 int i = pps.length;
4191 while (i > 0 && (!readPerm || !writePerm)) {
4192 i--;
4193 PathPermission pp = pps[i];
4194 if (!readPerm) {
4195 final String pprperm = pp.getReadPermission();
4196 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4197 + pprperm + " for " + pp.getPath()
4198 + ": match=" + pp.match(path)
4199 + " check=" + pm.checkUidPermission(pprperm, uid));
4200 if (pprperm != null && pp.match(path) &&
4201 (pm.checkUidPermission(pprperm, uid)
4202 == PackageManager.PERMISSION_GRANTED)) {
4203 readPerm = true;
4204 }
4205 }
4206 if (!writePerm) {
4207 final String ppwperm = pp.getWritePermission();
4208 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4209 + ppwperm + " for " + pp.getPath()
4210 + ": match=" + pp.match(path)
4211 + " check=" + pm.checkUidPermission(ppwperm, uid));
4212 if (ppwperm != null && pp.match(path) &&
4213 (pm.checkUidPermission(ppwperm, uid)
4214 == PackageManager.PERMISSION_GRANTED)) {
4215 writePerm = true;
4216 }
4217 }
4218 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 } catch (RemoteException e) {
4221 return false;
4222 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004223
4224 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
4226
4227 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4228 int modeFlags) {
4229 // Root gets to do everything.
4230 if (uid == 0 || !Process.supportsProcesses()) {
4231 return true;
4232 }
4233 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4234 if (perms == null) return false;
4235 UriPermission perm = perms.get(uri);
4236 if (perm == null) return false;
4237 return (modeFlags&perm.modeFlags) == modeFlags;
4238 }
4239
4240 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4241 // Another redirected-binder-call permissions check as in
4242 // {@link checkComponentPermission}.
4243 Identity tlsIdentity = sCallerIdentity.get();
4244 if (tlsIdentity != null) {
4245 uid = tlsIdentity.uid;
4246 pid = tlsIdentity.pid;
4247 }
4248
4249 // Our own process gets to do everything.
4250 if (pid == MY_PID) {
4251 return PackageManager.PERMISSION_GRANTED;
4252 }
4253 synchronized(this) {
4254 return checkUriPermissionLocked(uri, uid, modeFlags)
4255 ? PackageManager.PERMISSION_GRANTED
4256 : PackageManager.PERMISSION_DENIED;
4257 }
4258 }
4259
Dianne Hackborn39792d22010-08-19 18:01:52 -07004260 /**
4261 * Check if the targetPkg can be granted permission to access uri by
4262 * the callingUid using the given modeFlags. Throws a security exception
4263 * if callingUid is not allowed to do this. Returns the uid of the target
4264 * if the URI permission grant should be performed; returns -1 if it is not
4265 * needed (for example targetPkg already has permission to access the URI).
4266 */
4267 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4268 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4270 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4271 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004272 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 }
4274
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004275 if (targetPkg != null) {
4276 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4277 "Checking grant " + targetPkg + " permission to " + uri);
4278 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004279
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004280 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281
4282 // If this is not a content: uri, we can't do anything with it.
4283 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004284 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004285 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004286 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 }
4288
4289 String name = uri.getAuthority();
4290 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004291 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 if (cpr != null) {
4293 pi = cpr.info;
4294 } else {
4295 try {
4296 pi = pm.resolveContentProvider(name,
4297 PackageManager.GET_URI_PERMISSION_PATTERNS);
4298 } catch (RemoteException ex) {
4299 }
4300 }
4301 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004302 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004303 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305
4306 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004307 if (targetPkg != null) {
4308 try {
4309 targetUid = pm.getPackageUid(targetPkg);
4310 if (targetUid < 0) {
4311 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4312 "Can't grant URI permission no uid for: " + targetPkg);
4313 return -1;
4314 }
4315 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004316 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004318 } else {
4319 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 }
4321
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004322 if (targetUid >= 0) {
4323 // First... does the target actually need this permission?
4324 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4325 // No need to grant the target this permission.
4326 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4327 "Target " + targetPkg + " already has full permission to " + uri);
4328 return -1;
4329 }
4330 } else {
4331 // First... there is no target package, so can anyone access it?
4332 boolean allowed = pi.exported;
4333 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4334 if (pi.readPermission != null) {
4335 allowed = false;
4336 }
4337 }
4338 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4339 if (pi.writePermission != null) {
4340 allowed = false;
4341 }
4342 }
4343 if (allowed) {
4344 return -1;
4345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 }
4347
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004348 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 if (!pi.grantUriPermissions) {
4350 throw new SecurityException("Provider " + pi.packageName
4351 + "/" + pi.name
4352 + " does not allow granting of Uri permissions (uri "
4353 + uri + ")");
4354 }
4355 if (pi.uriPermissionPatterns != null) {
4356 final int N = pi.uriPermissionPatterns.length;
4357 boolean allowed = false;
4358 for (int i=0; i<N; i++) {
4359 if (pi.uriPermissionPatterns[i] != null
4360 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4361 allowed = true;
4362 break;
4363 }
4364 }
4365 if (!allowed) {
4366 throw new SecurityException("Provider " + pi.packageName
4367 + "/" + pi.name
4368 + " does not allow granting of permission to path of Uri "
4369 + uri);
4370 }
4371 }
4372
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004373 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004375 if (callingUid != Process.myUid()) {
4376 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4377 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4378 throw new SecurityException("Uid " + callingUid
4379 + " does not have permission to uri " + uri);
4380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 }
4382 }
4383
Dianne Hackborn39792d22010-08-19 18:01:52 -07004384 return targetUid;
4385 }
4386
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004387 public int checkGrantUriPermission(int callingUid, String targetPkg,
4388 Uri uri, int modeFlags) {
4389 synchronized(this) {
4390 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4391 }
4392 }
4393
Dianne Hackborn39792d22010-08-19 18:01:52 -07004394 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4395 Uri uri, int modeFlags, UriPermissionOwner owner) {
4396 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4397 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4398 if (modeFlags == 0) {
4399 return;
4400 }
4401
4402 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 // to the uri, and the target doesn't. Let's now give this to
4404 // the target.
4405
Joe Onorato8a9b2202010-02-26 18:56:32 -08004406 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004407 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 HashMap<Uri, UriPermission> targetUris
4410 = mGrantedUriPermissions.get(targetUid);
4411 if (targetUris == null) {
4412 targetUris = new HashMap<Uri, UriPermission>();
4413 mGrantedUriPermissions.put(targetUid, targetUris);
4414 }
4415
4416 UriPermission perm = targetUris.get(uri);
4417 if (perm == null) {
4418 perm = new UriPermission(targetUid, uri);
4419 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004423 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 perm.globalModeFlags |= modeFlags;
4425 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004426 perm.readOwners.add(owner);
4427 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004429 perm.writeOwners.add(owner);
4430 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 }
4432 }
4433
Dianne Hackborn39792d22010-08-19 18:01:52 -07004434 void grantUriPermissionLocked(int callingUid,
4435 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004436 if (targetPkg == null) {
4437 throw new NullPointerException("targetPkg");
4438 }
4439
Dianne Hackborn39792d22010-08-19 18:01:52 -07004440 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4441 if (targetUid < 0) {
4442 return;
4443 }
4444
4445 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4446 }
4447
4448 /**
4449 * Like checkGrantUriPermissionLocked, but takes an Intent.
4450 */
4451 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4452 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004453 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004454 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004455 + " from " + intent + "; flags=0x"
4456 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4457
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004458 if (targetPkg == null) {
4459 throw new NullPointerException("targetPkg");
4460 }
4461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004463 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 }
4465 Uri data = intent.getData();
4466 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004467 return -1;
4468 }
4469 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4470 intent.getFlags());
4471 }
4472
4473 /**
4474 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4475 */
4476 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4477 String targetPkg, Intent intent, UriPermissionOwner owner) {
4478 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4479 intent.getFlags(), owner);
4480 }
4481
4482 void grantUriPermissionFromIntentLocked(int callingUid,
4483 String targetPkg, Intent intent, UriPermissionOwner owner) {
4484 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4485 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 return;
4487 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488
4489 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 }
4491
4492 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4493 Uri uri, int modeFlags) {
4494 synchronized(this) {
4495 final ProcessRecord r = getRecordForAppLocked(caller);
4496 if (r == null) {
4497 throw new SecurityException("Unable to find app for caller "
4498 + caller
4499 + " when granting permission to uri " + uri);
4500 }
4501 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004502 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
4504 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004505 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
4507
4508 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4509 null);
4510 }
4511 }
4512
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004513 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4515 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4516 HashMap<Uri, UriPermission> perms
4517 = mGrantedUriPermissions.get(perm.uid);
4518 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004519 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004520 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 perms.remove(perm.uri);
4522 if (perms.size() == 0) {
4523 mGrantedUriPermissions.remove(perm.uid);
4524 }
4525 }
4526 }
4527 }
4528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004529 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4530 int modeFlags) {
4531 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4532 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4533 if (modeFlags == 0) {
4534 return;
4535 }
4536
Joe Onorato8a9b2202010-02-26 18:56:32 -08004537 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004538 "Revoking all granted permissions to " + uri);
4539
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004540 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541
4542 final String authority = uri.getAuthority();
4543 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004544 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 if (cpr != null) {
4546 pi = cpr.info;
4547 } else {
4548 try {
4549 pi = pm.resolveContentProvider(authority,
4550 PackageManager.GET_URI_PERMISSION_PATTERNS);
4551 } catch (RemoteException ex) {
4552 }
4553 }
4554 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004555 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 return;
4557 }
4558
4559 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004560 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 // Right now, if you are not the original owner of the permission,
4562 // you are not allowed to revoke it.
4563 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4564 throw new SecurityException("Uid " + callingUid
4565 + " does not have permission to uri " + uri);
4566 //}
4567 }
4568
4569 // Go through all of the permissions and remove any that match.
4570 final List<String> SEGMENTS = uri.getPathSegments();
4571 if (SEGMENTS != null) {
4572 final int NS = SEGMENTS.size();
4573 int N = mGrantedUriPermissions.size();
4574 for (int i=0; i<N; i++) {
4575 HashMap<Uri, UriPermission> perms
4576 = mGrantedUriPermissions.valueAt(i);
4577 Iterator<UriPermission> it = perms.values().iterator();
4578 toploop:
4579 while (it.hasNext()) {
4580 UriPermission perm = it.next();
4581 Uri targetUri = perm.uri;
4582 if (!authority.equals(targetUri.getAuthority())) {
4583 continue;
4584 }
4585 List<String> targetSegments = targetUri.getPathSegments();
4586 if (targetSegments == null) {
4587 continue;
4588 }
4589 if (targetSegments.size() < NS) {
4590 continue;
4591 }
4592 for (int j=0; j<NS; j++) {
4593 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4594 continue toploop;
4595 }
4596 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004597 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004598 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 perm.clearModes(modeFlags);
4600 if (perm.modeFlags == 0) {
4601 it.remove();
4602 }
4603 }
4604 if (perms.size() == 0) {
4605 mGrantedUriPermissions.remove(
4606 mGrantedUriPermissions.keyAt(i));
4607 N--;
4608 i--;
4609 }
4610 }
4611 }
4612 }
4613
4614 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4615 int modeFlags) {
4616 synchronized(this) {
4617 final ProcessRecord r = getRecordForAppLocked(caller);
4618 if (r == null) {
4619 throw new SecurityException("Unable to find app for caller "
4620 + caller
4621 + " when revoking permission to uri " + uri);
4622 }
4623 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004624 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 return;
4626 }
4627
4628 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4629 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4630 if (modeFlags == 0) {
4631 return;
4632 }
4633
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004634 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635
4636 final String authority = uri.getAuthority();
4637 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004638 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 if (cpr != null) {
4640 pi = cpr.info;
4641 } else {
4642 try {
4643 pi = pm.resolveContentProvider(authority,
4644 PackageManager.GET_URI_PERMISSION_PATTERNS);
4645 } catch (RemoteException ex) {
4646 }
4647 }
4648 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004649 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 return;
4651 }
4652
4653 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4654 }
4655 }
4656
Dianne Hackborn7e269642010-08-25 19:50:20 -07004657 @Override
4658 public IBinder newUriPermissionOwner(String name) {
4659 synchronized(this) {
4660 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4661 return owner.getExternalTokenLocked();
4662 }
4663 }
4664
4665 @Override
4666 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4667 Uri uri, int modeFlags) {
4668 synchronized(this) {
4669 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4670 if (owner == null) {
4671 throw new IllegalArgumentException("Unknown owner: " + token);
4672 }
4673 if (fromUid != Binder.getCallingUid()) {
4674 if (Binder.getCallingUid() != Process.myUid()) {
4675 // Only system code can grant URI permissions on behalf
4676 // of other users.
4677 throw new SecurityException("nice try");
4678 }
4679 }
4680 if (targetPkg == null) {
4681 throw new IllegalArgumentException("null target");
4682 }
4683 if (uri == null) {
4684 throw new IllegalArgumentException("null uri");
4685 }
4686
4687 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4688 }
4689 }
4690
4691 @Override
4692 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4693 synchronized(this) {
4694 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4695 if (owner == null) {
4696 throw new IllegalArgumentException("Unknown owner: " + token);
4697 }
4698
4699 if (uri == null) {
4700 owner.removeUriPermissionsLocked(mode);
4701 } else {
4702 owner.removeUriPermissionLocked(uri, mode);
4703 }
4704 }
4705 }
4706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4708 synchronized (this) {
4709 ProcessRecord app =
4710 who != null ? getRecordForAppLocked(who) : null;
4711 if (app == null) return;
4712
4713 Message msg = Message.obtain();
4714 msg.what = WAIT_FOR_DEBUGGER_MSG;
4715 msg.obj = app;
4716 msg.arg1 = waiting ? 1 : 0;
4717 mHandler.sendMessage(msg);
4718 }
4719 }
4720
4721 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4722 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004723 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004725 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 }
4727
4728 // =========================================================
4729 // TASK MANAGEMENT
4730 // =========================================================
4731
4732 public List getTasks(int maxNum, int flags,
4733 IThumbnailReceiver receiver) {
4734 ArrayList list = new ArrayList();
4735
4736 PendingThumbnailsRecord pending = null;
4737 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004738 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739
4740 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004741 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4743 + ", receiver=" + receiver);
4744
4745 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4746 != PackageManager.PERMISSION_GRANTED) {
4747 if (receiver != null) {
4748 // If the caller wants to wait for pending thumbnails,
4749 // it ain't gonna get them.
4750 try {
4751 receiver.finished();
4752 } catch (RemoteException ex) {
4753 }
4754 }
4755 String msg = "Permission Denial: getTasks() from pid="
4756 + Binder.getCallingPid()
4757 + ", uid=" + Binder.getCallingUid()
4758 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004759 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 throw new SecurityException(msg);
4761 }
4762
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004763 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004764 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004765 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004766 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 CharSequence topDescription = null;
4768 TaskRecord curTask = null;
4769 int numActivities = 0;
4770 int numRunning = 0;
4771 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004772 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004774 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775
4776 // Initialize state for next task if needed.
4777 if (top == null ||
4778 (top.state == ActivityState.INITIALIZING
4779 && top.task == r.task)) {
4780 top = r;
4781 topDescription = r.description;
4782 curTask = r.task;
4783 numActivities = numRunning = 0;
4784 }
4785
4786 // Add 'r' into the current task.
4787 numActivities++;
4788 if (r.app != null && r.app.thread != null) {
4789 numRunning++;
4790 }
4791 if (topDescription == null) {
4792 topDescription = r.description;
4793 }
4794
Joe Onorato8a9b2202010-02-26 18:56:32 -08004795 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 TAG, r.intent.getComponent().flattenToShortString()
4797 + ": task=" + r.task);
4798
4799 // If the next one is a different task, generate a new
4800 // TaskInfo entry for what we have.
4801 if (next == null || next.task != curTask) {
4802 ActivityManager.RunningTaskInfo ci
4803 = new ActivityManager.RunningTaskInfo();
4804 ci.id = curTask.taskId;
4805 ci.baseActivity = r.intent.getComponent();
4806 ci.topActivity = top.intent.getComponent();
4807 ci.thumbnail = top.thumbnail;
4808 ci.description = topDescription;
4809 ci.numActivities = numActivities;
4810 ci.numRunning = numRunning;
4811 //System.out.println(
4812 // "#" + maxNum + ": " + " descr=" + ci.description);
4813 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004814 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 TAG, "State=" + top.state + "Idle=" + top.idle
4816 + " app=" + top.app
4817 + " thr=" + (top.app != null ? top.app.thread : null));
4818 if (top.state == ActivityState.RESUMED
4819 || top.state == ActivityState.PAUSING) {
4820 if (top.idle && top.app != null
4821 && top.app.thread != null) {
4822 topRecord = top;
4823 topThumbnail = top.app.thread;
4824 } else {
4825 top.thumbnailNeeded = true;
4826 }
4827 }
4828 if (pending == null) {
4829 pending = new PendingThumbnailsRecord(receiver);
4830 }
4831 pending.pendingRecords.add(top);
4832 }
4833 list.add(ci);
4834 maxNum--;
4835 top = null;
4836 }
4837 }
4838
4839 if (pending != null) {
4840 mPendingThumbnails.add(pending);
4841 }
4842 }
4843
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845
4846 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004847 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004848 try {
4849 topThumbnail.requestThumbnail(topRecord);
4850 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004851 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 sendPendingThumbnail(null, topRecord, null, null, true);
4853 }
4854 }
4855
4856 if (pending == null && receiver != null) {
4857 // In this case all thumbnails were available and the client
4858 // is being asked to be told when the remaining ones come in...
4859 // which is unusually, since the top-most currently running
4860 // activity should never have a canned thumbnail! Oh well.
4861 try {
4862 receiver.finished();
4863 } catch (RemoteException ex) {
4864 }
4865 }
4866
4867 return list;
4868 }
4869
4870 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4871 int flags) {
4872 synchronized (this) {
4873 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4874 "getRecentTasks()");
4875
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004876 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 final int N = mRecentTasks.size();
4879 ArrayList<ActivityManager.RecentTaskInfo> res
4880 = new ArrayList<ActivityManager.RecentTaskInfo>(
4881 maxNum < N ? maxNum : N);
4882 for (int i=0; i<N && maxNum > 0; i++) {
4883 TaskRecord tr = mRecentTasks.get(i);
4884 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4885 || (tr.intent == null)
4886 || ((tr.intent.getFlags()
4887 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4888 ActivityManager.RecentTaskInfo rti
4889 = new ActivityManager.RecentTaskInfo();
4890 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4891 rti.baseIntent = new Intent(
4892 tr.intent != null ? tr.intent : tr.affinityIntent);
4893 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004894
4895 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4896 // Check whether this activity is currently available.
4897 try {
4898 if (rti.origActivity != null) {
4899 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4900 continue;
4901 }
4902 } else if (rti.baseIntent != null) {
4903 if (pm.queryIntentActivities(rti.baseIntent,
4904 null, 0) == null) {
4905 continue;
4906 }
4907 }
4908 } catch (RemoteException e) {
4909 // Will never happen.
4910 }
4911 }
4912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 res.add(rti);
4914 maxNum--;
4915 }
4916 }
4917 return res;
4918 }
4919 }
4920
4921 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4922 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004923 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004924 TaskRecord jt = startTask;
4925
4926 // First look backwards
4927 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004928 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 if (r.task != jt) {
4930 jt = r.task;
4931 if (affinity.equals(jt.affinity)) {
4932 return j;
4933 }
4934 }
4935 }
4936
4937 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004938 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 jt = startTask;
4940 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004941 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 if (r.task != jt) {
4943 if (affinity.equals(jt.affinity)) {
4944 return j;
4945 }
4946 jt = r.task;
4947 }
4948 }
4949
4950 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004951 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 return N-1;
4953 }
4954
4955 return -1;
4956 }
4957
4958 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004959 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 */
4961 public void moveTaskToFront(int task) {
4962 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4963 "moveTaskToFront()");
4964
4965 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004966 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4967 Binder.getCallingUid(), "Task to front")) {
4968 return;
4969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 final long origId = Binder.clearCallingIdentity();
4971 try {
4972 int N = mRecentTasks.size();
4973 for (int i=0; i<N; i++) {
4974 TaskRecord tr = mRecentTasks.get(i);
4975 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004976 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 return;
4978 }
4979 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004980 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4981 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004983 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 return;
4985 }
4986 }
4987 } finally {
4988 Binder.restoreCallingIdentity(origId);
4989 }
4990 }
4991 }
4992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 public void moveTaskToBack(int task) {
4994 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4995 "moveTaskToBack()");
4996
4997 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004998 if (mMainStack.mResumedActivity != null
4999 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005000 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5001 Binder.getCallingUid(), "Task to back")) {
5002 return;
5003 }
5004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005006 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 Binder.restoreCallingIdentity(origId);
5008 }
5009 }
5010
5011 /**
5012 * Moves an activity, and all of the other activities within the same task, to the bottom
5013 * of the history stack. The activity's order within the task is unchanged.
5014 *
5015 * @param token A reference to the activity we wish to move
5016 * @param nonRoot If false then this only works if the activity is the root
5017 * of a task; if true it will work for any activity in a task.
5018 * @return Returns true if the move completed, false if not.
5019 */
5020 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5021 synchronized(this) {
5022 final long origId = Binder.clearCallingIdentity();
5023 int taskId = getTaskForActivityLocked(token, !nonRoot);
5024 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005025 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 }
5027 Binder.restoreCallingIdentity(origId);
5028 }
5029 return false;
5030 }
5031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 public void moveTaskBackwards(int task) {
5033 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5034 "moveTaskBackwards()");
5035
5036 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005037 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5038 Binder.getCallingUid(), "Task backwards")) {
5039 return;
5040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 final long origId = Binder.clearCallingIdentity();
5042 moveTaskBackwardsLocked(task);
5043 Binder.restoreCallingIdentity(origId);
5044 }
5045 }
5046
5047 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005048 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 }
5050
5051 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5052 synchronized(this) {
5053 return getTaskForActivityLocked(token, onlyRoot);
5054 }
5055 }
5056
5057 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005058 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 TaskRecord lastTask = null;
5060 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005061 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 if (r == token) {
5063 if (!onlyRoot || lastTask != r.task) {
5064 return r.task.taskId;
5065 }
5066 return -1;
5067 }
5068 lastTask = r.task;
5069 }
5070
5071 return -1;
5072 }
5073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 public void finishOtherInstances(IBinder token, ComponentName className) {
5075 synchronized(this) {
5076 final long origId = Binder.clearCallingIdentity();
5077
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005078 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.realActivity.equals(className)
5083 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005084 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 null, "others")) {
5086 i--;
5087 N--;
5088 }
5089 }
5090 lastTask = r.task;
5091 }
5092
5093 Binder.restoreCallingIdentity(origId);
5094 }
5095 }
5096
5097 // =========================================================
5098 // THUMBNAILS
5099 // =========================================================
5100
5101 public void reportThumbnail(IBinder token,
5102 Bitmap thumbnail, CharSequence description) {
5103 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5104 final long origId = Binder.clearCallingIdentity();
5105 sendPendingThumbnail(null, token, thumbnail, description, true);
5106 Binder.restoreCallingIdentity(origId);
5107 }
5108
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005109 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 Bitmap thumbnail, CharSequence description, boolean always) {
5111 TaskRecord task = null;
5112 ArrayList receivers = null;
5113
5114 //System.out.println("Send pending thumbnail: " + r);
5115
5116 synchronized(this) {
5117 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005118 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 if (index < 0) {
5120 return;
5121 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005122 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 }
5124 if (thumbnail == null) {
5125 thumbnail = r.thumbnail;
5126 description = r.description;
5127 }
5128 if (thumbnail == null && !always) {
5129 // If there is no thumbnail, and this entry is not actually
5130 // going away, then abort for now and pick up the next
5131 // thumbnail we get.
5132 return;
5133 }
5134 task = r.task;
5135
5136 int N = mPendingThumbnails.size();
5137 int i=0;
5138 while (i<N) {
5139 PendingThumbnailsRecord pr =
5140 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5141 //System.out.println("Looking in " + pr.pendingRecords);
5142 if (pr.pendingRecords.remove(r)) {
5143 if (receivers == null) {
5144 receivers = new ArrayList();
5145 }
5146 receivers.add(pr);
5147 if (pr.pendingRecords.size() == 0) {
5148 pr.finished = true;
5149 mPendingThumbnails.remove(i);
5150 N--;
5151 continue;
5152 }
5153 }
5154 i++;
5155 }
5156 }
5157
5158 if (receivers != null) {
5159 final int N = receivers.size();
5160 for (int i=0; i<N; i++) {
5161 try {
5162 PendingThumbnailsRecord pr =
5163 (PendingThumbnailsRecord)receivers.get(i);
5164 pr.receiver.newThumbnail(
5165 task != null ? task.taskId : -1, thumbnail, description);
5166 if (pr.finished) {
5167 pr.receiver.finished();
5168 }
5169 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005170 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 }
5172 }
5173 }
5174 }
5175
5176 // =========================================================
5177 // CONTENT PROVIDERS
5178 // =========================================================
5179
5180 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5181 List providers = null;
5182 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005183 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005185 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 } catch (RemoteException ex) {
5187 }
5188 if (providers != null) {
5189 final int N = providers.size();
5190 for (int i=0; i<N; i++) {
5191 ProviderInfo cpi =
5192 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005193 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 if (cpr == null) {
5195 cpr = new ContentProviderRecord(cpi, app.info);
5196 mProvidersByClass.put(cpi.name, cpr);
5197 }
5198 app.pubProviders.put(cpi.name, cpr);
5199 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005200 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 }
5202 }
5203 return providers;
5204 }
5205
5206 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005207 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005208 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5209 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5210 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5211 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005212 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 return null;
5214 }
5215 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5216 cpi.exported ? -1 : cpi.applicationInfo.uid)
5217 == PackageManager.PERMISSION_GRANTED) {
5218 return null;
5219 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005220
5221 PathPermission[] pps = cpi.pathPermissions;
5222 if (pps != null) {
5223 int i = pps.length;
5224 while (i > 0) {
5225 i--;
5226 PathPermission pp = pps[i];
5227 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5228 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005229 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005230 return null;
5231 }
5232 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5233 cpi.exported ? -1 : cpi.applicationInfo.uid)
5234 == PackageManager.PERMISSION_GRANTED) {
5235 return null;
5236 }
5237 }
5238 }
5239
Dianne Hackbornb424b632010-08-18 15:59:05 -07005240 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5241 if (perms != null) {
5242 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5243 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5244 return null;
5245 }
5246 }
5247 }
5248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 String msg = "Permission Denial: opening provider " + cpi.name
5250 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5251 + ", uid=" + callingUid + ") requires "
5252 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005253 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 return msg;
5255 }
5256
5257 private final ContentProviderHolder getContentProviderImpl(
5258 IApplicationThread caller, String name) {
5259 ContentProviderRecord cpr;
5260 ProviderInfo cpi = null;
5261
5262 synchronized(this) {
5263 ProcessRecord r = null;
5264 if (caller != null) {
5265 r = getRecordForAppLocked(caller);
5266 if (r == null) {
5267 throw new SecurityException(
5268 "Unable to find app for caller " + caller
5269 + " (pid=" + Binder.getCallingPid()
5270 + ") when getting content provider " + name);
5271 }
5272 }
5273
5274 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005275 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 if (cpr != null) {
5277 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005278 String msg;
5279 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5280 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 }
5282
5283 if (r != null && cpr.canRunHere(r)) {
5284 // This provider has been published or is in the process
5285 // of being published... but it is also allowed to run
5286 // in the caller's process, so don't make a connection
5287 // and just let the caller instantiate its own instance.
5288 if (cpr.provider != null) {
5289 // don't give caller the provider object, it needs
5290 // to make its own.
5291 cpr = new ContentProviderRecord(cpr);
5292 }
5293 return cpr;
5294 }
5295
5296 final long origId = Binder.clearCallingIdentity();
5297
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005298 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 // return it right away.
5300 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005301 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005302 "Adding provider requested by "
5303 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005304 + cpr.info.processName);
5305 Integer cnt = r.conProviders.get(cpr);
5306 if (cnt == null) {
5307 r.conProviders.put(cpr, new Integer(1));
5308 } else {
5309 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005312 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5313 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005314 // make sure to count it as being accessed and thus
5315 // back up on the LRU list. This is good because
5316 // content providers are often expensive to start.
5317 updateLruProcessLocked(cpr.app, false, true);
5318 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005319 } else {
5320 cpr.externals++;
5321 }
5322
5323 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 updateOomAdjLocked(cpr.app);
5325 }
5326
5327 Binder.restoreCallingIdentity(origId);
5328
5329 } else {
5330 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005331 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005332 resolveContentProvider(name,
5333 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 } catch (RemoteException ex) {
5335 }
5336 if (cpi == null) {
5337 return null;
5338 }
5339
Dianne Hackbornb424b632010-08-18 15:59:05 -07005340 String msg;
5341 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5342 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 }
5344
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005345 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005346 && !cpi.processName.equals("system")) {
5347 // If this content provider does not run in the system
5348 // process, and the system is not yet ready to run other
5349 // processes, then fail fast instead of hanging.
5350 throw new IllegalArgumentException(
5351 "Attempt to launch content provider before system ready");
5352 }
5353
Dianne Hackborn860755f2010-06-03 18:47:52 -07005354 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 final boolean firstClass = cpr == null;
5356 if (firstClass) {
5357 try {
5358 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005359 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 getApplicationInfo(
5361 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005362 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005364 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 + cpi.name);
5366 return null;
5367 }
5368 cpr = new ContentProviderRecord(cpi, ai);
5369 } catch (RemoteException ex) {
5370 // pm is in same process, this will never happen.
5371 }
5372 }
5373
5374 if (r != null && cpr.canRunHere(r)) {
5375 // If this is a multiprocess provider, then just return its
5376 // info and allow the caller to instantiate it. Only do
5377 // this if the provider is the same user as the caller's
5378 // process, or can run as root (so can be in any process).
5379 return cpr;
5380 }
5381
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005382 if (DEBUG_PROVIDER) {
5383 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005385 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 }
5387
5388 // This is single process, and our app is now connecting to it.
5389 // See if we are already in the process of launching this
5390 // provider.
5391 final int N = mLaunchingProviders.size();
5392 int i;
5393 for (i=0; i<N; i++) {
5394 if (mLaunchingProviders.get(i) == cpr) {
5395 break;
5396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005397 }
5398
5399 // If the provider is not already being launched, then get it
5400 // started.
5401 if (i >= N) {
5402 final long origId = Binder.clearCallingIdentity();
5403 ProcessRecord proc = startProcessLocked(cpi.processName,
5404 cpr.appInfo, false, 0, "content provider",
5405 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005406 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005407 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005408 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 + cpi.applicationInfo.packageName + "/"
5410 + cpi.applicationInfo.uid + " for provider "
5411 + name + ": process is bad");
5412 return null;
5413 }
5414 cpr.launchingApp = proc;
5415 mLaunchingProviders.add(cpr);
5416 Binder.restoreCallingIdentity(origId);
5417 }
5418
5419 // Make sure the provider is published (the same provider class
5420 // may be published under multiple names).
5421 if (firstClass) {
5422 mProvidersByClass.put(cpi.name, cpr);
5423 }
5424 mProvidersByName.put(name, cpr);
5425
5426 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005427 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005428 "Adding provider requested by "
5429 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005430 + cpr.info.processName);
5431 Integer cnt = r.conProviders.get(cpr);
5432 if (cnt == null) {
5433 r.conProviders.put(cpr, new Integer(1));
5434 } else {
5435 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 cpr.clients.add(r);
5438 } else {
5439 cpr.externals++;
5440 }
5441 }
5442 }
5443
5444 // Wait for the provider to be published...
5445 synchronized (cpr) {
5446 while (cpr.provider == null) {
5447 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005448 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 + cpi.applicationInfo.packageName + "/"
5450 + cpi.applicationInfo.uid + " for provider "
5451 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005452 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 cpi.applicationInfo.packageName,
5454 cpi.applicationInfo.uid, name);
5455 return null;
5456 }
5457 try {
5458 cpr.wait();
5459 } catch (InterruptedException ex) {
5460 }
5461 }
5462 }
5463 return cpr;
5464 }
5465
5466 public final ContentProviderHolder getContentProvider(
5467 IApplicationThread caller, String name) {
5468 if (caller == null) {
5469 String msg = "null IApplicationThread when getting content provider "
5470 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005471 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 throw new SecurityException(msg);
5473 }
5474
5475 return getContentProviderImpl(caller, name);
5476 }
5477
5478 private ContentProviderHolder getContentProviderExternal(String name) {
5479 return getContentProviderImpl(null, name);
5480 }
5481
5482 /**
5483 * Drop a content provider from a ProcessRecord's bookkeeping
5484 * @param cpr
5485 */
5486 public void removeContentProvider(IApplicationThread caller, String name) {
5487 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005488 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005490 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005491 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005492 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 return;
5494 }
5495 final ProcessRecord r = getRecordForAppLocked(caller);
5496 if (r == null) {
5497 throw new SecurityException(
5498 "Unable to find app for caller " + caller +
5499 " when removing content provider " + name);
5500 }
5501 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005502 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005503 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005504 + r.info.processName + " from process "
5505 + localCpr.appInfo.processName);
5506 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005508 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005509 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 return;
5511 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005512 Integer cnt = r.conProviders.get(localCpr);
5513 if (cnt == null || cnt.intValue() <= 1) {
5514 localCpr.clients.remove(r);
5515 r.conProviders.remove(localCpr);
5516 } else {
5517 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 }
5520 updateOomAdjLocked();
5521 }
5522 }
5523
5524 private void removeContentProviderExternal(String name) {
5525 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005526 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 if(cpr == null) {
5528 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005529 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 return;
5531 }
5532
5533 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005534 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 localCpr.externals--;
5536 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005537 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 }
5539 updateOomAdjLocked();
5540 }
5541 }
5542
5543 public final void publishContentProviders(IApplicationThread caller,
5544 List<ContentProviderHolder> providers) {
5545 if (providers == null) {
5546 return;
5547 }
5548
5549 synchronized(this) {
5550 final ProcessRecord r = getRecordForAppLocked(caller);
5551 if (r == null) {
5552 throw new SecurityException(
5553 "Unable to find app for caller " + caller
5554 + " (pid=" + Binder.getCallingPid()
5555 + ") when publishing content providers");
5556 }
5557
5558 final long origId = Binder.clearCallingIdentity();
5559
5560 final int N = providers.size();
5561 for (int i=0; i<N; i++) {
5562 ContentProviderHolder src = providers.get(i);
5563 if (src == null || src.info == null || src.provider == null) {
5564 continue;
5565 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005566 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 if (dst != null) {
5568 mProvidersByClass.put(dst.info.name, dst);
5569 String names[] = dst.info.authority.split(";");
5570 for (int j = 0; j < names.length; j++) {
5571 mProvidersByName.put(names[j], dst);
5572 }
5573
5574 int NL = mLaunchingProviders.size();
5575 int j;
5576 for (j=0; j<NL; j++) {
5577 if (mLaunchingProviders.get(j) == dst) {
5578 mLaunchingProviders.remove(j);
5579 j--;
5580 NL--;
5581 }
5582 }
5583 synchronized (dst) {
5584 dst.provider = src.provider;
5585 dst.app = r;
5586 dst.notifyAll();
5587 }
5588 updateOomAdjLocked(r);
5589 }
5590 }
5591
5592 Binder.restoreCallingIdentity(origId);
5593 }
5594 }
5595
5596 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005597 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005598 synchronized (mSelf) {
5599 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5600 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005601 if (providers != null) {
5602 for (int i=providers.size()-1; i>=0; i--) {
5603 ProviderInfo pi = (ProviderInfo)providers.get(i);
5604 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5605 Slog.w(TAG, "Not installing system proc provider " + pi.name
5606 + ": not system .apk");
5607 providers.remove(i);
5608 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005609 }
5610 }
5611 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005612 if (providers != null) {
5613 mSystemThread.installSystemProviders(providers);
5614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 }
5616
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005617 /**
5618 * Allows app to retrieve the MIME type of a URI without having permission
5619 * to access its content provider.
5620 *
5621 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5622 *
5623 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5624 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5625 */
5626 public String getProviderMimeType(Uri uri) {
5627 final String name = uri.getAuthority();
5628 final long ident = Binder.clearCallingIdentity();
5629 ContentProviderHolder holder = null;
5630
5631 try {
5632 holder = getContentProviderExternal(name);
5633 if (holder != null) {
5634 return holder.provider.getType(uri);
5635 }
5636 } catch (RemoteException e) {
5637 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5638 return null;
5639 } finally {
5640 if (holder != null) {
5641 removeContentProviderExternal(name);
5642 }
5643 Binder.restoreCallingIdentity(ident);
5644 }
5645
5646 return null;
5647 }
5648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 // =========================================================
5650 // GLOBAL MANAGEMENT
5651 // =========================================================
5652
5653 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5654 ApplicationInfo info, String customProcess) {
5655 String proc = customProcess != null ? customProcess : info.processName;
5656 BatteryStatsImpl.Uid.Proc ps = null;
5657 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5658 synchronized (stats) {
5659 ps = stats.getProcessStatsLocked(info.uid, proc);
5660 }
5661 return new ProcessRecord(ps, thread, info, proc);
5662 }
5663
5664 final ProcessRecord addAppLocked(ApplicationInfo info) {
5665 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5666
5667 if (app == null) {
5668 app = newProcessRecordLocked(null, info, null);
5669 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005670 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 }
5672
5673 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5674 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5675 app.persistent = true;
5676 app.maxAdj = CORE_SERVER_ADJ;
5677 }
5678 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5679 mPersistentStartingProcesses.add(app);
5680 startProcessLocked(app, "added application", app.processName);
5681 }
5682
5683 return app;
5684 }
5685
5686 public void unhandledBack() {
5687 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5688 "unhandledBack()");
5689
5690 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005691 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005692 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 TAG, "Performing unhandledBack(): stack size = " + count);
5694 if (count > 1) {
5695 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005696 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5698 Binder.restoreCallingIdentity(origId);
5699 }
5700 }
5701 }
5702
5703 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5704 String name = uri.getAuthority();
5705 ContentProviderHolder cph = getContentProviderExternal(name);
5706 ParcelFileDescriptor pfd = null;
5707 if (cph != null) {
5708 // We record the binder invoker's uid in thread-local storage before
5709 // going to the content provider to open the file. Later, in the code
5710 // that handles all permissions checks, we look for this uid and use
5711 // that rather than the Activity Manager's own uid. The effect is that
5712 // we do the check against the caller's permissions even though it looks
5713 // to the content provider like the Activity Manager itself is making
5714 // the request.
5715 sCallerIdentity.set(new Identity(
5716 Binder.getCallingPid(), Binder.getCallingUid()));
5717 try {
5718 pfd = cph.provider.openFile(uri, "r");
5719 } catch (FileNotFoundException e) {
5720 // do nothing; pfd will be returned null
5721 } finally {
5722 // Ensure that whatever happens, we clean up the identity state
5723 sCallerIdentity.remove();
5724 }
5725
5726 // We've got the fd now, so we're done with the provider.
5727 removeContentProviderExternal(name);
5728 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005729 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 }
5731 return pfd;
5732 }
5733
5734 public void goingToSleep() {
5735 synchronized(this) {
5736 mSleeping = true;
5737 mWindowManager.setEventDispatching(false);
5738
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005739 if (mMainStack.mResumedActivity != null) {
5740 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005742 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005744
5745 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005746 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005747 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5748 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005749 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 }
5751 }
5752
Dianne Hackborn55280a92009-05-07 15:53:46 -07005753 public boolean shutdown(int timeout) {
5754 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5755 != PackageManager.PERMISSION_GRANTED) {
5756 throw new SecurityException("Requires permission "
5757 + android.Manifest.permission.SHUTDOWN);
5758 }
5759
5760 boolean timedout = false;
5761
5762 synchronized(this) {
5763 mShuttingDown = true;
5764 mWindowManager.setEventDispatching(false);
5765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005766 if (mMainStack.mResumedActivity != null) {
5767 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005768 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005769 while (mMainStack.mResumedActivity != null
5770 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005771 long delay = endTime - System.currentTimeMillis();
5772 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005773 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005774 timedout = true;
5775 break;
5776 }
5777 try {
5778 this.wait();
5779 } catch (InterruptedException e) {
5780 }
5781 }
5782 }
5783 }
5784
5785 mUsageStatsService.shutdown();
5786 mBatteryStatsService.shutdown();
5787
5788 return timedout;
5789 }
5790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 public void wakingUp() {
5792 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005793 if (mMainStack.mGoingToSleep.isHeld()) {
5794 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 }
5796 mWindowManager.setEventDispatching(true);
5797 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005798 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 }
5800 }
5801
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005802 public void stopAppSwitches() {
5803 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5804 != PackageManager.PERMISSION_GRANTED) {
5805 throw new SecurityException("Requires permission "
5806 + android.Manifest.permission.STOP_APP_SWITCHES);
5807 }
5808
5809 synchronized(this) {
5810 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5811 + APP_SWITCH_DELAY_TIME;
5812 mDidAppSwitch = false;
5813 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5814 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5815 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5816 }
5817 }
5818
5819 public void resumeAppSwitches() {
5820 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5821 != PackageManager.PERMISSION_GRANTED) {
5822 throw new SecurityException("Requires permission "
5823 + android.Manifest.permission.STOP_APP_SWITCHES);
5824 }
5825
5826 synchronized(this) {
5827 // Note that we don't execute any pending app switches... we will
5828 // let those wait until either the timeout, or the next start
5829 // activity request.
5830 mAppSwitchesAllowedTime = 0;
5831 }
5832 }
5833
5834 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5835 String name) {
5836 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5837 return true;
5838 }
5839
5840 final int perm = checkComponentPermission(
5841 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5842 callingUid, -1);
5843 if (perm == PackageManager.PERMISSION_GRANTED) {
5844 return true;
5845 }
5846
Joe Onorato8a9b2202010-02-26 18:56:32 -08005847 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005848 return false;
5849 }
5850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 public void setDebugApp(String packageName, boolean waitForDebugger,
5852 boolean persistent) {
5853 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5854 "setDebugApp()");
5855
5856 // Note that this is not really thread safe if there are multiple
5857 // callers into it at the same time, but that's not a situation we
5858 // care about.
5859 if (persistent) {
5860 final ContentResolver resolver = mContext.getContentResolver();
5861 Settings.System.putString(
5862 resolver, Settings.System.DEBUG_APP,
5863 packageName);
5864 Settings.System.putInt(
5865 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5866 waitForDebugger ? 1 : 0);
5867 }
5868
5869 synchronized (this) {
5870 if (!persistent) {
5871 mOrigDebugApp = mDebugApp;
5872 mOrigWaitForDebugger = mWaitForDebugger;
5873 }
5874 mDebugApp = packageName;
5875 mWaitForDebugger = waitForDebugger;
5876 mDebugTransient = !persistent;
5877 if (packageName != null) {
5878 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005879 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005880 Binder.restoreCallingIdentity(origId);
5881 }
5882 }
5883 }
5884
5885 public void setAlwaysFinish(boolean enabled) {
5886 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5887 "setAlwaysFinish()");
5888
5889 Settings.System.putInt(
5890 mContext.getContentResolver(),
5891 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5892
5893 synchronized (this) {
5894 mAlwaysFinishActivities = enabled;
5895 }
5896 }
5897
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005898 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005900 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005902 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 }
5904 }
5905
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005906 public boolean isUserAMonkey() {
5907 // For now the fact that there is a controller implies
5908 // we have a monkey.
5909 synchronized (this) {
5910 return mController != null;
5911 }
5912 }
5913
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005914 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005915 synchronized (this) {
5916 mWatchers.register(watcher);
5917 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005918 }
5919
5920 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005921 synchronized (this) {
5922 mWatchers.unregister(watcher);
5923 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005924 }
5925
Daniel Sandler69a48172010-06-23 16:29:36 -04005926 public void setImmersive(IBinder token, boolean immersive) {
5927 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005928 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005929 if (index < 0) {
5930 throw new IllegalArgumentException();
5931 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005932 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005933 r.immersive = immersive;
5934 }
5935 }
5936
5937 public boolean isImmersive(IBinder token) {
5938 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005939 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005940 if (index < 0) {
5941 throw new IllegalArgumentException();
5942 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005943 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005944 return r.immersive;
5945 }
5946 }
5947
5948 public boolean isTopActivityImmersive() {
5949 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005950 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005951 return (r != null) ? r.immersive : false;
5952 }
5953 }
5954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 public final void enterSafeMode() {
5956 synchronized(this) {
5957 // It only makes sense to do this before the system is ready
5958 // and started launching other packages.
5959 if (!mSystemReady) {
5960 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005961 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 } catch (RemoteException e) {
5963 }
5964
5965 View v = LayoutInflater.from(mContext).inflate(
5966 com.android.internal.R.layout.safe_mode, null);
5967 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07005968 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5970 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5971 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5972 lp.format = v.getBackground().getOpacity();
5973 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5974 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5975 ((WindowManager)mContext.getSystemService(
5976 Context.WINDOW_SERVICE)).addView(v, lp);
5977 }
5978 }
5979 }
5980
5981 public void noteWakeupAlarm(IIntentSender sender) {
5982 if (!(sender instanceof PendingIntentRecord)) {
5983 return;
5984 }
5985 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5986 synchronized (stats) {
5987 if (mBatteryStatsService.isOnBattery()) {
5988 mBatteryStatsService.enforceCallingPermission();
5989 PendingIntentRecord rec = (PendingIntentRecord)sender;
5990 int MY_UID = Binder.getCallingUid();
5991 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5992 BatteryStatsImpl.Uid.Pkg pkg =
5993 stats.getPackageStatsLocked(uid, rec.key.packageName);
5994 pkg.incWakeupsLocked();
5995 }
5996 }
5997 }
5998
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005999 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006001 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006003 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006004 // XXX Note: don't acquire main activity lock here, because the window
6005 // manager calls in with its locks held.
6006
6007 boolean killed = false;
6008 synchronized (mPidsSelfLocked) {
6009 int[] types = new int[pids.length];
6010 int worstType = 0;
6011 for (int i=0; i<pids.length; i++) {
6012 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6013 if (proc != null) {
6014 int type = proc.setAdj;
6015 types[i] = type;
6016 if (type > worstType) {
6017 worstType = type;
6018 }
6019 }
6020 }
6021
6022 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6023 // then constrain it so we will kill all hidden procs.
6024 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6025 worstType = HIDDEN_APP_MIN_ADJ;
6026 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006027 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006028 for (int i=0; i<pids.length; i++) {
6029 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6030 if (proc == null) {
6031 continue;
6032 }
6033 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006034 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006035 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006036 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6037 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006039 proc.killedBackground = true;
6040 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 }
6042 }
6043 }
6044 return killed;
6045 }
6046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 public final void startRunning(String pkg, String cls, String action,
6048 String data) {
6049 synchronized(this) {
6050 if (mStartRunning) {
6051 return;
6052 }
6053 mStartRunning = true;
6054 mTopComponent = pkg != null && cls != null
6055 ? new ComponentName(pkg, cls) : null;
6056 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6057 mTopData = data;
6058 if (!mSystemReady) {
6059 return;
6060 }
6061 }
6062
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006063 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 }
6065
6066 private void retrieveSettings() {
6067 final ContentResolver resolver = mContext.getContentResolver();
6068 String debugApp = Settings.System.getString(
6069 resolver, Settings.System.DEBUG_APP);
6070 boolean waitForDebugger = Settings.System.getInt(
6071 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6072 boolean alwaysFinishActivities = Settings.System.getInt(
6073 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6074
6075 Configuration configuration = new Configuration();
6076 Settings.System.getConfiguration(resolver, configuration);
6077
6078 synchronized (this) {
6079 mDebugApp = mOrigDebugApp = debugApp;
6080 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6081 mAlwaysFinishActivities = alwaysFinishActivities;
6082 // This happens before any activities are started, so we can
6083 // change mConfiguration in-place.
6084 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006085 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006086 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 }
6088 }
6089
6090 public boolean testIsSystemReady() {
6091 // no need to synchronize(this) just to read & return the value
6092 return mSystemReady;
6093 }
6094
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006095 private static File getCalledPreBootReceiversFile() {
6096 File dataDir = Environment.getDataDirectory();
6097 File systemDir = new File(dataDir, "system");
6098 File fname = new File(systemDir, "called_pre_boots.dat");
6099 return fname;
6100 }
6101
6102 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6103 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6104 File file = getCalledPreBootReceiversFile();
6105 FileInputStream fis = null;
6106 try {
6107 fis = new FileInputStream(file);
6108 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6109 int vers = dis.readInt();
6110 String codename = dis.readUTF();
6111 if (vers == android.os.Build.VERSION.SDK_INT
6112 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6113 int num = dis.readInt();
6114 while (num > 0) {
6115 num--;
6116 String pkg = dis.readUTF();
6117 String cls = dis.readUTF();
6118 lastDoneReceivers.add(new ComponentName(pkg, cls));
6119 }
6120 }
6121 } catch (FileNotFoundException e) {
6122 } catch (IOException e) {
6123 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6124 } finally {
6125 if (fis != null) {
6126 try {
6127 fis.close();
6128 } catch (IOException e) {
6129 }
6130 }
6131 }
6132 return lastDoneReceivers;
6133 }
6134
6135 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6136 File file = getCalledPreBootReceiversFile();
6137 FileOutputStream fos = null;
6138 DataOutputStream dos = null;
6139 try {
6140 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6141 fos = new FileOutputStream(file);
6142 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6143 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6144 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6145 dos.writeInt(list.size());
6146 for (int i=0; i<list.size(); i++) {
6147 dos.writeUTF(list.get(i).getPackageName());
6148 dos.writeUTF(list.get(i).getClassName());
6149 }
6150 } catch (IOException e) {
6151 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6152 file.delete();
6153 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006154 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006155 if (dos != null) {
6156 try {
6157 dos.close();
6158 } catch (IOException e) {
6159 // TODO Auto-generated catch block
6160 e.printStackTrace();
6161 }
6162 }
6163 }
6164 }
6165
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006166 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 // In the simulator, startRunning will never have been called, which
6168 // normally sets a few crucial variables. Do it here instead.
6169 if (!Process.supportsProcesses()) {
6170 mStartRunning = true;
6171 mTopAction = Intent.ACTION_MAIN;
6172 }
6173
6174 synchronized(this) {
6175 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006176 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 return;
6178 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006179
6180 // Check to see if there are any update receivers to run.
6181 if (!mDidUpdate) {
6182 if (mWaitingUpdate) {
6183 return;
6184 }
6185 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6186 List<ResolveInfo> ris = null;
6187 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006188 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006189 intent, null, 0);
6190 } catch (RemoteException e) {
6191 }
6192 if (ris != null) {
6193 for (int i=ris.size()-1; i>=0; i--) {
6194 if ((ris.get(i).activityInfo.applicationInfo.flags
6195 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6196 ris.remove(i);
6197 }
6198 }
6199 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006200
6201 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6202
6203 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006204 for (int i=0; i<ris.size(); i++) {
6205 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006206 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6207 if (lastDoneReceivers.contains(comp)) {
6208 ris.remove(i);
6209 i--;
6210 }
6211 }
6212
6213 for (int i=0; i<ris.size(); i++) {
6214 ActivityInfo ai = ris.get(i).activityInfo;
6215 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6216 doneReceivers.add(comp);
6217 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006218 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006219 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006220 finisher = new IIntentReceiver.Stub() {
6221 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006222 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006223 boolean sticky) {
6224 // The raw IIntentReceiver interface is called
6225 // with the AM lock held, so redispatch to
6226 // execute our code without the lock.
6227 mHandler.post(new Runnable() {
6228 public void run() {
6229 synchronized (ActivityManagerService.this) {
6230 mDidUpdate = true;
6231 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006232 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006233 systemReady(goingCallback);
6234 }
6235 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006236 }
6237 };
6238 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006239 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006240 broadcastIntentLocked(null, null, intent, null, finisher,
6241 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006242 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006243 mWaitingUpdate = true;
6244 }
6245 }
6246 }
6247 if (mWaitingUpdate) {
6248 return;
6249 }
6250 mDidUpdate = true;
6251 }
6252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 mSystemReady = true;
6254 if (!mStartRunning) {
6255 return;
6256 }
6257 }
6258
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006259 ArrayList<ProcessRecord> procsToKill = null;
6260 synchronized(mPidsSelfLocked) {
6261 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6262 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6263 if (!isAllowedWhileBooting(proc.info)){
6264 if (procsToKill == null) {
6265 procsToKill = new ArrayList<ProcessRecord>();
6266 }
6267 procsToKill.add(proc);
6268 }
6269 }
6270 }
6271
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006272 synchronized(this) {
6273 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006274 for (int i=procsToKill.size()-1; i>=0; i--) {
6275 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006276 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006277 removeProcessLocked(proc, true);
6278 }
6279 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006280
6281 // Now that we have cleaned up any update processes, we
6282 // are ready to start launching real processes and know that
6283 // we won't trample on them any more.
6284 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006285 }
6286
Joe Onorato8a9b2202010-02-26 18:56:32 -08006287 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006288 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 SystemClock.uptimeMillis());
6290
6291 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006292 // Make sure we have no pre-ready processes sitting around.
6293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6295 ResolveInfo ri = mContext.getPackageManager()
6296 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006297 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 CharSequence errorMsg = null;
6299 if (ri != null) {
6300 ActivityInfo ai = ri.activityInfo;
6301 ApplicationInfo app = ai.applicationInfo;
6302 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6303 mTopAction = Intent.ACTION_FACTORY_TEST;
6304 mTopData = null;
6305 mTopComponent = new ComponentName(app.packageName,
6306 ai.name);
6307 } else {
6308 errorMsg = mContext.getResources().getText(
6309 com.android.internal.R.string.factorytest_not_system);
6310 }
6311 } else {
6312 errorMsg = mContext.getResources().getText(
6313 com.android.internal.R.string.factorytest_no_action);
6314 }
6315 if (errorMsg != null) {
6316 mTopAction = null;
6317 mTopData = null;
6318 mTopComponent = null;
6319 Message msg = Message.obtain();
6320 msg.what = SHOW_FACTORY_ERROR_MSG;
6321 msg.getData().putCharSequence("msg", errorMsg);
6322 mHandler.sendMessage(msg);
6323 }
6324 }
6325 }
6326
6327 retrieveSettings();
6328
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006329 if (goingCallback != null) goingCallback.run();
6330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 synchronized (this) {
6332 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6333 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006334 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006335 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 if (apps != null) {
6337 int N = apps.size();
6338 int i;
6339 for (i=0; i<N; i++) {
6340 ApplicationInfo info
6341 = (ApplicationInfo)apps.get(i);
6342 if (info != null &&
6343 !info.packageName.equals("android")) {
6344 addAppLocked(info);
6345 }
6346 }
6347 }
6348 } catch (RemoteException ex) {
6349 // pm is in same process, this will never happen.
6350 }
6351 }
6352
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006353 // Start up initial activity.
6354 mBooting = true;
6355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006357 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 Message msg = Message.obtain();
6359 msg.what = SHOW_UID_ERROR_MSG;
6360 mHandler.sendMessage(msg);
6361 }
6362 } catch (RemoteException e) {
6363 }
6364
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006365 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 }
6367 }
6368
Dan Egnorb7f03672009-12-09 16:22:32 -08006369 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006370 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006372 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006373 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 startAppProblemLocked(app);
6375 app.stopFreezingAllLocked();
6376 return handleAppCrashLocked(app);
6377 }
6378
Dan Egnorb7f03672009-12-09 16:22:32 -08006379 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006380 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006382 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006383 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6384 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 startAppProblemLocked(app);
6386 app.stopFreezingAllLocked();
6387 }
6388
6389 /**
6390 * Generate a process error record, suitable for attachment to a ProcessRecord.
6391 *
6392 * @param app The ProcessRecord in which the error occurred.
6393 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6394 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006395 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 * @param shortMsg Short message describing the crash.
6397 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006398 * @param stackTrace Full crash stack trace, may be null.
6399 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 * @return Returns a fully-formed AppErrorStateInfo record.
6401 */
6402 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006403 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 report.condition = condition;
6407 report.processName = app.processName;
6408 report.pid = app.pid;
6409 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006410 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 report.shortMsg = shortMsg;
6412 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006413 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414
6415 return report;
6416 }
6417
Dan Egnor42471dd2010-01-07 17:25:22 -08006418 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 synchronized (this) {
6420 app.crashing = false;
6421 app.crashingReport = null;
6422 app.notResponding = false;
6423 app.notRespondingReport = null;
6424 if (app.anrDialog == fromDialog) {
6425 app.anrDialog = null;
6426 }
6427 if (app.waitDialog == fromDialog) {
6428 app.waitDialog = null;
6429 }
6430 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006431 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006432 Slog.i(ActivityManagerService.TAG, "Killing "
6433 + app.processName + " (pid=" + app.pid + "): user's request");
6434 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6435 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 Process.killProcess(app.pid);
6437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 }
6439 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006440
Dan Egnorb7f03672009-12-09 16:22:32 -08006441 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 long now = SystemClock.uptimeMillis();
6443
6444 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6445 app.info.uid);
6446 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6447 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006450 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 app.info.processName, app.info.uid);
6452 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006453 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6454 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006456 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006458 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 }
6460 }
6461 if (!app.persistent) {
6462 // We don't want to start this process again until the user
6463 // explicitly does so... but for persistent process, we really
6464 // need to keep it running. If a persistent process is actually
6465 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006466 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 app.info.processName);
6468 mBadProcesses.put(app.info.processName, app.info.uid, now);
6469 app.bad = true;
6470 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6471 app.removed = true;
6472 removeProcessLocked(app, false);
6473 return false;
6474 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006475 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006476 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006477 if (r.app == app) {
6478 // If the top running activity is from this crashing
6479 // process, then terminate it to avoid getting in a loop.
6480 Slog.w(TAG, " Force finishing activity "
6481 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006482 int index = mMainStack.indexOfTokenLocked(r);
6483 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006484 Activity.RESULT_CANCELED, null, "crashed");
6485 // Also terminate an activities below it that aren't yet
6486 // stopped, to avoid a situation where one will get
6487 // re-start our crashing activity once it gets resumed again.
6488 index--;
6489 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006490 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006491 if (r.state == ActivityState.RESUMED
6492 || r.state == ActivityState.PAUSING
6493 || r.state == ActivityState.PAUSED) {
6494 if (!r.isHomeActivity) {
6495 Slog.w(TAG, " Force finishing activity "
6496 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006497 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006498 Activity.RESULT_CANCELED, null, "crashed");
6499 }
6500 }
6501 }
6502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 }
6504
6505 // Bump up the crash count of any services currently running in the proc.
6506 if (app.services.size() != 0) {
6507 // Any services running in the application need to be placed
6508 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006509 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006511 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 sr.crashCount++;
6513 }
6514 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006515
6516 // If the crashing process is what we consider to be the "home process" and it has been
6517 // replaced by a third-party app, clear the package preferred activities from packages
6518 // with a home activity running in the process to prevent a repeatedly crashing app
6519 // from blocking the user to manually clear the list.
6520 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6521 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6522 Iterator it = mHomeProcess.activities.iterator();
6523 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006524 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006525 if (r.isHomeActivity) {
6526 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6527 try {
6528 ActivityThread.getPackageManager()
6529 .clearPackagePreferredActivities(r.packageName);
6530 } catch (RemoteException c) {
6531 // pm is in same process, this will never happen.
6532 }
6533 }
6534 }
6535 }
6536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6538 return true;
6539 }
6540
6541 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006542 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6543 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 skipCurrentReceiverLocked(app);
6545 }
6546
6547 void skipCurrentReceiverLocked(ProcessRecord app) {
6548 boolean reschedule = false;
6549 BroadcastRecord r = app.curReceiver;
6550 if (r != null) {
6551 // The current broadcast is waiting for this app's receiver
6552 // to be finished. Looks like that's not going to happen, so
6553 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006554 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6556 r.resultExtras, r.resultAbort, true);
6557 reschedule = true;
6558 }
6559 r = mPendingBroadcast;
6560 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006561 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006563 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6565 r.resultExtras, r.resultAbort, true);
6566 reschedule = true;
6567 }
6568 if (reschedule) {
6569 scheduleBroadcastsLocked();
6570 }
6571 }
6572
Dan Egnor60d87622009-12-16 16:32:58 -08006573 /**
6574 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6575 * The application process will exit immediately after this call returns.
6576 * @param app object of the crashing app, null for the system server
6577 * @param crashInfo describing the exception
6578 */
6579 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6580 ProcessRecord r = findAppProcess(app);
6581
6582 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6583 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006584 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006585 crashInfo.exceptionClassName,
6586 crashInfo.exceptionMessage,
6587 crashInfo.throwFileName,
6588 crashInfo.throwLineNumber);
6589
Dan Egnor42471dd2010-01-07 17:25:22 -08006590 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006591
6592 crashApplication(r, crashInfo);
6593 }
6594
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006595 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006596 IBinder app,
6597 int violationMask,
6598 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006599 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006600
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006601 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006602 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006603 boolean logIt = true;
6604 synchronized (mAlreadyLoggedViolatedStacks) {
6605 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6606 logIt = false;
6607 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006608 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006609 // the relative pain numbers, without logging all
6610 // the stack traces repeatedly. We'd want to do
6611 // likewise in the client code, which also does
6612 // dup suppression, before the Binder call.
6613 } else {
6614 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6615 mAlreadyLoggedViolatedStacks.clear();
6616 }
6617 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6618 }
6619 }
6620 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006621 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006622 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006623 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006624
6625 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6626 AppErrorResult result = new AppErrorResult();
6627 synchronized (this) {
6628 final long origId = Binder.clearCallingIdentity();
6629
6630 Message msg = Message.obtain();
6631 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6632 HashMap<String, Object> data = new HashMap<String, Object>();
6633 data.put("result", result);
6634 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006635 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006636 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006637 msg.obj = data;
6638 mHandler.sendMessage(msg);
6639
6640 Binder.restoreCallingIdentity(origId);
6641 }
6642 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006643 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006644 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006645 }
6646
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006647 // Depending on the policy in effect, there could be a bunch of
6648 // these in quick succession so we try to batch these together to
6649 // minimize disk writes, number of dropbox entries, and maximize
6650 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006651 private void logStrictModeViolationToDropBox(
6652 ProcessRecord process,
6653 StrictMode.ViolationInfo info) {
6654 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006655 return;
6656 }
6657 final boolean isSystemApp = process == null ||
6658 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6659 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6660 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6661 final DropBoxManager dbox = (DropBoxManager)
6662 mContext.getSystemService(Context.DROPBOX_SERVICE);
6663
6664 // Exit early if the dropbox isn't configured to accept this report type.
6665 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6666
6667 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006668 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006669 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6670 synchronized (sb) {
6671 bufferWasEmpty = sb.length() == 0;
6672 appendDropBoxProcessHeaders(process, sb);
6673 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6674 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006675 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6676 if (info.violationNumThisLoop != 0) {
6677 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6678 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006679 if (info.numAnimationsRunning != 0) {
6680 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6681 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006682 if (info.broadcastIntentAction != null) {
6683 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6684 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006685 if (info != null && info.durationMillis != -1) {
6686 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006687 }
6688 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006689 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6690 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006691 }
6692 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006693
6694 // Only buffer up to ~64k. Various logging bits truncate
6695 // things at 128k.
6696 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006697 }
6698
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006699 // Flush immediately if the buffer's grown too large, or this
6700 // is a non-system app. Non-system apps are isolated with a
6701 // different tag & policy and not batched.
6702 //
6703 // Batching is useful during internal testing with
6704 // StrictMode settings turned up high. Without batching,
6705 // thousands of separate files could be created on boot.
6706 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006707 new Thread("Error dump: " + dropboxTag) {
6708 @Override
6709 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006710 String report;
6711 synchronized (sb) {
6712 report = sb.toString();
6713 sb.delete(0, sb.length());
6714 sb.trimToSize();
6715 }
6716 if (report.length() != 0) {
6717 dbox.addText(dropboxTag, report);
6718 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006719 }
6720 }.start();
6721 return;
6722 }
6723
6724 // System app batching:
6725 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006726 // An existing dropbox-writing thread is outstanding, so
6727 // we don't need to start it up. The existing thread will
6728 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006729 return;
6730 }
6731
6732 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6733 // (After this point, we shouldn't access AMS internal data structures.)
6734 new Thread("Error dump: " + dropboxTag) {
6735 @Override
6736 public void run() {
6737 // 5 second sleep to let stacks arrive and be batched together
6738 try {
6739 Thread.sleep(5000); // 5 seconds
6740 } catch (InterruptedException e) {}
6741
6742 String errorReport;
6743 synchronized (mStrictModeBuffer) {
6744 errorReport = mStrictModeBuffer.toString();
6745 if (errorReport.length() == 0) {
6746 return;
6747 }
6748 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6749 mStrictModeBuffer.trimToSize();
6750 }
6751 dbox.addText(dropboxTag, errorReport);
6752 }
6753 }.start();
6754 }
6755
Dan Egnor60d87622009-12-16 16:32:58 -08006756 /**
6757 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6758 * @param app object of the crashing app, null for the system server
6759 * @param tag reported by the caller
6760 * @param crashInfo describing the context of the error
6761 * @return true if the process should exit immediately (WTF is fatal)
6762 */
6763 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006764 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006765 ProcessRecord r = findAppProcess(app);
6766
6767 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6768 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006769 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006770 tag, crashInfo.exceptionMessage);
6771
Dan Egnor42471dd2010-01-07 17:25:22 -08006772 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006773
Doug Zongker43866e02010-01-07 12:09:54 -08006774 if (Settings.Secure.getInt(mContext.getContentResolver(),
6775 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006776 crashApplication(r, crashInfo);
6777 return true;
6778 } else {
6779 return false;
6780 }
6781 }
6782
6783 /**
6784 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6785 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6786 */
6787 private ProcessRecord findAppProcess(IBinder app) {
6788 if (app == null) {
6789 return null;
6790 }
6791
6792 synchronized (this) {
6793 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6794 final int NA = apps.size();
6795 for (int ia=0; ia<NA; ia++) {
6796 ProcessRecord p = apps.valueAt(ia);
6797 if (p.thread != null && p.thread.asBinder() == app) {
6798 return p;
6799 }
6800 }
6801 }
6802
Joe Onorato8a9b2202010-02-26 18:56:32 -08006803 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006804 return null;
6805 }
6806 }
6807
6808 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006809 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6810 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006811 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006812 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6813 // Note: ProcessRecord 'process' is guarded by the service
6814 // instance. (notably process.pkgList, which could otherwise change
6815 // concurrently during execution of this method)
6816 synchronized (this) {
6817 if (process == null || process.pid == MY_PID) {
6818 sb.append("Process: system_server\n");
6819 } else {
6820 sb.append("Process: ").append(process.processName).append("\n");
6821 }
6822 if (process == null) {
6823 return;
6824 }
Dan Egnora455d192010-03-12 08:52:28 -08006825 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006826 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006827 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6828 for (String pkg : process.pkgList) {
6829 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006830 try {
Dan Egnora455d192010-03-12 08:52:28 -08006831 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6832 if (pi != null) {
6833 sb.append(" v").append(pi.versionCode);
6834 if (pi.versionName != null) {
6835 sb.append(" (").append(pi.versionName).append(")");
6836 }
6837 }
6838 } catch (RemoteException e) {
6839 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006840 }
Dan Egnora455d192010-03-12 08:52:28 -08006841 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006842 }
Dan Egnora455d192010-03-12 08:52:28 -08006843 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006844 }
6845
6846 private static String processClass(ProcessRecord process) {
6847 if (process == null || process.pid == MY_PID) {
6848 return "system_server";
6849 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6850 return "system_app";
6851 } else {
6852 return "data_app";
6853 }
6854 }
6855
6856 /**
6857 * Write a description of an error (crash, WTF, ANR) to the drop box.
6858 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6859 * @param process which caused the error, null means the system server
6860 * @param activity which triggered the error, null if unknown
6861 * @param parent activity related to the error, null if unknown
6862 * @param subject line related to the error, null if absent
6863 * @param report in long form describing the error, null if absent
6864 * @param logFile to include in the report, null if none
6865 * @param crashInfo giving an application stack trace, null if absent
6866 */
6867 public void addErrorToDropBox(String eventType,
6868 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6869 final String report, final File logFile,
6870 final ApplicationErrorReport.CrashInfo crashInfo) {
6871 // NOTE -- this must never acquire the ActivityManagerService lock,
6872 // otherwise the watchdog may be prevented from resetting the system.
6873
6874 final String dropboxTag = processClass(process) + "_" + eventType;
6875 final DropBoxManager dbox = (DropBoxManager)
6876 mContext.getSystemService(Context.DROPBOX_SERVICE);
6877
6878 // Exit early if the dropbox isn't configured to accept this report type.
6879 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6880
6881 final StringBuilder sb = new StringBuilder(1024);
6882 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006883 if (activity != null) {
6884 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6885 }
6886 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6887 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6888 }
6889 if (parent != null && parent != activity) {
6890 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6891 }
6892 if (subject != null) {
6893 sb.append("Subject: ").append(subject).append("\n");
6894 }
6895 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006896 if (Debug.isDebuggerConnected()) {
6897 sb.append("Debugger: Connected\n");
6898 }
Dan Egnora455d192010-03-12 08:52:28 -08006899 sb.append("\n");
6900
6901 // Do the rest in a worker thread to avoid blocking the caller on I/O
6902 // (After this point, we shouldn't access AMS internal data structures.)
6903 Thread worker = new Thread("Error dump: " + dropboxTag) {
6904 @Override
6905 public void run() {
6906 if (report != null) {
6907 sb.append(report);
6908 }
6909 if (logFile != null) {
6910 try {
6911 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6912 } catch (IOException e) {
6913 Slog.e(TAG, "Error reading " + logFile, e);
6914 }
6915 }
6916 if (crashInfo != null && crashInfo.stackTrace != null) {
6917 sb.append(crashInfo.stackTrace);
6918 }
6919
6920 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6921 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6922 if (lines > 0) {
6923 sb.append("\n");
6924
6925 // Merge several logcat streams, and take the last N lines
6926 InputStreamReader input = null;
6927 try {
6928 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6929 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6930 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6931
6932 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6933 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6934 input = new InputStreamReader(logcat.getInputStream());
6935
6936 int num;
6937 char[] buf = new char[8192];
6938 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6939 } catch (IOException e) {
6940 Slog.e(TAG, "Error running logcat", e);
6941 } finally {
6942 if (input != null) try { input.close(); } catch (IOException e) {}
6943 }
6944 }
6945
6946 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006947 }
Dan Egnora455d192010-03-12 08:52:28 -08006948 };
6949
6950 if (process == null || process.pid == MY_PID) {
6951 worker.run(); // We may be about to die -- need to run this synchronously
6952 } else {
6953 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006954 }
6955 }
6956
6957 /**
6958 * Bring up the "unexpected error" dialog box for a crashing app.
6959 * Deal with edge cases (intercepts from instrumented applications,
6960 * ActivityController, error intent receivers, that sort of thing).
6961 * @param r the application crashing
6962 * @param crashInfo describing the failure
6963 */
6964 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006965 long timeMillis = System.currentTimeMillis();
6966 String shortMsg = crashInfo.exceptionClassName;
6967 String longMsg = crashInfo.exceptionMessage;
6968 String stackTrace = crashInfo.stackTrace;
6969 if (shortMsg != null && longMsg != null) {
6970 longMsg = shortMsg + ": " + longMsg;
6971 } else if (shortMsg != null) {
6972 longMsg = shortMsg;
6973 }
6974
Dan Egnor60d87622009-12-16 16:32:58 -08006975 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006977 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006978 try {
6979 String name = r != null ? r.processName : null;
6980 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006981 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006982 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006983 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 + " at watcher's request");
6985 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006986 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006987 }
6988 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006989 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990 }
6991 }
6992
6993 final long origId = Binder.clearCallingIdentity();
6994
6995 // If this process is running instrumentation, finish it.
6996 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006997 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006999 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7000 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007001 Bundle info = new Bundle();
7002 info.putString("shortMsg", shortMsg);
7003 info.putString("longMsg", longMsg);
7004 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7005 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007006 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007007 }
7008
Dan Egnor60d87622009-12-16 16:32:58 -08007009 // If we can't identify the process or it's already exceeded its crash quota,
7010 // quit right away without showing a crash dialog.
7011 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007013 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 }
7015
7016 Message msg = Message.obtain();
7017 msg.what = SHOW_ERROR_MSG;
7018 HashMap data = new HashMap();
7019 data.put("result", result);
7020 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 msg.obj = data;
7022 mHandler.sendMessage(msg);
7023
7024 Binder.restoreCallingIdentity(origId);
7025 }
7026
7027 int res = result.get();
7028
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007029 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 synchronized (this) {
7031 if (r != null) {
7032 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7033 SystemClock.uptimeMillis());
7034 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007035 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007036 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007037 }
7038 }
7039
7040 if (appErrorIntent != null) {
7041 try {
7042 mContext.startActivity(appErrorIntent);
7043 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007044 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007048
7049 Intent createAppErrorIntentLocked(ProcessRecord r,
7050 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7051 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007052 if (report == null) {
7053 return null;
7054 }
7055 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7056 result.setComponent(r.errorReportReceiver);
7057 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7058 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7059 return result;
7060 }
7061
Dan Egnorb7f03672009-12-09 16:22:32 -08007062 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7063 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007064 if (r.errorReportReceiver == null) {
7065 return null;
7066 }
7067
7068 if (!r.crashing && !r.notResponding) {
7069 return null;
7070 }
7071
Dan Egnorb7f03672009-12-09 16:22:32 -08007072 ApplicationErrorReport report = new ApplicationErrorReport();
7073 report.packageName = r.info.packageName;
7074 report.installerPackageName = r.errorReportReceiver.getPackageName();
7075 report.processName = r.processName;
7076 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007077 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007078
Dan Egnorb7f03672009-12-09 16:22:32 -08007079 if (r.crashing) {
7080 report.type = ApplicationErrorReport.TYPE_CRASH;
7081 report.crashInfo = crashInfo;
7082 } else if (r.notResponding) {
7083 report.type = ApplicationErrorReport.TYPE_ANR;
7084 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007085
Dan Egnorb7f03672009-12-09 16:22:32 -08007086 report.anrInfo.activity = r.notRespondingReport.tag;
7087 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7088 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007089 }
7090
Dan Egnorb7f03672009-12-09 16:22:32 -08007091 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007092 }
7093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007094 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7095 // assume our apps are happy - lazy create the list
7096 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7097
7098 synchronized (this) {
7099
7100 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007101 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7102 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7104 // This one's in trouble, so we'll generate a report for it
7105 // crashes are higher priority (in case there's a crash *and* an anr)
7106 ActivityManager.ProcessErrorStateInfo report = null;
7107 if (app.crashing) {
7108 report = app.crashingReport;
7109 } else if (app.notResponding) {
7110 report = app.notRespondingReport;
7111 }
7112
7113 if (report != null) {
7114 if (errList == null) {
7115 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7116 }
7117 errList.add(report);
7118 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007119 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 " crashing = " + app.crashing +
7121 " notResponding = " + app.notResponding);
7122 }
7123 }
7124 }
7125 }
7126
7127 return errList;
7128 }
7129
7130 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7131 // Lazy instantiation of list
7132 List<ActivityManager.RunningAppProcessInfo> runList = null;
7133 synchronized (this) {
7134 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007135 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7136 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7138 // Generate process state info for running application
7139 ActivityManager.RunningAppProcessInfo currApp =
7140 new ActivityManager.RunningAppProcessInfo(app.processName,
7141 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007142 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007143 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007144 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007145 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007146 if (app.persistent) {
7147 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007150 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7152 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7153 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007154 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7155 } else if (adj >= HOME_APP_ADJ) {
7156 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7157 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 } else if (adj >= SECONDARY_SERVER_ADJ) {
7159 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007160 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007161 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007162 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7163 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 } else if (adj >= VISIBLE_APP_ADJ) {
7165 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7166 } else {
7167 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7168 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007169 currApp.importanceReasonCode = app.adjTypeCode;
7170 if (app.adjSource instanceof ProcessRecord) {
7171 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007172 } else if (app.adjSource instanceof ActivityRecord) {
7173 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007174 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7175 }
7176 if (app.adjTarget instanceof ComponentName) {
7177 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7178 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007179 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 // + " lru=" + currApp.lru);
7181 if (runList == null) {
7182 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7183 }
7184 runList.add(currApp);
7185 }
7186 }
7187 }
7188 return runList;
7189 }
7190
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007191 public List<ApplicationInfo> getRunningExternalApplications() {
7192 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7193 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7194 if (runningApps != null && runningApps.size() > 0) {
7195 Set<String> extList = new HashSet<String>();
7196 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7197 if (app.pkgList != null) {
7198 for (String pkg : app.pkgList) {
7199 extList.add(pkg);
7200 }
7201 }
7202 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007203 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007204 for (String pkg : extList) {
7205 try {
7206 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7207 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7208 retList.add(info);
7209 }
7210 } catch (RemoteException e) {
7211 }
7212 }
7213 }
7214 return retList;
7215 }
7216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 @Override
7218 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007219 if (checkCallingPermission(android.Manifest.permission.DUMP)
7220 != PackageManager.PERMISSION_GRANTED) {
7221 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7222 + Binder.getCallingPid()
7223 + ", uid=" + Binder.getCallingUid()
7224 + " without permission "
7225 + android.Manifest.permission.DUMP);
7226 return;
7227 }
7228
7229 boolean dumpAll = false;
7230
7231 int opti = 0;
7232 while (opti < args.length) {
7233 String opt = args[opti];
7234 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7235 break;
7236 }
7237 opti++;
7238 if ("-a".equals(opt)) {
7239 dumpAll = true;
7240 } else if ("-h".equals(opt)) {
7241 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007242 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007243 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007244 pw.println(" a[ctivities]: activity stack state");
7245 pw.println(" b[roadcasts]: broadcast state");
7246 pw.println(" i[ntents]: pending intent state");
7247 pw.println(" p[rocesses]: process state");
7248 pw.println(" o[om]: out of memory management");
7249 pw.println(" prov[iders]: content provider state");
7250 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007251 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 } else {
7254 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007255 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007256 }
7257
7258 // Is the caller requesting to dump a particular piece of data?
7259 if (opti < args.length) {
7260 String cmd = args[opti];
7261 opti++;
7262 if ("activities".equals(cmd) || "a".equals(cmd)) {
7263 synchronized (this) {
7264 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007266 return;
7267 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7268 synchronized (this) {
7269 dumpBroadcastsLocked(fd, pw, args, opti, true);
7270 }
7271 return;
7272 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7273 synchronized (this) {
7274 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7275 }
7276 return;
7277 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7278 synchronized (this) {
7279 dumpProcessesLocked(fd, pw, args, opti, true);
7280 }
7281 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007282 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7283 synchronized (this) {
7284 dumpOomLocked(fd, pw, args, opti, true);
7285 }
7286 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007287 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7288 synchronized (this) {
7289 dumpProvidersLocked(fd, pw, args, opti, true);
7290 }
7291 return;
7292 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007293 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007294 return;
7295 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7296 synchronized (this) {
7297 dumpServicesLocked(fd, pw, args, opti, true);
7298 }
7299 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007300 } else {
7301 // Dumping a single activity?
7302 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7303 return;
7304 }
7305 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007307 }
7308
7309 // No piece of data specified, dump everything.
7310 synchronized (this) {
7311 boolean needSep;
7312 if (dumpAll) {
7313 pw.println("Providers in Current Activity Manager State:");
7314 }
7315 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7316 if (needSep) {
7317 pw.println(" ");
7318 }
7319 if (dumpAll) {
7320 pw.println("-------------------------------------------------------------------------------");
7321 pw.println("Broadcasts in Current Activity Manager State:");
7322 }
7323 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7324 if (needSep) {
7325 pw.println(" ");
7326 }
7327 if (dumpAll) {
7328 pw.println("-------------------------------------------------------------------------------");
7329 pw.println("Services in Current Activity Manager State:");
7330 }
7331 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7332 if (needSep) {
7333 pw.println(" ");
7334 }
7335 if (dumpAll) {
7336 pw.println("-------------------------------------------------------------------------------");
7337 pw.println("PendingIntents in Current Activity Manager State:");
7338 }
7339 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7340 if (needSep) {
7341 pw.println(" ");
7342 }
7343 if (dumpAll) {
7344 pw.println("-------------------------------------------------------------------------------");
7345 pw.println("Activities in Current Activity Manager State:");
7346 }
7347 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7348 if (needSep) {
7349 pw.println(" ");
7350 }
7351 if (dumpAll) {
7352 pw.println("-------------------------------------------------------------------------------");
7353 pw.println("Processes in Current Activity Manager State:");
7354 }
7355 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7356 }
7357 }
7358
7359 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7360 int opti, boolean dumpAll, boolean needHeader) {
7361 if (needHeader) {
7362 pw.println(" Activity stack:");
7363 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007364 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007365 pw.println(" ");
7366 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007367 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7368 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007370 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007371 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007372 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007373 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007375 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007376 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007377 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007378 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007379 pw.println(" ");
7380 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007381 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007384 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007385 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7386 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007387 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007388 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390 if (dumpAll && mRecentTasks.size() > 0) {
7391 pw.println(" ");
7392 pw.println("Recent tasks in Current Activity Manager State:");
7393
7394 final int N = mRecentTasks.size();
7395 for (int i=0; i<N; i++) {
7396 TaskRecord tr = mRecentTasks.get(i);
7397 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7398 pw.println(tr);
7399 mRecentTasks.get(i).dump(pw, " ");
7400 }
7401 }
7402
7403 pw.println(" ");
7404 pw.println(" mCurTask: " + mCurTask);
7405
7406 return true;
7407 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007408
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007409 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7410 int opti, boolean dumpAll) {
7411 boolean needSep = false;
7412 int numPers = 0;
7413
7414 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7416 final int NA = procs.size();
7417 for (int ia=0; ia<NA; ia++) {
7418 if (!needSep) {
7419 pw.println(" All known processes:");
7420 needSep = true;
7421 }
7422 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007423 pw.print(r.persistent ? " *PERS*" : " *APP*");
7424 pw.print(" UID "); pw.print(procs.keyAt(ia));
7425 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 r.dump(pw, " ");
7427 if (r.persistent) {
7428 numPers++;
7429 }
7430 }
7431 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 }
7433
7434 if (mLruProcesses.size() > 0) {
7435 if (needSep) pw.println(" ");
7436 needSep = true;
7437 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007438 dumpProcessOomList(pw, this, mLruProcesses, " ",
7439 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007440 needSep = true;
7441 }
7442
7443 synchronized (mPidsSelfLocked) {
7444 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007445 if (needSep) pw.println(" ");
7446 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007447 pw.println(" PID mappings:");
7448 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7449 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7450 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451 }
7452 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007453 }
7454
7455 if (mForegroundProcesses.size() > 0) {
7456 if (needSep) pw.println(" ");
7457 needSep = true;
7458 pw.println(" Foreground Processes:");
7459 for (int i=0; i<mForegroundProcesses.size(); i++) {
7460 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7461 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007463 }
7464
7465 if (mPersistentStartingProcesses.size() > 0) {
7466 if (needSep) pw.println(" ");
7467 needSep = true;
7468 pw.println(" Persisent processes that are starting:");
7469 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007470 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007473 if (mStartingProcesses.size() > 0) {
7474 if (needSep) pw.println(" ");
7475 needSep = true;
7476 pw.println(" Processes that are starting:");
7477 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007478 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007479 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007480
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007481 if (mRemovedProcesses.size() > 0) {
7482 if (needSep) pw.println(" ");
7483 needSep = true;
7484 pw.println(" Processes that are being removed:");
7485 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007486 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007487 }
7488
7489 if (mProcessesOnHold.size() > 0) {
7490 if (needSep) pw.println(" ");
7491 needSep = true;
7492 pw.println(" Processes that are on old until the system is ready:");
7493 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007494 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007496
Dianne Hackborn287952c2010-09-22 22:34:31 -07007497 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498
7499 if (mProcessCrashTimes.getMap().size() > 0) {
7500 if (needSep) pw.println(" ");
7501 needSep = true;
7502 pw.println(" Time since processes crashed:");
7503 long now = SystemClock.uptimeMillis();
7504 for (Map.Entry<String, SparseArray<Long>> procs
7505 : mProcessCrashTimes.getMap().entrySet()) {
7506 SparseArray<Long> uids = procs.getValue();
7507 final int N = uids.size();
7508 for (int i=0; i<N; i++) {
7509 pw.print(" Process "); pw.print(procs.getKey());
7510 pw.print(" uid "); pw.print(uids.keyAt(i));
7511 pw.print(": last crashed ");
7512 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007513 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007514 }
7515 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007518 if (mBadProcesses.getMap().size() > 0) {
7519 if (needSep) pw.println(" ");
7520 needSep = true;
7521 pw.println(" Bad processes:");
7522 for (Map.Entry<String, SparseArray<Long>> procs
7523 : mBadProcesses.getMap().entrySet()) {
7524 SparseArray<Long> uids = procs.getValue();
7525 final int N = uids.size();
7526 for (int i=0; i<N; i++) {
7527 pw.print(" Bad process "); pw.print(procs.getKey());
7528 pw.print(" uid "); pw.print(uids.keyAt(i));
7529 pw.print(": crashed at time ");
7530 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 }
7532 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007535 pw.println(" ");
7536 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007537 if (mHeavyWeightProcess != null) {
7538 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7539 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007540 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007541 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007542 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7543 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7544 || mOrigWaitForDebugger) {
7545 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7546 + " mDebugTransient=" + mDebugTransient
7547 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7548 }
7549 if (mAlwaysFinishActivities || mController != null) {
7550 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7551 + " mController=" + mController);
7552 }
7553 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007555 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007556 + " mProcessesReady=" + mProcessesReady
7557 + " mSystemReady=" + mSystemReady);
7558 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 + " mBooted=" + mBooted
7560 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007561 pw.print(" mLastPowerCheckRealtime=");
7562 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7563 pw.println("");
7564 pw.print(" mLastPowerCheckUptime=");
7565 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7566 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007567 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7568 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007569 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007571
7572 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 }
7574
Dianne Hackborn287952c2010-09-22 22:34:31 -07007575 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7576 int opti, boolean needSep, boolean dumpAll) {
7577 if (mProcessesToGc.size() > 0) {
7578 if (needSep) pw.println(" ");
7579 needSep = true;
7580 pw.println(" Processes that are waiting to GC:");
7581 long now = SystemClock.uptimeMillis();
7582 for (int i=0; i<mProcessesToGc.size(); i++) {
7583 ProcessRecord proc = mProcessesToGc.get(i);
7584 pw.print(" Process "); pw.println(proc);
7585 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7586 pw.print(", last gced=");
7587 pw.print(now-proc.lastRequestedGc);
7588 pw.print(" ms ago, last lowMem=");
7589 pw.print(now-proc.lastLowMemory);
7590 pw.println(" ms ago");
7591
7592 }
7593 }
7594 return needSep;
7595 }
7596
7597 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7598 int opti, boolean dumpAll) {
7599 boolean needSep = false;
7600
7601 if (mLruProcesses.size() > 0) {
7602 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7603
7604 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7605 @Override
7606 public int compare(ProcessRecord object1, ProcessRecord object2) {
7607 if (object1.setAdj != object2.setAdj) {
7608 return object1.setAdj > object2.setAdj ? -1 : 1;
7609 }
7610 if (object1.setSchedGroup != object2.setSchedGroup) {
7611 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7612 }
7613 if (object1.keeping != object2.keeping) {
7614 return object1.keeping ? -1 : 1;
7615 }
7616 if (object1.pid != object2.pid) {
7617 return object1.pid > object2.pid ? -1 : 1;
7618 }
7619 return 0;
7620 }
7621 };
7622
7623 Collections.sort(procs, comparator);
7624
7625 if (needSep) pw.println(" ");
7626 needSep = true;
7627 pw.println(" Process OOM control:");
7628 dumpProcessOomList(pw, this, procs, " ",
7629 "Proc", "PERS", true);
7630 needSep = true;
7631 }
7632
7633 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7634
7635 pw.println(" ");
7636 pw.println(" mHomeProcess: " + mHomeProcess);
7637 if (mHeavyWeightProcess != null) {
7638 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7639 }
7640
7641 return true;
7642 }
7643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 /**
7645 * There are three ways to call this:
7646 * - no service specified: dump all the services
7647 * - a flattened component name that matched an existing service was specified as the
7648 * first arg: dump that one service
7649 * - the first arg isn't the flattened component name of an existing service:
7650 * dump all services whose component contains the first arg as a substring
7651 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007652 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 String[] newArgs;
7654 String componentNameString;
7655 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007656 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 componentNameString = null;
7658 newArgs = EMPTY_STRING_ARRAY;
7659 r = null;
7660 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 componentNameString = args[opti];
7662 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007664 synchronized (this) {
7665 r = componentName != null ? mServices.get(componentName) : null;
7666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 newArgs = new String[args.length - opti];
7668 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 }
7670
7671 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007672 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007674 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7675 synchronized (this) {
7676 for (ServiceRecord r1 : mServices.values()) {
7677 if (componentNameString == null
7678 || r1.name.flattenToString().contains(componentNameString)) {
7679 services.add(r1);
7680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681 }
7682 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007683 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007684 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007686 }
7687 }
7688
7689 /**
7690 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7691 * there is a thread associated with the service.
7692 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007693 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7694 pw.println("------------------------------------------------------------"
7695 + "-------------------");
7696 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 if (r.app != null && r.app.thread != null) {
7698 try {
7699 // flush anything that is already in the PrintWriter since the thread is going
7700 // to write to the file descriptor directly
7701 pw.flush();
7702 r.app.thread.dumpService(fd, r, args);
7703 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007704 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 } catch (RemoteException e) {
7706 pw.println("got a RemoteException while dumping the service");
7707 }
7708 }
7709 }
7710
Dianne Hackborn625ac272010-09-17 18:29:22 -07007711 /**
7712 * There are three things that cmd can be:
7713 * - a flattened component name that matched an existing activity
7714 * - the cmd arg isn't the flattened component name of an existing activity:
7715 * dump all activity whose component contains the cmd as a substring
7716 * - A hex number of the ActivityRecord object instance.
7717 */
7718 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7719 int opti, boolean dumpAll) {
7720 String[] newArgs;
7721 ComponentName componentName = ComponentName.unflattenFromString(name);
7722 int objectId = 0;
7723 try {
7724 objectId = Integer.parseInt(name, 16);
7725 name = null;
7726 componentName = null;
7727 } catch (RuntimeException e) {
7728 }
7729 newArgs = new String[args.length - opti];
7730 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7731
7732 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7733 synchronized (this) {
7734 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7735 if (componentName != null) {
7736 if (r1.intent.getComponent().equals(componentName)) {
7737 activities.add(r1);
7738 }
7739 } else if (name != null) {
7740 if (r1.intent.getComponent().flattenToString().contains(name)) {
7741 activities.add(r1);
7742 }
7743 } else if (System.identityHashCode(this) == objectId) {
7744 activities.add(r1);
7745 }
7746 }
7747 }
7748
7749 if (activities.size() <= 0) {
7750 return false;
7751 }
7752
7753 for (int i=0; i<activities.size(); i++) {
7754 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7755 }
7756 return true;
7757 }
7758
7759 /**
7760 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7761 * there is a thread associated with the activity.
7762 */
7763 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7764 boolean dumpAll) {
7765 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7766 if (dumpAll) {
7767 synchronized (this) {
7768 pw.print(" * "); pw.println(r);
7769 r.dump(pw, " ");
7770 }
7771 pw.println("");
7772 }
7773 if (r.app != null && r.app.thread != null) {
7774 try {
7775 // flush anything that is already in the PrintWriter since the thread is going
7776 // to write to the file descriptor directly
7777 pw.flush();
7778 r.app.thread.dumpActivity(fd, r, args);
7779 pw.print("\n");
7780 pw.flush();
7781 } catch (RemoteException e) {
7782 pw.println("got a RemoteException while dumping the activity");
7783 }
7784 }
7785 }
7786
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007787 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7788 int opti, boolean dumpAll) {
7789 boolean needSep = false;
7790
7791 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 if (mRegisteredReceivers.size() > 0) {
7793 pw.println(" ");
7794 pw.println(" Registered Receivers:");
7795 Iterator it = mRegisteredReceivers.values().iterator();
7796 while (it.hasNext()) {
7797 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007798 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 r.dump(pw, " ");
7800 }
7801 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 pw.println(" ");
7804 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007805 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007806 needSep = true;
7807 }
7808
7809 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7810 || mPendingBroadcast != null) {
7811 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007813 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007815 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7816 pw.println(" Broadcast #" + i + ":");
7817 mParallelBroadcasts.get(i).dump(pw, " ");
7818 }
7819 if (mOrderedBroadcasts.size() > 0) {
7820 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007821 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007822 }
7823 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7824 pw.println(" Serialized Broadcast #" + i + ":");
7825 mOrderedBroadcasts.get(i).dump(pw, " ");
7826 }
7827 pw.println(" ");
7828 pw.println(" Pending broadcast:");
7829 if (mPendingBroadcast != null) {
7830 mPendingBroadcast.dump(pw, " ");
7831 } else {
7832 pw.println(" (null)");
7833 }
7834 needSep = true;
7835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007837 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007839 pw.println(" Historical broadcasts:");
7840 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7841 BroadcastRecord r = mBroadcastHistory[i];
7842 if (r == null) {
7843 break;
7844 }
7845 pw.println(" Historical Broadcast #" + i + ":");
7846 r.dump(pw, " ");
7847 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007848 needSep = true;
7849 }
7850
7851 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007852 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007853 pw.println(" Sticky broadcasts:");
7854 StringBuilder sb = new StringBuilder(128);
7855 for (Map.Entry<String, ArrayList<Intent>> ent
7856 : mStickyBroadcasts.entrySet()) {
7857 pw.print(" * Sticky action "); pw.print(ent.getKey());
7858 pw.println(":");
7859 ArrayList<Intent> intents = ent.getValue();
7860 final int N = intents.size();
7861 for (int i=0; i<N; i++) {
7862 sb.setLength(0);
7863 sb.append(" Intent: ");
7864 intents.get(i).toShortString(sb, true, false);
7865 pw.println(sb.toString());
7866 Bundle bundle = intents.get(i).getExtras();
7867 if (bundle != null) {
7868 pw.print(" ");
7869 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007870 }
7871 }
7872 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007873 needSep = true;
7874 }
7875
7876 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007878 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 pw.println(" mHandler:");
7880 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007881 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007883
7884 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007885 }
7886
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007887 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7888 int opti, boolean dumpAll) {
7889 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007891 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 if (mServices.size() > 0) {
7893 pw.println(" Active services:");
7894 Iterator<ServiceRecord> it = mServices.values().iterator();
7895 while (it.hasNext()) {
7896 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007897 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 r.dump(pw, " ");
7899 }
7900 needSep = true;
7901 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007904 if (mPendingServices.size() > 0) {
7905 if (needSep) pw.println(" ");
7906 pw.println(" Pending services:");
7907 for (int i=0; i<mPendingServices.size(); i++) {
7908 ServiceRecord r = mPendingServices.get(i);
7909 pw.print(" * Pending "); pw.println(r);
7910 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912 needSep = true;
7913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007915 if (mRestartingServices.size() > 0) {
7916 if (needSep) pw.println(" ");
7917 pw.println(" Restarting services:");
7918 for (int i=0; i<mRestartingServices.size(); i++) {
7919 ServiceRecord r = mRestartingServices.get(i);
7920 pw.print(" * Restarting "); pw.println(r);
7921 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007923 needSep = true;
7924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007926 if (mStoppingServices.size() > 0) {
7927 if (needSep) pw.println(" ");
7928 pw.println(" Stopping services:");
7929 for (int i=0; i<mStoppingServices.size(); i++) {
7930 ServiceRecord r = mStoppingServices.get(i);
7931 pw.print(" * Stopping "); pw.println(r);
7932 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 needSep = true;
7935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007937 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 if (mServiceConnections.size() > 0) {
7939 if (needSep) pw.println(" ");
7940 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007941 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007942 = mServiceConnections.values().iterator();
7943 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007944 ArrayList<ConnectionRecord> r = it.next();
7945 for (int i=0; i<r.size(); i++) {
7946 pw.print(" * "); pw.println(r.get(i));
7947 r.get(i).dump(pw, " ");
7948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007950 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951 }
7952 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007953
7954 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 }
7956
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007957 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7958 int opti, boolean dumpAll) {
7959 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007960
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007961 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 if (mProvidersByClass.size() > 0) {
7963 if (needSep) pw.println(" ");
7964 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007965 Iterator<Map.Entry<String, ContentProviderRecord>> it
7966 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007968 Map.Entry<String, ContentProviderRecord> e = it.next();
7969 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007970 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 r.dump(pw, " ");
7972 }
7973 needSep = true;
7974 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007975
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007976 if (mProvidersByName.size() > 0) {
7977 pw.println(" ");
7978 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007979 Iterator<Map.Entry<String, ContentProviderRecord>> it
7980 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007981 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007982 Map.Entry<String, ContentProviderRecord> e = it.next();
7983 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007984 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7985 pw.println(r);
7986 }
7987 needSep = true;
7988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007990
7991 if (mLaunchingProviders.size() > 0) {
7992 if (needSep) pw.println(" ");
7993 pw.println(" Launching content providers:");
7994 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7995 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7996 pw.println(mLaunchingProviders.get(i));
7997 }
7998 needSep = true;
7999 }
8000
8001 if (mGrantedUriPermissions.size() > 0) {
8002 pw.println();
8003 pw.println("Granted Uri Permissions:");
8004 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8005 int uid = mGrantedUriPermissions.keyAt(i);
8006 HashMap<Uri, UriPermission> perms
8007 = mGrantedUriPermissions.valueAt(i);
8008 pw.print(" * UID "); pw.print(uid);
8009 pw.println(" holds:");
8010 for (UriPermission perm : perms.values()) {
8011 pw.print(" "); pw.println(perm);
8012 perm.dump(pw, " ");
8013 }
8014 }
8015 needSep = true;
8016 }
8017
8018 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 }
8020
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008021 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8022 int opti, boolean dumpAll) {
8023 boolean needSep = false;
8024
8025 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 if (this.mIntentSenderRecords.size() > 0) {
8027 Iterator<WeakReference<PendingIntentRecord>> it
8028 = mIntentSenderRecords.values().iterator();
8029 while (it.hasNext()) {
8030 WeakReference<PendingIntentRecord> ref = it.next();
8031 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008032 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008034 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035 rec.dump(pw, " ");
8036 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008037 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 }
8039 }
8040 }
8041 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008042
8043 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 }
8045
8046 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008047 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 TaskRecord lastTask = null;
8049 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008050 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008051 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 if (lastTask != r.task) {
8053 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008054 pw.print(prefix);
8055 pw.print(full ? "* " : " ");
8056 pw.println(lastTask);
8057 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008058 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008060 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008061 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8062 pw.print(" #"); pw.print(i); pw.print(": ");
8063 pw.println(r);
8064 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008065 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067 }
8068 }
8069
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008070 private static String buildOomTag(String prefix, String space, int val, int base) {
8071 if (val == base) {
8072 if (space == null) return prefix;
8073 return prefix + " ";
8074 }
8075 return prefix + "+" + Integer.toString(val-base);
8076 }
8077
8078 private static final int dumpProcessList(PrintWriter pw,
8079 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008080 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008082 final int N = list.size()-1;
8083 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008085 pw.println(String.format("%s%s #%2d: %s",
8086 prefix, (r.persistent ? persistentLabel : normalLabel),
8087 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008088 if (r.persistent) {
8089 numPers++;
8090 }
8091 }
8092 return numPers;
8093 }
8094
Dianne Hackborn287952c2010-09-22 22:34:31 -07008095 private static final void dumpProcessOomList(PrintWriter pw,
8096 ActivityManagerService service, List<ProcessRecord> list,
8097 String prefix, String normalLabel, String persistentLabel,
8098 boolean inclDetails) {
8099
8100 final long curRealtime = SystemClock.elapsedRealtime();
8101 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8102 final long curUptime = SystemClock.uptimeMillis();
8103 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8104
8105 final int N = list.size()-1;
8106 for (int i=N; i>=0; i--) {
8107 ProcessRecord r = list.get(i);
8108 String oomAdj;
8109 if (r.setAdj >= EMPTY_APP_ADJ) {
8110 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8111 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8112 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8113 } else if (r.setAdj >= HOME_APP_ADJ) {
8114 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8115 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8116 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8117 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8118 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8119 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8120 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8121 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8122 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8123 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8124 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8125 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8126 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8127 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8128 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8129 } else if (r.setAdj >= SYSTEM_ADJ) {
8130 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8131 } else {
8132 oomAdj = Integer.toString(r.setAdj);
8133 }
8134 String schedGroup;
8135 switch (r.setSchedGroup) {
8136 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8137 schedGroup = "B";
8138 break;
8139 case Process.THREAD_GROUP_DEFAULT:
8140 schedGroup = "F";
8141 break;
8142 default:
8143 schedGroup = Integer.toString(r.setSchedGroup);
8144 break;
8145 }
8146 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8147 prefix, (r.persistent ? persistentLabel : normalLabel),
8148 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8149 if (r.adjSource != null || r.adjTarget != null) {
8150 pw.print(prefix);
8151 pw.print(" ");
8152 if (r.adjTarget instanceof ComponentName) {
8153 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8154 } else if (r.adjTarget != null) {
8155 pw.print(r.adjTarget.toString());
8156 } else {
8157 pw.print("{null}");
8158 }
8159 pw.print("<=");
8160 if (r.adjSource instanceof ProcessRecord) {
8161 pw.print("Proc{");
8162 pw.print(((ProcessRecord)r.adjSource).toShortString());
8163 pw.println("}");
8164 } else if (r.adjSource != null) {
8165 pw.println(r.adjSource.toString());
8166 } else {
8167 pw.println("{null}");
8168 }
8169 }
8170 if (inclDetails) {
8171 pw.print(prefix);
8172 pw.print(" ");
8173 pw.print("oom: max="); pw.print(r.maxAdj);
8174 pw.print(" hidden="); pw.print(r.hiddenAdj);
8175 pw.print(" curRaw="); pw.print(r.curRawAdj);
8176 pw.print(" setRaw="); pw.print(r.setRawAdj);
8177 pw.print(" cur="); pw.print(r.curAdj);
8178 pw.print(" set="); pw.println(r.setAdj);
8179 pw.print(prefix);
8180 pw.print(" ");
8181 pw.print("keeping="); pw.print(r.keeping);
8182 pw.print(" hidden="); pw.print(r.hidden);
8183 pw.print(" empty="); pw.println(r.empty);
8184
8185 if (!r.keeping) {
8186 if (r.lastWakeTime != 0) {
8187 long wtime;
8188 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8189 synchronized (stats) {
8190 wtime = stats.getProcessWakeTime(r.info.uid,
8191 r.pid, curRealtime);
8192 }
8193 long timeUsed = wtime - r.lastWakeTime;
8194 pw.print(prefix);
8195 pw.print(" ");
8196 pw.print("keep awake over ");
8197 TimeUtils.formatDuration(realtimeSince, pw);
8198 pw.print(" used ");
8199 TimeUtils.formatDuration(timeUsed, pw);
8200 pw.print(" (");
8201 pw.print((timeUsed*100)/realtimeSince);
8202 pw.println("%)");
8203 }
8204 if (r.lastCpuTime != 0) {
8205 long timeUsed = r.curCpuTime - r.lastCpuTime;
8206 pw.print(prefix);
8207 pw.print(" ");
8208 pw.print("run cpu over ");
8209 TimeUtils.formatDuration(uptimeSince, pw);
8210 pw.print(" used ");
8211 TimeUtils.formatDuration(timeUsed, pw);
8212 pw.print(" (");
8213 pw.print((timeUsed*100)/uptimeSince);
8214 pw.println("%)");
8215 }
8216 }
8217 }
8218 }
8219 }
8220
Dianne Hackborn472ad872010-04-07 17:31:48 -07008221 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008223 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 long uptime = SystemClock.uptimeMillis();
8225 long realtime = SystemClock.elapsedRealtime();
8226
8227 if (isCheckinRequest) {
8228 // short checkin version
8229 pw.println(uptime + "," + realtime);
8230 pw.flush();
8231 } else {
8232 pw.println("Applications Memory Usage (kB):");
8233 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8234 }
8235 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8236 ProcessRecord r = (ProcessRecord)list.get(i);
8237 if (r.thread != null) {
8238 if (!isCheckinRequest) {
8239 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8240 pw.flush();
8241 }
8242 try {
8243 r.thread.asBinder().dump(fd, args);
8244 } catch (RemoteException e) {
8245 if (!isCheckinRequest) {
8246 pw.println("Got RemoteException!");
8247 pw.flush();
8248 }
8249 }
8250 }
8251 }
8252 }
8253
8254 /**
8255 * Searches array of arguments for the specified string
8256 * @param args array of argument strings
8257 * @param value value to search for
8258 * @return true if the value is contained in the array
8259 */
8260 private static boolean scanArgs(String[] args, String value) {
8261 if (args != null) {
8262 for (String arg : args) {
8263 if (value.equals(arg)) {
8264 return true;
8265 }
8266 }
8267 }
8268 return false;
8269 }
8270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 private final void killServicesLocked(ProcessRecord app,
8272 boolean allowRestart) {
8273 // Report disconnected services.
8274 if (false) {
8275 // XXX we are letting the client link to the service for
8276 // death notifications.
8277 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008278 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008280 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008281 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008282 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 = r.connections.values().iterator();
8284 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008285 ArrayList<ConnectionRecord> cl = jt.next();
8286 for (int i=0; i<cl.size(); i++) {
8287 ConnectionRecord c = cl.get(i);
8288 if (c.binding.client != app) {
8289 try {
8290 //c.conn.connected(r.className, null);
8291 } catch (Exception e) {
8292 // todo: this should be asynchronous!
8293 Slog.w(TAG, "Exception thrown disconnected servce "
8294 + r.shortName
8295 + " from app " + app.processName, e);
8296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008297 }
8298 }
8299 }
8300 }
8301 }
8302 }
8303 }
8304
8305 // Clean up any connections this application has to other services.
8306 if (app.connections.size() > 0) {
8307 Iterator<ConnectionRecord> it = app.connections.iterator();
8308 while (it.hasNext()) {
8309 ConnectionRecord r = it.next();
8310 removeConnectionLocked(r, app, null);
8311 }
8312 }
8313 app.connections.clear();
8314
8315 if (app.services.size() != 0) {
8316 // Any services running in the application need to be placed
8317 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008318 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008319 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008320 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 synchronized (sr.stats.getBatteryStats()) {
8322 sr.stats.stopLaunchedLocked();
8323 }
8324 sr.app = null;
8325 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008326 if (mStoppingServices.remove(sr)) {
8327 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8328 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008329
8330 boolean hasClients = sr.bindings.size() > 0;
8331 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 Iterator<IntentBindRecord> bindings
8333 = sr.bindings.values().iterator();
8334 while (bindings.hasNext()) {
8335 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008336 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008337 + ": shouldUnbind=" + b.hasBound);
8338 b.binder = null;
8339 b.requested = b.received = b.hasBound = false;
8340 }
8341 }
8342
8343 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008344 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008346 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 sr.crashCount, sr.shortName, app.pid);
8348 bringDownServiceLocked(sr, true);
8349 } else if (!allowRestart) {
8350 bringDownServiceLocked(sr, true);
8351 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008352 boolean canceled = scheduleServiceRestartLocked(sr, true);
8353
8354 // Should the service remain running? Note that in the
8355 // extreme case of so many attempts to deliver a command
8356 // that it failed, that we also will stop it here.
8357 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8358 if (sr.pendingStarts.size() == 0) {
8359 sr.startRequested = false;
8360 if (!hasClients) {
8361 // Whoops, no reason to restart!
8362 bringDownServiceLocked(sr, true);
8363 }
8364 }
8365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366 }
8367 }
8368
8369 if (!allowRestart) {
8370 app.services.clear();
8371 }
8372 }
8373
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008374 // Make sure we have no more records on the stopping list.
8375 int i = mStoppingServices.size();
8376 while (i > 0) {
8377 i--;
8378 ServiceRecord sr = mStoppingServices.get(i);
8379 if (sr.app == app) {
8380 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008381 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008382 }
8383 }
8384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 app.executingServices.clear();
8386 }
8387
8388 private final void removeDyingProviderLocked(ProcessRecord proc,
8389 ContentProviderRecord cpr) {
8390 synchronized (cpr) {
8391 cpr.launchingApp = null;
8392 cpr.notifyAll();
8393 }
8394
8395 mProvidersByClass.remove(cpr.info.name);
8396 String names[] = cpr.info.authority.split(";");
8397 for (int j = 0; j < names.length; j++) {
8398 mProvidersByName.remove(names[j]);
8399 }
8400
8401 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8402 while (cit.hasNext()) {
8403 ProcessRecord capp = cit.next();
8404 if (!capp.persistent && capp.thread != null
8405 && capp.pid != 0
8406 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008407 Slog.i(TAG, "Kill " + capp.processName
8408 + " (pid " + capp.pid + "): provider " + cpr.info.name
8409 + " in dying process " + proc.processName);
8410 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8411 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 Process.killProcess(capp.pid);
8413 }
8414 }
8415
8416 mLaunchingProviders.remove(cpr);
8417 }
8418
8419 /**
8420 * Main code for cleaning up a process when it has gone away. This is
8421 * called both as a result of the process dying, or directly when stopping
8422 * a process when running in single process mode.
8423 */
8424 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8425 boolean restarting, int index) {
8426 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008427 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 }
8429
Dianne Hackborn36124872009-10-08 16:22:03 -07008430 mProcessesToGc.remove(app);
8431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 // Dismiss any open dialogs.
8433 if (app.crashDialog != null) {
8434 app.crashDialog.dismiss();
8435 app.crashDialog = null;
8436 }
8437 if (app.anrDialog != null) {
8438 app.anrDialog.dismiss();
8439 app.anrDialog = null;
8440 }
8441 if (app.waitDialog != null) {
8442 app.waitDialog.dismiss();
8443 app.waitDialog = null;
8444 }
8445
8446 app.crashing = false;
8447 app.notResponding = false;
8448
8449 app.resetPackageList();
8450 app.thread = null;
8451 app.forcingToForeground = null;
8452 app.foregroundServices = false;
8453
8454 killServicesLocked(app, true);
8455
8456 boolean restart = false;
8457
8458 int NL = mLaunchingProviders.size();
8459
8460 // Remove published content providers.
8461 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008462 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008464 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 cpr.provider = null;
8466 cpr.app = null;
8467
8468 // See if someone is waiting for this provider... in which
8469 // case we don't remove it, but just let it restart.
8470 int i = 0;
8471 if (!app.bad) {
8472 for (; i<NL; i++) {
8473 if (mLaunchingProviders.get(i) == cpr) {
8474 restart = true;
8475 break;
8476 }
8477 }
8478 } else {
8479 i = NL;
8480 }
8481
8482 if (i >= NL) {
8483 removeDyingProviderLocked(app, cpr);
8484 NL = mLaunchingProviders.size();
8485 }
8486 }
8487 app.pubProviders.clear();
8488 }
8489
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008490 // Take care of any launching providers waiting for this process.
8491 if (checkAppInLaunchingProvidersLocked(app, false)) {
8492 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 // Unregister from connected content providers.
8496 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008497 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008498 while (it.hasNext()) {
8499 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8500 cpr.clients.remove(app);
8501 }
8502 app.conProviders.clear();
8503 }
8504
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008505 // At this point there may be remaining entries in mLaunchingProviders
8506 // where we were the only one waiting, so they are no longer of use.
8507 // Look for these and clean up if found.
8508 // XXX Commented out for now. Trying to figure out a way to reproduce
8509 // the actual situation to identify what is actually going on.
8510 if (false) {
8511 for (int i=0; i<NL; i++) {
8512 ContentProviderRecord cpr = (ContentProviderRecord)
8513 mLaunchingProviders.get(i);
8514 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8515 synchronized (cpr) {
8516 cpr.launchingApp = null;
8517 cpr.notifyAll();
8518 }
8519 }
8520 }
8521 }
8522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008523 skipCurrentReceiverLocked(app);
8524
8525 // Unregister any receivers.
8526 if (app.receivers.size() > 0) {
8527 Iterator<ReceiverList> it = app.receivers.iterator();
8528 while (it.hasNext()) {
8529 removeReceiverLocked(it.next());
8530 }
8531 app.receivers.clear();
8532 }
8533
Christopher Tate181fafa2009-05-14 11:12:14 -07008534 // If the app is undergoing backup, tell the backup manager about it
8535 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008536 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008537 try {
8538 IBackupManager bm = IBackupManager.Stub.asInterface(
8539 ServiceManager.getService(Context.BACKUP_SERVICE));
8540 bm.agentDisconnected(app.info.packageName);
8541 } catch (RemoteException e) {
8542 // can't happen; backup manager is local
8543 }
8544 }
8545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 // If the caller is restarting this app, then leave it in its
8547 // current lists and let the caller take care of it.
8548 if (restarting) {
8549 return;
8550 }
8551
8552 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008553 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 "Removing non-persistent process during cleanup: " + app);
8555 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008556 if (mHeavyWeightProcess == app) {
8557 mHeavyWeightProcess = null;
8558 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008560 } else if (!app.removed) {
8561 // This app is persistent, so we need to keep its record around.
8562 // If it is not already on the pending app list, add it there
8563 // and start a new process for it.
8564 app.thread = null;
8565 app.forcingToForeground = null;
8566 app.foregroundServices = false;
8567 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8568 mPersistentStartingProcesses.add(app);
8569 restart = true;
8570 }
8571 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008572 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8573 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 mProcessesOnHold.remove(app);
8575
The Android Open Source Project4df24232009-03-05 14:34:35 -08008576 if (app == mHomeProcess) {
8577 mHomeProcess = null;
8578 }
8579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580 if (restart) {
8581 // We have components that still need to be running in the
8582 // process, so re-launch it.
8583 mProcessNames.put(app.processName, app.info.uid, app);
8584 startProcessLocked(app, "restart", app.processName);
8585 } else if (app.pid > 0 && app.pid != MY_PID) {
8586 // Goodbye!
8587 synchronized (mPidsSelfLocked) {
8588 mPidsSelfLocked.remove(app.pid);
8589 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8590 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008591 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008592 }
8593 }
8594
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008595 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8596 // Look through the content providers we are waiting to have launched,
8597 // and if any run in this process then either schedule a restart of
8598 // the process or kill the client waiting for it if this process has
8599 // gone bad.
8600 int NL = mLaunchingProviders.size();
8601 boolean restart = false;
8602 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008603 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008604 if (cpr.launchingApp == app) {
8605 if (!alwaysBad && !app.bad) {
8606 restart = true;
8607 } else {
8608 removeDyingProviderLocked(app, cpr);
8609 NL = mLaunchingProviders.size();
8610 }
8611 }
8612 }
8613 return restart;
8614 }
8615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008616 // =========================================================
8617 // SERVICES
8618 // =========================================================
8619
8620 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8621 ActivityManager.RunningServiceInfo info =
8622 new ActivityManager.RunningServiceInfo();
8623 info.service = r.name;
8624 if (r.app != null) {
8625 info.pid = r.app.pid;
8626 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008627 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008628 info.process = r.processName;
8629 info.foreground = r.isForeground;
8630 info.activeSince = r.createTime;
8631 info.started = r.startRequested;
8632 info.clientCount = r.connections.size();
8633 info.crashCount = r.crashCount;
8634 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008635 if (r.isForeground) {
8636 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8637 }
8638 if (r.startRequested) {
8639 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8640 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008641 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008642 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8643 }
8644 if (r.app != null && r.app.persistent) {
8645 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8646 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008647
8648 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8649 for (int i=0; i<connl.size(); i++) {
8650 ConnectionRecord conn = connl.get(i);
8651 if (conn.clientLabel != 0) {
8652 info.clientPackage = conn.binding.client.info.packageName;
8653 info.clientLabel = conn.clientLabel;
8654 return info;
8655 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008656 }
8657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008658 return info;
8659 }
8660
8661 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8662 int flags) {
8663 synchronized (this) {
8664 ArrayList<ActivityManager.RunningServiceInfo> res
8665 = new ArrayList<ActivityManager.RunningServiceInfo>();
8666
8667 if (mServices.size() > 0) {
8668 Iterator<ServiceRecord> it = mServices.values().iterator();
8669 while (it.hasNext() && res.size() < maxNum) {
8670 res.add(makeRunningServiceInfoLocked(it.next()));
8671 }
8672 }
8673
8674 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8675 ServiceRecord r = mRestartingServices.get(i);
8676 ActivityManager.RunningServiceInfo info =
8677 makeRunningServiceInfoLocked(r);
8678 info.restarting = r.nextRestartTime;
8679 res.add(info);
8680 }
8681
8682 return res;
8683 }
8684 }
8685
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008686 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8687 synchronized (this) {
8688 ServiceRecord r = mServices.get(name);
8689 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008690 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8691 for (int i=0; i<conn.size(); i++) {
8692 if (conn.get(i).clientIntent != null) {
8693 return conn.get(i).clientIntent;
8694 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008695 }
8696 }
8697 }
8698 }
8699 return null;
8700 }
8701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 private final ServiceRecord findServiceLocked(ComponentName name,
8703 IBinder token) {
8704 ServiceRecord r = mServices.get(name);
8705 return r == token ? r : null;
8706 }
8707
8708 private final class ServiceLookupResult {
8709 final ServiceRecord record;
8710 final String permission;
8711
8712 ServiceLookupResult(ServiceRecord _record, String _permission) {
8713 record = _record;
8714 permission = _permission;
8715 }
8716 };
8717
8718 private ServiceLookupResult findServiceLocked(Intent service,
8719 String resolvedType) {
8720 ServiceRecord r = null;
8721 if (service.getComponent() != null) {
8722 r = mServices.get(service.getComponent());
8723 }
8724 if (r == null) {
8725 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8726 r = mServicesByIntent.get(filter);
8727 }
8728
8729 if (r == null) {
8730 try {
8731 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008732 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008733 service, resolvedType, 0);
8734 ServiceInfo sInfo =
8735 rInfo != null ? rInfo.serviceInfo : null;
8736 if (sInfo == null) {
8737 return null;
8738 }
8739
8740 ComponentName name = new ComponentName(
8741 sInfo.applicationInfo.packageName, sInfo.name);
8742 r = mServices.get(name);
8743 } catch (RemoteException ex) {
8744 // pm is in same process, this will never happen.
8745 }
8746 }
8747 if (r != null) {
8748 int callingPid = Binder.getCallingPid();
8749 int callingUid = Binder.getCallingUid();
8750 if (checkComponentPermission(r.permission,
8751 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8752 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008753 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 + " from pid=" + callingPid
8755 + ", uid=" + callingUid
8756 + " requires " + r.permission);
8757 return new ServiceLookupResult(null, r.permission);
8758 }
8759 return new ServiceLookupResult(r, null);
8760 }
8761 return null;
8762 }
8763
8764 private class ServiceRestarter implements Runnable {
8765 private ServiceRecord mService;
8766
8767 void setService(ServiceRecord service) {
8768 mService = service;
8769 }
8770
8771 public void run() {
8772 synchronized(ActivityManagerService.this) {
8773 performServiceRestartLocked(mService);
8774 }
8775 }
8776 }
8777
8778 private ServiceLookupResult retrieveServiceLocked(Intent service,
8779 String resolvedType, int callingPid, int callingUid) {
8780 ServiceRecord r = null;
8781 if (service.getComponent() != null) {
8782 r = mServices.get(service.getComponent());
8783 }
8784 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8785 r = mServicesByIntent.get(filter);
8786 if (r == null) {
8787 try {
8788 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008789 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008790 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 ServiceInfo sInfo =
8792 rInfo != null ? rInfo.serviceInfo : null;
8793 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008794 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008795 ": not found");
8796 return null;
8797 }
8798
8799 ComponentName name = new ComponentName(
8800 sInfo.applicationInfo.packageName, sInfo.name);
8801 r = mServices.get(name);
8802 if (r == null) {
8803 filter = new Intent.FilterComparison(service.cloneFilter());
8804 ServiceRestarter res = new ServiceRestarter();
8805 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8806 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8807 synchronized (stats) {
8808 ss = stats.getServiceStatsLocked(
8809 sInfo.applicationInfo.uid, sInfo.packageName,
8810 sInfo.name);
8811 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008812 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 res.setService(r);
8814 mServices.put(name, r);
8815 mServicesByIntent.put(filter, r);
8816
8817 // Make sure this component isn't in the pending list.
8818 int N = mPendingServices.size();
8819 for (int i=0; i<N; i++) {
8820 ServiceRecord pr = mPendingServices.get(i);
8821 if (pr.name.equals(name)) {
8822 mPendingServices.remove(i);
8823 i--;
8824 N--;
8825 }
8826 }
8827 }
8828 } catch (RemoteException ex) {
8829 // pm is in same process, this will never happen.
8830 }
8831 }
8832 if (r != null) {
8833 if (checkComponentPermission(r.permission,
8834 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8835 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008836 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008837 + " from pid=" + Binder.getCallingPid()
8838 + ", uid=" + Binder.getCallingUid()
8839 + " requires " + r.permission);
8840 return new ServiceLookupResult(null, r.permission);
8841 }
8842 return new ServiceLookupResult(r, null);
8843 }
8844 return null;
8845 }
8846
Dianne Hackborn287952c2010-09-22 22:34:31 -07008847 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8848 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8849 + why + " of " + r + " in app " + r.app);
8850 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8851 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008852 long now = SystemClock.uptimeMillis();
8853 if (r.executeNesting == 0 && r.app != null) {
8854 if (r.app.executingServices.size() == 0) {
8855 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8856 msg.obj = r.app;
8857 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8858 }
8859 r.app.executingServices.add(r);
8860 }
8861 r.executeNesting++;
8862 r.executingStart = now;
8863 }
8864
8865 private final void sendServiceArgsLocked(ServiceRecord r,
8866 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008867 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 if (N == 0) {
8869 return;
8870 }
8871
Dianne Hackborn39792d22010-08-19 18:01:52 -07008872 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008873 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008874 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008875 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8876 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008877 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008878 // If somehow we got a dummy start at the front, then
8879 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008880 continue;
8881 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008882 si.deliveredTime = SystemClock.uptimeMillis();
8883 r.deliveredStarts.add(si);
8884 si.deliveryCount++;
8885 if (si.targetPermissionUid >= 0) {
8886 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008887 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008888 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008889 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 if (!oomAdjusted) {
8891 oomAdjusted = true;
8892 updateOomAdjLocked(r.app);
8893 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008894 int flags = 0;
8895 if (si.deliveryCount > 0) {
8896 flags |= Service.START_FLAG_RETRY;
8897 }
8898 if (si.doneExecutingCount > 0) {
8899 flags |= Service.START_FLAG_REDELIVERY;
8900 }
8901 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008902 } catch (RemoteException e) {
8903 // Remote process gone... we'll let the normal cleanup take
8904 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008905 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008906 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008907 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008908 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008909 break;
8910 }
8911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008912 }
8913
8914 private final boolean requestServiceBindingLocked(ServiceRecord r,
8915 IntentBindRecord i, boolean rebind) {
8916 if (r.app == null || r.app.thread == null) {
8917 // If service is not currently running, can't yet bind.
8918 return false;
8919 }
8920 if ((!i.requested || rebind) && i.apps.size() > 0) {
8921 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008922 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8924 if (!rebind) {
8925 i.requested = true;
8926 }
8927 i.hasBound = true;
8928 i.doRebind = false;
8929 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008930 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 return false;
8932 }
8933 }
8934 return true;
8935 }
8936
8937 private final void requestServiceBindingsLocked(ServiceRecord r) {
8938 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8939 while (bindings.hasNext()) {
8940 IntentBindRecord i = bindings.next();
8941 if (!requestServiceBindingLocked(r, i, false)) {
8942 break;
8943 }
8944 }
8945 }
8946
8947 private final void realStartServiceLocked(ServiceRecord r,
8948 ProcessRecord app) throws RemoteException {
8949 if (app.thread == null) {
8950 throw new RemoteException();
8951 }
8952
8953 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008954 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008955
8956 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008957 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008958 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959
8960 boolean created = false;
8961 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008962 mStringBuilder.setLength(0);
8963 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008964 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008965 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008966 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 synchronized (r.stats.getBatteryStats()) {
8968 r.stats.startLaunchedLocked();
8969 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008970 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008971 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008972 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 created = true;
8974 } finally {
8975 if (!created) {
8976 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008977 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008978 }
8979 }
8980
8981 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008982
8983 // If the service is in the started state, and there are no
8984 // pending arguments, then fake up one so its onStartCommand() will
8985 // be called.
8986 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8987 r.lastStartId++;
8988 if (r.lastStartId < 1) {
8989 r.lastStartId = 1;
8990 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008991 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008992 }
8993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 sendServiceArgsLocked(r, true);
8995 }
8996
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008997 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8998 boolean allowCancel) {
8999 boolean canceled = false;
9000
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009001 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009002 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009003 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009004
9005 // Any delivered but not yet finished starts should be put back
9006 // on the pending list.
9007 final int N = r.deliveredStarts.size();
9008 if (N > 0) {
9009 for (int i=N-1; i>=0; i--) {
9010 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009011 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009012 if (si.intent == null) {
9013 // We'll generate this again if needed.
9014 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9015 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9016 r.pendingStarts.add(0, si);
9017 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9018 dur *= 2;
9019 if (minDuration < dur) minDuration = dur;
9020 if (resetTime < dur) resetTime = dur;
9021 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009022 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009023 + r.name);
9024 canceled = true;
9025 }
9026 }
9027 r.deliveredStarts.clear();
9028 }
9029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009030 r.totalRestartCount++;
9031 if (r.restartDelay == 0) {
9032 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009033 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 } else {
9035 // If it has been a "reasonably long time" since the service
9036 // was started, then reset our restart duration back to
9037 // the beginning, so we don't infinitely increase the duration
9038 // on a service that just occasionally gets killed (which is
9039 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009040 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009042 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009043 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009044 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009045 if (r.restartDelay < minDuration) {
9046 r.restartDelay = minDuration;
9047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009048 }
9049 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009050
9051 r.nextRestartTime = now + r.restartDelay;
9052
9053 // Make sure that we don't end up restarting a bunch of services
9054 // all at the same time.
9055 boolean repeat;
9056 do {
9057 repeat = false;
9058 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9059 ServiceRecord r2 = mRestartingServices.get(i);
9060 if (r2 != r && r.nextRestartTime
9061 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9062 && r.nextRestartTime
9063 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9064 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9065 r.restartDelay = r.nextRestartTime - now;
9066 repeat = true;
9067 break;
9068 }
9069 }
9070 } while (repeat);
9071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 if (!mRestartingServices.contains(r)) {
9073 mRestartingServices.add(r);
9074 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009075
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009076 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009078 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009079 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009081 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009083 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 r.shortName, r.restartDelay);
9085
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009086 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 }
9088
9089 final void performServiceRestartLocked(ServiceRecord r) {
9090 if (!mRestartingServices.contains(r)) {
9091 return;
9092 }
9093 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9094 }
9095
9096 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9097 if (r.restartDelay == 0) {
9098 return false;
9099 }
9100 r.resetRestartCounter();
9101 mRestartingServices.remove(r);
9102 mHandler.removeCallbacks(r.restarter);
9103 return true;
9104 }
9105
9106 private final boolean bringUpServiceLocked(ServiceRecord r,
9107 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009108 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 //r.dump(" ");
9110
Dianne Hackborn36124872009-10-08 16:22:03 -07009111 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 sendServiceArgsLocked(r, false);
9113 return true;
9114 }
9115
9116 if (!whileRestarting && r.restartDelay > 0) {
9117 // If waiting for a restart, then do nothing.
9118 return true;
9119 }
9120
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009121 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009123 // We are now bringing the service up, so no longer in the
9124 // restarting state.
9125 mRestartingServices.remove(r);
9126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009127 final String appName = r.processName;
9128 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9129 if (app != null && app.thread != null) {
9130 try {
9131 realStartServiceLocked(r, app);
9132 return true;
9133 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009134 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 }
9136
9137 // If a dead object exception was thrown -- fall through to
9138 // restart the application.
9139 }
9140
Dianne Hackborn36124872009-10-08 16:22:03 -07009141 // Not running -- get it started, and enqueue this service record
9142 // to be executed when the app comes up.
9143 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9144 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009145 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009146 + r.appInfo.packageName + "/"
9147 + r.appInfo.uid + " for service "
9148 + r.intent.getIntent() + ": process is bad");
9149 bringDownServiceLocked(r, true);
9150 return false;
9151 }
9152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 mPendingServices.add(r);
9155 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 return true;
9158 }
9159
9160 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009161 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009162 //r.dump(" ");
9163
9164 // Does it still need to run?
9165 if (!force && r.startRequested) {
9166 return;
9167 }
9168 if (r.connections.size() > 0) {
9169 if (!force) {
9170 // XXX should probably keep a count of the number of auto-create
9171 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009172 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009174 ArrayList<ConnectionRecord> cr = it.next();
9175 for (int i=0; i<cr.size(); i++) {
9176 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9177 return;
9178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 }
9180 }
9181 }
9182
9183 // Report to all of the connections that the service is no longer
9184 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009185 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009187 ArrayList<ConnectionRecord> c = it.next();
9188 for (int i=0; i<c.size(); i++) {
9189 try {
9190 c.get(i).conn.connected(r.name, null);
9191 } catch (Exception e) {
9192 Slog.w(TAG, "Failure disconnecting service " + r.name +
9193 " to connection " + c.get(i).conn.asBinder() +
9194 " (in " + c.get(i).binding.client.processName + ")", e);
9195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 }
9197 }
9198 }
9199
9200 // Tell the service that it has been unbound.
9201 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9202 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9203 while (it.hasNext()) {
9204 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009205 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 + ": hasBound=" + ibr.hasBound);
9207 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9208 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009209 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009210 updateOomAdjLocked(r.app);
9211 ibr.hasBound = false;
9212 r.app.thread.scheduleUnbindService(r,
9213 ibr.intent.getIntent());
9214 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009215 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009216 + r.shortName, e);
9217 serviceDoneExecutingLocked(r, true);
9218 }
9219 }
9220 }
9221 }
9222
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009223 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009224 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 System.identityHashCode(r), r.shortName,
9226 (r.app != null) ? r.app.pid : -1);
9227
9228 mServices.remove(r.name);
9229 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 r.totalRestartCount = 0;
9231 unscheduleServiceRestartLocked(r);
9232
9233 // Also make sure it is not on the pending list.
9234 int N = mPendingServices.size();
9235 for (int i=0; i<N; i++) {
9236 if (mPendingServices.get(i) == r) {
9237 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009238 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 i--;
9240 N--;
9241 }
9242 }
9243
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009244 r.cancelNotification();
9245 r.isForeground = false;
9246 r.foregroundId = 0;
9247 r.foregroundNoti = null;
9248
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009249 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009250 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009251 r.pendingStarts.clear();
9252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009253 if (r.app != null) {
9254 synchronized (r.stats.getBatteryStats()) {
9255 r.stats.stopLaunchedLocked();
9256 }
9257 r.app.services.remove(r);
9258 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009260 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 mStoppingServices.add(r);
9262 updateOomAdjLocked(r.app);
9263 r.app.thread.scheduleStopService(r);
9264 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009265 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 + r.shortName, e);
9267 serviceDoneExecutingLocked(r, true);
9268 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009269 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009270 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009271 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009272 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 }
9274 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009275 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009276 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 }
9278 }
9279
9280 ComponentName startServiceLocked(IApplicationThread caller,
9281 Intent service, String resolvedType,
9282 int callingPid, int callingUid) {
9283 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009284 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 + " type=" + resolvedType + " args=" + service.getExtras());
9286
9287 if (caller != null) {
9288 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9289 if (callerApp == null) {
9290 throw new SecurityException(
9291 "Unable to find app for caller " + caller
9292 + " (pid=" + Binder.getCallingPid()
9293 + ") when starting service " + service);
9294 }
9295 }
9296
9297 ServiceLookupResult res =
9298 retrieveServiceLocked(service, resolvedType,
9299 callingPid, callingUid);
9300 if (res == null) {
9301 return null;
9302 }
9303 if (res.record == null) {
9304 return new ComponentName("!", res.permission != null
9305 ? res.permission : "private to package");
9306 }
9307 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009308 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9309 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009311 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 }
9313 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009314 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009315 r.lastStartId++;
9316 if (r.lastStartId < 1) {
9317 r.lastStartId = 1;
9318 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009319 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9320 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009321 r.lastActivity = SystemClock.uptimeMillis();
9322 synchronized (r.stats.getBatteryStats()) {
9323 r.stats.startRunningLocked();
9324 }
9325 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9326 return new ComponentName("!", "Service process is bad");
9327 }
9328 return r.name;
9329 }
9330 }
9331
9332 public ComponentName startService(IApplicationThread caller, Intent service,
9333 String resolvedType) {
9334 // Refuse possible leaked file descriptors
9335 if (service != null && service.hasFileDescriptors() == true) {
9336 throw new IllegalArgumentException("File descriptors passed in Intent");
9337 }
9338
9339 synchronized(this) {
9340 final int callingPid = Binder.getCallingPid();
9341 final int callingUid = Binder.getCallingUid();
9342 final long origId = Binder.clearCallingIdentity();
9343 ComponentName res = startServiceLocked(caller, service,
9344 resolvedType, callingPid, callingUid);
9345 Binder.restoreCallingIdentity(origId);
9346 return res;
9347 }
9348 }
9349
9350 ComponentName startServiceInPackage(int uid,
9351 Intent service, String resolvedType) {
9352 synchronized(this) {
9353 final long origId = Binder.clearCallingIdentity();
9354 ComponentName res = startServiceLocked(null, service,
9355 resolvedType, -1, uid);
9356 Binder.restoreCallingIdentity(origId);
9357 return res;
9358 }
9359 }
9360
9361 public int stopService(IApplicationThread caller, Intent service,
9362 String resolvedType) {
9363 // Refuse possible leaked file descriptors
9364 if (service != null && service.hasFileDescriptors() == true) {
9365 throw new IllegalArgumentException("File descriptors passed in Intent");
9366 }
9367
9368 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009369 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009370 + " type=" + resolvedType);
9371
9372 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9373 if (caller != null && callerApp == null) {
9374 throw new SecurityException(
9375 "Unable to find app for caller " + caller
9376 + " (pid=" + Binder.getCallingPid()
9377 + ") when stopping service " + service);
9378 }
9379
9380 // If this service is active, make sure it is stopped.
9381 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9382 if (r != null) {
9383 if (r.record != null) {
9384 synchronized (r.record.stats.getBatteryStats()) {
9385 r.record.stats.stopRunningLocked();
9386 }
9387 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009388 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 final long origId = Binder.clearCallingIdentity();
9390 bringDownServiceLocked(r.record, false);
9391 Binder.restoreCallingIdentity(origId);
9392 return 1;
9393 }
9394 return -1;
9395 }
9396 }
9397
9398 return 0;
9399 }
9400
9401 public IBinder peekService(Intent service, String resolvedType) {
9402 // Refuse possible leaked file descriptors
9403 if (service != null && service.hasFileDescriptors() == true) {
9404 throw new IllegalArgumentException("File descriptors passed in Intent");
9405 }
9406
9407 IBinder ret = null;
9408
9409 synchronized(this) {
9410 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9411
9412 if (r != null) {
9413 // r.record is null if findServiceLocked() failed the caller permission check
9414 if (r.record == null) {
9415 throw new SecurityException(
9416 "Permission Denial: Accessing service " + r.record.name
9417 + " from pid=" + Binder.getCallingPid()
9418 + ", uid=" + Binder.getCallingUid()
9419 + " requires " + r.permission);
9420 }
9421 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9422 if (ib != null) {
9423 ret = ib.binder;
9424 }
9425 }
9426 }
9427
9428 return ret;
9429 }
9430
9431 public boolean stopServiceToken(ComponentName className, IBinder token,
9432 int startId) {
9433 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009434 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009435 + " " + token + " startId=" + startId);
9436 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009437 if (r != null) {
9438 if (startId >= 0) {
9439 // Asked to only stop if done with all work. Note that
9440 // to avoid leaks, we will take this as dropping all
9441 // start items up to and including this one.
9442 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9443 if (si != null) {
9444 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009445 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9446 cur.removeUriPermissionsLocked();
9447 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009448 break;
9449 }
9450 }
9451 }
9452
9453 if (r.lastStartId != startId) {
9454 return false;
9455 }
9456
9457 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009458 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009459 + " is last, but have " + r.deliveredStarts.size()
9460 + " remaining args");
9461 }
9462 }
9463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009464 synchronized (r.stats.getBatteryStats()) {
9465 r.stats.stopRunningLocked();
9466 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009467 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 }
9469 final long origId = Binder.clearCallingIdentity();
9470 bringDownServiceLocked(r, false);
9471 Binder.restoreCallingIdentity(origId);
9472 return true;
9473 }
9474 }
9475 return false;
9476 }
9477
9478 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009479 int id, Notification notification, boolean removeNotification) {
9480 final long origId = Binder.clearCallingIdentity();
9481 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482 synchronized(this) {
9483 ServiceRecord r = findServiceLocked(className, token);
9484 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009485 if (id != 0) {
9486 if (notification == null) {
9487 throw new IllegalArgumentException("null notification");
9488 }
9489 if (r.foregroundId != id) {
9490 r.cancelNotification();
9491 r.foregroundId = id;
9492 }
9493 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9494 r.foregroundNoti = notification;
9495 r.isForeground = true;
9496 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497 if (r.app != null) {
9498 updateServiceForegroundLocked(r.app, true);
9499 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009500 } else {
9501 if (r.isForeground) {
9502 r.isForeground = false;
9503 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009504 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009505 updateServiceForegroundLocked(r.app, true);
9506 }
9507 }
9508 if (removeNotification) {
9509 r.cancelNotification();
9510 r.foregroundId = 0;
9511 r.foregroundNoti = null;
9512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009513 }
9514 }
9515 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009516 } finally {
9517 Binder.restoreCallingIdentity(origId);
9518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009519 }
9520
9521 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9522 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009523 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009524 if (sr.isForeground) {
9525 anyForeground = true;
9526 break;
9527 }
9528 }
9529 if (anyForeground != proc.foregroundServices) {
9530 proc.foregroundServices = anyForeground;
9531 if (oomAdj) {
9532 updateOomAdjLocked();
9533 }
9534 }
9535 }
9536
9537 public int bindService(IApplicationThread caller, IBinder token,
9538 Intent service, String resolvedType,
9539 IServiceConnection connection, int flags) {
9540 // Refuse possible leaked file descriptors
9541 if (service != null && service.hasFileDescriptors() == true) {
9542 throw new IllegalArgumentException("File descriptors passed in Intent");
9543 }
9544
9545 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009546 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009547 + " type=" + resolvedType + " conn=" + connection.asBinder()
9548 + " flags=0x" + Integer.toHexString(flags));
9549 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9550 if (callerApp == null) {
9551 throw new SecurityException(
9552 "Unable to find app for caller " + caller
9553 + " (pid=" + Binder.getCallingPid()
9554 + ") when binding service " + service);
9555 }
9556
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009557 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009558 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009559 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009560 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009561 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 return 0;
9563 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009564 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 }
9566
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009567 int clientLabel = 0;
9568 PendingIntent clientIntent = null;
9569
9570 if (callerApp.info.uid == Process.SYSTEM_UID) {
9571 // Hacky kind of thing -- allow system stuff to tell us
9572 // what they are, so we can report this elsewhere for
9573 // others to know why certain services are running.
9574 try {
9575 clientIntent = (PendingIntent)service.getParcelableExtra(
9576 Intent.EXTRA_CLIENT_INTENT);
9577 } catch (RuntimeException e) {
9578 }
9579 if (clientIntent != null) {
9580 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9581 if (clientLabel != 0) {
9582 // There are no useful extras in the intent, trash them.
9583 // System code calling with this stuff just needs to know
9584 // this will happen.
9585 service = service.cloneFilter();
9586 }
9587 }
9588 }
9589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 ServiceLookupResult res =
9591 retrieveServiceLocked(service, resolvedType,
9592 Binder.getCallingPid(), Binder.getCallingUid());
9593 if (res == null) {
9594 return 0;
9595 }
9596 if (res.record == null) {
9597 return -1;
9598 }
9599 ServiceRecord s = res.record;
9600
9601 final long origId = Binder.clearCallingIdentity();
9602
9603 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009604 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009605 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009606 }
9607
9608 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9609 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009610 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611
9612 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009613 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9614 if (clist == null) {
9615 clist = new ArrayList<ConnectionRecord>();
9616 s.connections.put(binder, clist);
9617 }
9618 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009619 b.connections.add(c);
9620 if (activity != null) {
9621 if (activity.connections == null) {
9622 activity.connections = new HashSet<ConnectionRecord>();
9623 }
9624 activity.connections.add(c);
9625 }
9626 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009627 clist = mServiceConnections.get(binder);
9628 if (clist == null) {
9629 clist = new ArrayList<ConnectionRecord>();
9630 mServiceConnections.put(binder, clist);
9631 }
9632 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633
9634 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9635 s.lastActivity = SystemClock.uptimeMillis();
9636 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9637 return 0;
9638 }
9639 }
9640
9641 if (s.app != null) {
9642 // This could have made the service more important.
9643 updateOomAdjLocked(s.app);
9644 }
9645
Joe Onorato8a9b2202010-02-26 18:56:32 -08009646 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009647 + ": received=" + b.intent.received
9648 + " apps=" + b.intent.apps.size()
9649 + " doRebind=" + b.intent.doRebind);
9650
9651 if (s.app != null && b.intent.received) {
9652 // Service is already running, so we can immediately
9653 // publish the connection.
9654 try {
9655 c.conn.connected(s.name, b.intent.binder);
9656 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009657 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 + " to connection " + c.conn.asBinder()
9659 + " (in " + c.binding.client.processName + ")", e);
9660 }
9661
9662 // If this is the first app connected back to this binding,
9663 // and the service had previously asked to be told when
9664 // rebound, then do so.
9665 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9666 requestServiceBindingLocked(s, b.intent, true);
9667 }
9668 } else if (!b.intent.requested) {
9669 requestServiceBindingLocked(s, b.intent, false);
9670 }
9671
9672 Binder.restoreCallingIdentity(origId);
9673 }
9674
9675 return 1;
9676 }
9677
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009678 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009679 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009680 IBinder binder = c.conn.asBinder();
9681 AppBindRecord b = c.binding;
9682 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009683 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9684 if (clist != null) {
9685 clist.remove(c);
9686 if (clist.size() == 0) {
9687 s.connections.remove(binder);
9688 }
9689 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009690 b.connections.remove(c);
9691 if (c.activity != null && c.activity != skipAct) {
9692 if (c.activity.connections != null) {
9693 c.activity.connections.remove(c);
9694 }
9695 }
9696 if (b.client != skipApp) {
9697 b.client.connections.remove(c);
9698 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009699 clist = mServiceConnections.get(binder);
9700 if (clist != null) {
9701 clist.remove(c);
9702 if (clist.size() == 0) {
9703 mServiceConnections.remove(binder);
9704 }
9705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706
9707 if (b.connections.size() == 0) {
9708 b.intent.apps.remove(b.client);
9709 }
9710
Joe Onorato8a9b2202010-02-26 18:56:32 -08009711 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009712 + ": shouldUnbind=" + b.intent.hasBound);
9713 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9714 && b.intent.hasBound) {
9715 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009716 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717 updateOomAdjLocked(s.app);
9718 b.intent.hasBound = false;
9719 // Assume the client doesn't want to know about a rebind;
9720 // we will deal with that later if it asks for one.
9721 b.intent.doRebind = false;
9722 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9723 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009724 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009725 serviceDoneExecutingLocked(s, true);
9726 }
9727 }
9728
9729 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9730 bringDownServiceLocked(s, false);
9731 }
9732 }
9733
9734 public boolean unbindService(IServiceConnection connection) {
9735 synchronized (this) {
9736 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009737 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009738 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9739 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009740 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 + connection.asBinder());
9742 return false;
9743 }
9744
9745 final long origId = Binder.clearCallingIdentity();
9746
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009747 while (clist.size() > 0) {
9748 ConnectionRecord r = clist.get(0);
9749 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009751 if (r.binding.service.app != null) {
9752 // This could have made the service less important.
9753 updateOomAdjLocked(r.binding.service.app);
9754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009755 }
9756
9757 Binder.restoreCallingIdentity(origId);
9758 }
9759
9760 return true;
9761 }
9762
9763 public void publishService(IBinder token, Intent intent, IBinder service) {
9764 // Refuse possible leaked file descriptors
9765 if (intent != null && intent.hasFileDescriptors() == true) {
9766 throw new IllegalArgumentException("File descriptors passed in Intent");
9767 }
9768
9769 synchronized(this) {
9770 if (!(token instanceof ServiceRecord)) {
9771 throw new IllegalArgumentException("Invalid service token");
9772 }
9773 ServiceRecord r = (ServiceRecord)token;
9774
9775 final long origId = Binder.clearCallingIdentity();
9776
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009777 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 + " " + intent + ": " + service);
9779 if (r != null) {
9780 Intent.FilterComparison filter
9781 = new Intent.FilterComparison(intent);
9782 IntentBindRecord b = r.bindings.get(filter);
9783 if (b != null && !b.received) {
9784 b.binder = service;
9785 b.requested = true;
9786 b.received = true;
9787 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009788 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 = r.connections.values().iterator();
9790 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009791 ArrayList<ConnectionRecord> clist = it.next();
9792 for (int i=0; i<clist.size(); i++) {
9793 ConnectionRecord c = clist.get(i);
9794 if (!filter.equals(c.binding.intent.intent)) {
9795 if (DEBUG_SERVICE) Slog.v(
9796 TAG, "Not publishing to: " + c);
9797 if (DEBUG_SERVICE) Slog.v(
9798 TAG, "Bound intent: " + c.binding.intent.intent);
9799 if (DEBUG_SERVICE) Slog.v(
9800 TAG, "Published intent: " + intent);
9801 continue;
9802 }
9803 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9804 try {
9805 c.conn.connected(r.name, service);
9806 } catch (Exception e) {
9807 Slog.w(TAG, "Failure sending service " + r.name +
9808 " to connection " + c.conn.asBinder() +
9809 " (in " + c.binding.client.processName + ")", e);
9810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811 }
9812 }
9813 }
9814 }
9815
9816 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9817
9818 Binder.restoreCallingIdentity(origId);
9819 }
9820 }
9821 }
9822
9823 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9824 // Refuse possible leaked file descriptors
9825 if (intent != null && intent.hasFileDescriptors() == true) {
9826 throw new IllegalArgumentException("File descriptors passed in Intent");
9827 }
9828
9829 synchronized(this) {
9830 if (!(token instanceof ServiceRecord)) {
9831 throw new IllegalArgumentException("Invalid service token");
9832 }
9833 ServiceRecord r = (ServiceRecord)token;
9834
9835 final long origId = Binder.clearCallingIdentity();
9836
9837 if (r != null) {
9838 Intent.FilterComparison filter
9839 = new Intent.FilterComparison(intent);
9840 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009841 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 + " at " + b + ": apps="
9843 + (b != null ? b.apps.size() : 0));
9844 if (b != null) {
9845 if (b.apps.size() > 0) {
9846 // Applications have already bound since the last
9847 // unbind, so just rebind right here.
9848 requestServiceBindingLocked(r, b, true);
9849 } else {
9850 // Note to tell the service the next time there is
9851 // a new client.
9852 b.doRebind = true;
9853 }
9854 }
9855
9856 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9857
9858 Binder.restoreCallingIdentity(origId);
9859 }
9860 }
9861 }
9862
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009863 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 synchronized(this) {
9865 if (!(token instanceof ServiceRecord)) {
9866 throw new IllegalArgumentException("Invalid service token");
9867 }
9868 ServiceRecord r = (ServiceRecord)token;
9869 boolean inStopping = mStoppingServices.contains(token);
9870 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009872 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 + " with incorrect token: given " + token
9874 + ", expected " + r);
9875 return;
9876 }
9877
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009878 if (type == 1) {
9879 // This is a call from a service start... take care of
9880 // book-keeping.
9881 r.callStart = true;
9882 switch (res) {
9883 case Service.START_STICKY_COMPATIBILITY:
9884 case Service.START_STICKY: {
9885 // We are done with the associated start arguments.
9886 r.findDeliveredStart(startId, true);
9887 // Don't stop if killed.
9888 r.stopIfKilled = false;
9889 break;
9890 }
9891 case Service.START_NOT_STICKY: {
9892 // We are done with the associated start arguments.
9893 r.findDeliveredStart(startId, true);
9894 if (r.lastStartId == startId) {
9895 // There is no more work, and this service
9896 // doesn't want to hang around if killed.
9897 r.stopIfKilled = true;
9898 }
9899 break;
9900 }
9901 case Service.START_REDELIVER_INTENT: {
9902 // We'll keep this item until they explicitly
9903 // call stop for it, but keep track of the fact
9904 // that it was delivered.
9905 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9906 if (si != null) {
9907 si.deliveryCount = 0;
9908 si.doneExecutingCount++;
9909 // Don't stop if killed.
9910 r.stopIfKilled = true;
9911 }
9912 break;
9913 }
9914 default:
9915 throw new IllegalArgumentException(
9916 "Unknown service start result: " + res);
9917 }
9918 if (res == Service.START_STICKY_COMPATIBILITY) {
9919 r.callStart = false;
9920 }
9921 }
9922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 final long origId = Binder.clearCallingIdentity();
9924 serviceDoneExecutingLocked(r, inStopping);
9925 Binder.restoreCallingIdentity(origId);
9926 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009927 Slog.w(TAG, "Done executing unknown service from pid "
9928 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 }
9930 }
9931 }
9932
9933 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009934 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9935 + ": nesting=" + r.executeNesting
9936 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009937 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938 r.executeNesting--;
9939 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009940 if (DEBUG_SERVICE) Slog.v(TAG,
9941 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942 r.app.executingServices.remove(r);
9943 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009944 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9945 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9947 }
9948 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009949 if (DEBUG_SERVICE) Slog.v(TAG,
9950 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009951 mStoppingServices.remove(r);
9952 }
9953 updateOomAdjLocked(r.app);
9954 }
9955 }
9956
9957 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009958 String anrMessage = null;
9959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009960 synchronized(this) {
9961 if (proc.executingServices.size() == 0 || proc.thread == null) {
9962 return;
9963 }
9964 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9965 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9966 ServiceRecord timeout = null;
9967 long nextTime = 0;
9968 while (it.hasNext()) {
9969 ServiceRecord sr = it.next();
9970 if (sr.executingStart < maxTime) {
9971 timeout = sr;
9972 break;
9973 }
9974 if (sr.executingStart > nextTime) {
9975 nextTime = sr.executingStart;
9976 }
9977 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009978 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009979 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009980 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 } else {
9982 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9983 msg.obj = proc;
9984 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9985 }
9986 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009987
9988 if (anrMessage != null) {
9989 appNotResponding(proc, null, null, anrMessage);
9990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 }
9992
9993 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009994 // BACKUP AND RESTORE
9995 // =========================================================
9996
9997 // Cause the target app to be launched if necessary and its backup agent
9998 // instantiated. The backup agent will invoke backupAgentCreated() on the
9999 // activity manager to announce its creation.
10000 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010001 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010002 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10003
10004 synchronized(this) {
10005 // !!! TODO: currently no check here that we're already bound
10006 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10007 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10008 synchronized (stats) {
10009 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10010 }
10011
10012 BackupRecord r = new BackupRecord(ss, app, backupMode);
10013 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10014 // startProcessLocked() returns existing proc's record if it's already running
10015 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010016 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010017 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010018 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010019 return false;
10020 }
10021
10022 r.app = proc;
10023 mBackupTarget = r;
10024 mBackupAppName = app.packageName;
10025
Christopher Tate6fa95972009-06-05 18:43:55 -070010026 // Try not to kill the process during backup
10027 updateOomAdjLocked(proc);
10028
Christopher Tate181fafa2009-05-14 11:12:14 -070010029 // If the process is already attached, schedule the creation of the backup agent now.
10030 // If it is not yet live, this will be done when it attaches to the framework.
10031 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010032 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010033 try {
10034 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10035 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010036 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010037 }
10038 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010039 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010040 }
10041 // Invariants: at this point, the target app process exists and the application
10042 // is either already running or in the process of coming up. mBackupTarget and
10043 // mBackupAppName describe the app, so that when it binds back to the AM we
10044 // know that it's scheduled for a backup-agent operation.
10045 }
10046
10047 return true;
10048 }
10049
10050 // A backup agent has just come up
10051 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010052 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010053 + " = " + agent);
10054
10055 synchronized(this) {
10056 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010057 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010058 return;
10059 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010060 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010061
Dianne Hackborn06740692010-09-22 22:46:21 -070010062 long oldIdent = Binder.clearCallingIdentity();
10063 try {
10064 IBackupManager bm = IBackupManager.Stub.asInterface(
10065 ServiceManager.getService(Context.BACKUP_SERVICE));
10066 bm.agentConnected(agentPackageName, agent);
10067 } catch (RemoteException e) {
10068 // can't happen; the backup manager service is local
10069 } catch (Exception e) {
10070 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10071 e.printStackTrace();
10072 } finally {
10073 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010074 }
10075 }
10076
10077 // done with this agent
10078 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010079 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010080 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010081 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010082 return;
10083 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010084
10085 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010086 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010087 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010088 return;
10089 }
10090
Christopher Tate181fafa2009-05-14 11:12:14 -070010091 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010092 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010093 return;
10094 }
10095
Christopher Tate6fa95972009-06-05 18:43:55 -070010096 ProcessRecord proc = mBackupTarget.app;
10097 mBackupTarget = null;
10098 mBackupAppName = null;
10099
10100 // Not backing this app up any more; reset its OOM adjustment
10101 updateOomAdjLocked(proc);
10102
Christopher Tatec7b31e32009-06-10 15:49:30 -070010103 // If the app crashed during backup, 'thread' will be null here
10104 if (proc.thread != null) {
10105 try {
10106 proc.thread.scheduleDestroyBackupAgent(appInfo);
10107 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010108 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010109 e.printStackTrace();
10110 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010111 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010112 }
10113 }
10114 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 // BROADCASTS
10116 // =========================================================
10117
Josh Bartel7f208742010-02-25 11:01:44 -060010118 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119 List cur) {
10120 final ContentResolver resolver = mContext.getContentResolver();
10121 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10122 if (list == null) {
10123 return cur;
10124 }
10125 int N = list.size();
10126 for (int i=0; i<N; i++) {
10127 Intent intent = list.get(i);
10128 if (filter.match(resolver, intent, true, TAG) >= 0) {
10129 if (cur == null) {
10130 cur = new ArrayList<Intent>();
10131 }
10132 cur.add(intent);
10133 }
10134 }
10135 return cur;
10136 }
10137
10138 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010139 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 + mBroadcastsScheduled);
10141
10142 if (mBroadcastsScheduled) {
10143 return;
10144 }
10145 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10146 mBroadcastsScheduled = true;
10147 }
10148
10149 public Intent registerReceiver(IApplicationThread caller,
10150 IIntentReceiver receiver, IntentFilter filter, String permission) {
10151 synchronized(this) {
10152 ProcessRecord callerApp = null;
10153 if (caller != null) {
10154 callerApp = getRecordForAppLocked(caller);
10155 if (callerApp == null) {
10156 throw new SecurityException(
10157 "Unable to find app for caller " + caller
10158 + " (pid=" + Binder.getCallingPid()
10159 + ") when registering receiver " + receiver);
10160 }
10161 }
10162
10163 List allSticky = null;
10164
10165 // Look for any matching sticky broadcasts...
10166 Iterator actions = filter.actionsIterator();
10167 if (actions != null) {
10168 while (actions.hasNext()) {
10169 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010170 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 }
10172 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010173 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 }
10175
10176 // The first sticky in the list is returned directly back to
10177 // the client.
10178 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10179
Joe Onorato8a9b2202010-02-26 18:56:32 -080010180 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010181 + ": " + sticky);
10182
10183 if (receiver == null) {
10184 return sticky;
10185 }
10186
10187 ReceiverList rl
10188 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10189 if (rl == null) {
10190 rl = new ReceiverList(this, callerApp,
10191 Binder.getCallingPid(),
10192 Binder.getCallingUid(), receiver);
10193 if (rl.app != null) {
10194 rl.app.receivers.add(rl);
10195 } else {
10196 try {
10197 receiver.asBinder().linkToDeath(rl, 0);
10198 } catch (RemoteException e) {
10199 return sticky;
10200 }
10201 rl.linkedToDeath = true;
10202 }
10203 mRegisteredReceivers.put(receiver.asBinder(), rl);
10204 }
10205 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10206 rl.add(bf);
10207 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010208 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 }
10210 mReceiverResolver.addFilter(bf);
10211
10212 // Enqueue broadcasts for all existing stickies that match
10213 // this filter.
10214 if (allSticky != null) {
10215 ArrayList receivers = new ArrayList();
10216 receivers.add(bf);
10217
10218 int N = allSticky.size();
10219 for (int i=0; i<N; i++) {
10220 Intent intent = (Intent)allSticky.get(i);
10221 BroadcastRecord r = new BroadcastRecord(intent, null,
10222 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010223 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010224 if (mParallelBroadcasts.size() == 0) {
10225 scheduleBroadcastsLocked();
10226 }
10227 mParallelBroadcasts.add(r);
10228 }
10229 }
10230
10231 return sticky;
10232 }
10233 }
10234
10235 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010236 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237
10238 boolean doNext = false;
10239
10240 synchronized(this) {
10241 ReceiverList rl
10242 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10243 if (rl != null) {
10244 if (rl.curBroadcast != null) {
10245 BroadcastRecord r = rl.curBroadcast;
10246 doNext = finishReceiverLocked(
10247 receiver.asBinder(), r.resultCode, r.resultData,
10248 r.resultExtras, r.resultAbort, true);
10249 }
10250
10251 if (rl.app != null) {
10252 rl.app.receivers.remove(rl);
10253 }
10254 removeReceiverLocked(rl);
10255 if (rl.linkedToDeath) {
10256 rl.linkedToDeath = false;
10257 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10258 }
10259 }
10260 }
10261
10262 if (!doNext) {
10263 return;
10264 }
10265
10266 final long origId = Binder.clearCallingIdentity();
10267 processNextBroadcast(false);
10268 trimApplications();
10269 Binder.restoreCallingIdentity(origId);
10270 }
10271
10272 void removeReceiverLocked(ReceiverList rl) {
10273 mRegisteredReceivers.remove(rl.receiver.asBinder());
10274 int N = rl.size();
10275 for (int i=0; i<N; i++) {
10276 mReceiverResolver.removeFilter(rl.get(i));
10277 }
10278 }
10279
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010280 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10281 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10282 ProcessRecord r = mLruProcesses.get(i);
10283 if (r.thread != null) {
10284 try {
10285 r.thread.dispatchPackageBroadcast(cmd, packages);
10286 } catch (RemoteException ex) {
10287 }
10288 }
10289 }
10290 }
10291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 private final int broadcastIntentLocked(ProcessRecord callerApp,
10293 String callerPackage, Intent intent, String resolvedType,
10294 IIntentReceiver resultTo, int resultCode, String resultData,
10295 Bundle map, String requiredPermission,
10296 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10297 intent = new Intent(intent);
10298
Joe Onorato8a9b2202010-02-26 18:56:32 -080010299 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10301 + " ordered=" + ordered);
10302 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 }
10305
10306 // Handle special intents: if this broadcast is from the package
10307 // manager about a package being removed, we need to remove all of
10308 // its activities from the history stack.
10309 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10310 intent.getAction());
10311 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10312 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010313 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 || uidRemoved) {
10315 if (checkComponentPermission(
10316 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10317 callingPid, callingUid, -1)
10318 == PackageManager.PERMISSION_GRANTED) {
10319 if (uidRemoved) {
10320 final Bundle intentExtras = intent.getExtras();
10321 final int uid = intentExtras != null
10322 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10323 if (uid >= 0) {
10324 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10325 synchronized (bs) {
10326 bs.removeUidStatsLocked(uid);
10327 }
10328 }
10329 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010330 // If resources are unvailble just force stop all
10331 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010332 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010333 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10334 if (list != null && (list.length > 0)) {
10335 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010336 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010337 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010338 sendPackageBroadcastLocked(
10339 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010340 }
10341 } else {
10342 Uri data = intent.getData();
10343 String ssp;
10344 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10345 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10346 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010347 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010348 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010349 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10350 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10351 new String[] {ssp});
10352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 }
10354 }
10355 }
10356 } else {
10357 String msg = "Permission Denial: " + intent.getAction()
10358 + " broadcast from " + callerPackage + " (pid=" + callingPid
10359 + ", uid=" + callingUid + ")"
10360 + " requires "
10361 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010362 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 throw new SecurityException(msg);
10364 }
10365 }
10366
10367 /*
10368 * If this is the time zone changed action, queue up a message that will reset the timezone
10369 * of all currently running processes. This message will get queued up before the broadcast
10370 * happens.
10371 */
10372 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10373 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10374 }
10375
Dianne Hackborn854060af2009-07-09 18:14:31 -070010376 /*
10377 * Prevent non-system code (defined here to be non-persistent
10378 * processes) from sending protected broadcasts.
10379 */
10380 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10381 || callingUid == Process.SHELL_UID || callingUid == 0) {
10382 // Always okay.
10383 } else if (callerApp == null || !callerApp.persistent) {
10384 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010385 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010386 intent.getAction())) {
10387 String msg = "Permission Denial: not allowed to send broadcast "
10388 + intent.getAction() + " from pid="
10389 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010390 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010391 throw new SecurityException(msg);
10392 }
10393 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010394 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010395 return BROADCAST_SUCCESS;
10396 }
10397 }
10398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 // Add to the sticky list if requested.
10400 if (sticky) {
10401 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10402 callingPid, callingUid)
10403 != PackageManager.PERMISSION_GRANTED) {
10404 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10405 + callingPid + ", uid=" + callingUid
10406 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010407 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 throw new SecurityException(msg);
10409 }
10410 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010411 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 + " and enforce permission " + requiredPermission);
10413 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10414 }
10415 if (intent.getComponent() != null) {
10416 throw new SecurityException(
10417 "Sticky broadcasts can't target a specific component");
10418 }
10419 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10420 if (list == null) {
10421 list = new ArrayList<Intent>();
10422 mStickyBroadcasts.put(intent.getAction(), list);
10423 }
10424 int N = list.size();
10425 int i;
10426 for (i=0; i<N; i++) {
10427 if (intent.filterEquals(list.get(i))) {
10428 // This sticky already exists, replace it.
10429 list.set(i, new Intent(intent));
10430 break;
10431 }
10432 }
10433 if (i >= N) {
10434 list.add(new Intent(intent));
10435 }
10436 }
10437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010438 // Figure out who all will receive this broadcast.
10439 List receivers = null;
10440 List<BroadcastFilter> registeredReceivers = null;
10441 try {
10442 if (intent.getComponent() != null) {
10443 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010444 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010445 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 if (ai != null) {
10447 receivers = new ArrayList();
10448 ResolveInfo ri = new ResolveInfo();
10449 ri.activityInfo = ai;
10450 receivers.add(ri);
10451 }
10452 } else {
10453 // Need to resolve the intent to interested receivers...
10454 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10455 == 0) {
10456 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010457 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010458 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 }
Mihai Preda074edef2009-05-18 17:13:31 +020010460 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010461 }
10462 } catch (RemoteException ex) {
10463 // pm is in same process, this will never happen.
10464 }
10465
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010466 final boolean replacePending =
10467 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10468
Joe Onorato8a9b2202010-02-26 18:56:32 -080010469 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010470 + " replacePending=" + replacePending);
10471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010472 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10473 if (!ordered && NR > 0) {
10474 // If we are not serializing this broadcast, then send the
10475 // registered receivers separately so they don't wait for the
10476 // components to be launched.
10477 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10478 callerPackage, callingPid, callingUid, requiredPermission,
10479 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010480 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010481 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482 TAG, "Enqueueing parallel broadcast " + r
10483 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010484 boolean replaced = false;
10485 if (replacePending) {
10486 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10487 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010488 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010489 "***** DROPPING PARALLEL: " + intent);
10490 mParallelBroadcasts.set(i, r);
10491 replaced = true;
10492 break;
10493 }
10494 }
10495 }
10496 if (!replaced) {
10497 mParallelBroadcasts.add(r);
10498 scheduleBroadcastsLocked();
10499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 registeredReceivers = null;
10501 NR = 0;
10502 }
10503
10504 // Merge into one list.
10505 int ir = 0;
10506 if (receivers != null) {
10507 // A special case for PACKAGE_ADDED: do not allow the package
10508 // being added to see this broadcast. This prevents them from
10509 // using this as a back door to get run as soon as they are
10510 // installed. Maybe in the future we want to have a special install
10511 // broadcast or such for apps, but we'd like to deliberately make
10512 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010513 String skipPackages[] = null;
10514 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10515 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10516 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10517 Uri data = intent.getData();
10518 if (data != null) {
10519 String pkgName = data.getSchemeSpecificPart();
10520 if (pkgName != null) {
10521 skipPackages = new String[] { pkgName };
10522 }
10523 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010524 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010525 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010526 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010527 if (skipPackages != null && (skipPackages.length > 0)) {
10528 for (String skipPackage : skipPackages) {
10529 if (skipPackage != null) {
10530 int NT = receivers.size();
10531 for (int it=0; it<NT; it++) {
10532 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10533 if (curt.activityInfo.packageName.equals(skipPackage)) {
10534 receivers.remove(it);
10535 it--;
10536 NT--;
10537 }
10538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 }
10540 }
10541 }
10542
10543 int NT = receivers != null ? receivers.size() : 0;
10544 int it = 0;
10545 ResolveInfo curt = null;
10546 BroadcastFilter curr = null;
10547 while (it < NT && ir < NR) {
10548 if (curt == null) {
10549 curt = (ResolveInfo)receivers.get(it);
10550 }
10551 if (curr == null) {
10552 curr = registeredReceivers.get(ir);
10553 }
10554 if (curr.getPriority() >= curt.priority) {
10555 // Insert this broadcast record into the final list.
10556 receivers.add(it, curr);
10557 ir++;
10558 curr = null;
10559 it++;
10560 NT++;
10561 } else {
10562 // Skip to the next ResolveInfo in the final list.
10563 it++;
10564 curt = null;
10565 }
10566 }
10567 }
10568 while (ir < NR) {
10569 if (receivers == null) {
10570 receivers = new ArrayList();
10571 }
10572 receivers.add(registeredReceivers.get(ir));
10573 ir++;
10574 }
10575
10576 if ((receivers != null && receivers.size() > 0)
10577 || resultTo != null) {
10578 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10579 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010580 receivers, resultTo, resultCode, resultData, map, ordered,
10581 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010582 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 TAG, "Enqueueing ordered broadcast " + r
10584 + ": prev had " + mOrderedBroadcasts.size());
10585 if (DEBUG_BROADCAST) {
10586 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010587 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010589 boolean replaced = false;
10590 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010591 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010592 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010593 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010594 "***** DROPPING ORDERED: " + intent);
10595 mOrderedBroadcasts.set(i, r);
10596 replaced = true;
10597 break;
10598 }
10599 }
10600 }
10601 if (!replaced) {
10602 mOrderedBroadcasts.add(r);
10603 scheduleBroadcastsLocked();
10604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 }
10606
10607 return BROADCAST_SUCCESS;
10608 }
10609
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010610 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 // Refuse possible leaked file descriptors
10612 if (intent != null && intent.hasFileDescriptors() == true) {
10613 throw new IllegalArgumentException("File descriptors passed in Intent");
10614 }
10615
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010616 int flags = intent.getFlags();
10617
10618 if (!mProcessesReady) {
10619 // if the caller really truly claims to know what they're doing, go
10620 // ahead and allow the broadcast without launching any receivers
10621 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10622 intent = new Intent(intent);
10623 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10624 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10625 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10626 + " before boot completion");
10627 throw new IllegalStateException("Cannot broadcast before boot completed");
10628 }
10629 }
10630
10631 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10632 throw new IllegalArgumentException(
10633 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10634 }
10635
10636 return intent;
10637 }
10638
10639 public final int broadcastIntent(IApplicationThread caller,
10640 Intent intent, String resolvedType, IIntentReceiver resultTo,
10641 int resultCode, String resultData, Bundle map,
10642 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010643 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010644 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10647 final int callingPid = Binder.getCallingPid();
10648 final int callingUid = Binder.getCallingUid();
10649 final long origId = Binder.clearCallingIdentity();
10650 int res = broadcastIntentLocked(callerApp,
10651 callerApp != null ? callerApp.info.packageName : null,
10652 intent, resolvedType, resultTo,
10653 resultCode, resultData, map, requiredPermission, serialized,
10654 sticky, callingPid, callingUid);
10655 Binder.restoreCallingIdentity(origId);
10656 return res;
10657 }
10658 }
10659
10660 int broadcastIntentInPackage(String packageName, int uid,
10661 Intent intent, String resolvedType, IIntentReceiver resultTo,
10662 int resultCode, String resultData, Bundle map,
10663 String requiredPermission, boolean serialized, boolean sticky) {
10664 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010665 intent = verifyBroadcastLocked(intent);
10666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 final long origId = Binder.clearCallingIdentity();
10668 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10669 resultTo, resultCode, resultData, map, requiredPermission,
10670 serialized, sticky, -1, uid);
10671 Binder.restoreCallingIdentity(origId);
10672 return res;
10673 }
10674 }
10675
10676 public final void unbroadcastIntent(IApplicationThread caller,
10677 Intent intent) {
10678 // Refuse possible leaked file descriptors
10679 if (intent != null && intent.hasFileDescriptors() == true) {
10680 throw new IllegalArgumentException("File descriptors passed in Intent");
10681 }
10682
10683 synchronized(this) {
10684 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10685 != PackageManager.PERMISSION_GRANTED) {
10686 String msg = "Permission Denial: unbroadcastIntent() from pid="
10687 + Binder.getCallingPid()
10688 + ", uid=" + Binder.getCallingUid()
10689 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010690 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 throw new SecurityException(msg);
10692 }
10693 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10694 if (list != null) {
10695 int N = list.size();
10696 int i;
10697 for (i=0; i<N; i++) {
10698 if (intent.filterEquals(list.get(i))) {
10699 list.remove(i);
10700 break;
10701 }
10702 }
10703 }
10704 }
10705 }
10706
10707 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10708 String resultData, Bundle resultExtras, boolean resultAbort,
10709 boolean explicit) {
10710 if (mOrderedBroadcasts.size() == 0) {
10711 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010712 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 }
10714 return false;
10715 }
10716 BroadcastRecord r = mOrderedBroadcasts.get(0);
10717 if (r.receiver == null) {
10718 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010719 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 }
10721 return false;
10722 }
10723 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010724 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 return false;
10726 }
10727 int state = r.state;
10728 r.state = r.IDLE;
10729 if (state == r.IDLE) {
10730 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010731 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 }
10733 }
10734 r.receiver = null;
10735 r.intent.setComponent(null);
10736 if (r.curApp != null) {
10737 r.curApp.curReceiver = null;
10738 }
10739 if (r.curFilter != null) {
10740 r.curFilter.receiverList.curBroadcast = null;
10741 }
10742 r.curFilter = null;
10743 r.curApp = null;
10744 r.curComponent = null;
10745 r.curReceiver = null;
10746 mPendingBroadcast = null;
10747
10748 r.resultCode = resultCode;
10749 r.resultData = resultData;
10750 r.resultExtras = resultExtras;
10751 r.resultAbort = resultAbort;
10752
10753 // We will process the next receiver right now if this is finishing
10754 // an app receiver (which is always asynchronous) or after we have
10755 // come back from calling a receiver.
10756 return state == BroadcastRecord.APP_RECEIVE
10757 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10758 }
10759
10760 public void finishReceiver(IBinder who, int resultCode, String resultData,
10761 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010762 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010763
10764 // Refuse possible leaked file descriptors
10765 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10766 throw new IllegalArgumentException("File descriptors passed in Bundle");
10767 }
10768
10769 boolean doNext;
10770
10771 final long origId = Binder.clearCallingIdentity();
10772
10773 synchronized(this) {
10774 doNext = finishReceiverLocked(
10775 who, resultCode, resultData, resultExtras, resultAbort, true);
10776 }
10777
10778 if (doNext) {
10779 processNextBroadcast(false);
10780 }
10781 trimApplications();
10782
10783 Binder.restoreCallingIdentity(origId);
10784 }
10785
Jeff Brown4d94a762010-09-23 11:33:28 -070010786 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 if (r.nextReceiver > 0) {
10788 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10789 if (curReceiver instanceof BroadcastFilter) {
10790 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010791 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 System.identityHashCode(r),
10793 r.intent.getAction(),
10794 r.nextReceiver - 1,
10795 System.identityHashCode(bf));
10796 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010797 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 System.identityHashCode(r),
10799 r.intent.getAction(),
10800 r.nextReceiver - 1,
10801 ((ResolveInfo)curReceiver).toString());
10802 }
10803 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010804 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010806 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 System.identityHashCode(r),
10808 r.intent.getAction(),
10809 r.nextReceiver,
10810 "NONE");
10811 }
10812 }
10813
Jeff Brown4d94a762010-09-23 11:33:28 -070010814 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10815 if (! mPendingBroadcastTimeoutMessage) {
10816 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10817 mHandler.sendMessageAtTime(msg, timeoutTime);
10818 mPendingBroadcastTimeoutMessage = true;
10819 }
10820 }
10821
10822 private final void cancelBroadcastTimeoutLocked() {
10823 if (mPendingBroadcastTimeoutMessage) {
10824 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10825 mPendingBroadcastTimeoutMessage = false;
10826 }
10827 }
10828
10829 private final void broadcastTimeoutLocked(boolean fromMsg) {
10830 if (fromMsg) {
10831 mPendingBroadcastTimeoutMessage = false;
10832 }
10833
10834 if (mOrderedBroadcasts.size() == 0) {
10835 return;
10836 }
10837
10838 long now = SystemClock.uptimeMillis();
10839 BroadcastRecord r = mOrderedBroadcasts.get(0);
10840 if (fromMsg) {
10841 if (mDidDexOpt) {
10842 // Delay timeouts until dexopt finishes.
10843 mDidDexOpt = false;
10844 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10845 setBroadcastTimeoutLocked(timeoutTime);
10846 return;
10847 }
10848 if (! mProcessesReady) {
10849 // Only process broadcast timeouts if the system is ready. That way
10850 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10851 // to do heavy lifting for system up.
10852 return;
10853 }
10854
10855 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10856 if (timeoutTime > now) {
10857 // We can observe premature timeouts because we do not cancel and reset the
10858 // broadcast timeout message after each receiver finishes. Instead, we set up
10859 // an initial timeout then kick it down the road a little further as needed
10860 // when it expires.
10861 if (DEBUG_BROADCAST) Slog.v(TAG,
10862 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10863 + timeoutTime);
10864 setBroadcastTimeoutLocked(timeoutTime);
10865 return;
10866 }
10867 }
10868
10869 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10870 + ", started " + (now - r.receiverTime) + "ms ago");
10871 r.receiverTime = now;
10872 r.anrCount++;
10873
10874 // Current receiver has passed its expiration date.
10875 if (r.nextReceiver <= 0) {
10876 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10877 return;
10878 }
10879
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010880 ProcessRecord app = null;
10881 String anrMessage = null;
10882
Jeff Brown4d94a762010-09-23 11:33:28 -070010883 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10884 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10885 logBroadcastReceiverDiscardLocked(r);
10886 if (curReceiver instanceof BroadcastFilter) {
10887 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10888 if (bf.receiverList.pid != 0
10889 && bf.receiverList.pid != MY_PID) {
10890 synchronized (this.mPidsSelfLocked) {
10891 app = this.mPidsSelfLocked.get(
10892 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010895 } else {
10896 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010897 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010898
Jeff Brown4d94a762010-09-23 11:33:28 -070010899 if (app != null) {
10900 anrMessage = "Broadcast of " + r.intent.toString();
10901 }
10902
10903 if (mPendingBroadcast == r) {
10904 mPendingBroadcast = null;
10905 }
10906
10907 // Move on to the next receiver.
10908 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10909 r.resultExtras, r.resultAbort, true);
10910 scheduleBroadcastsLocked();
10911
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010912 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010913 // Post the ANR to the handler since we do not want to process ANRs while
10914 // potentially holding our lock.
10915 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 }
10918
10919 private final void processCurBroadcastLocked(BroadcastRecord r,
10920 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010921 if (DEBUG_BROADCAST) Slog.v(TAG,
10922 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 if (app.thread == null) {
10924 throw new RemoteException();
10925 }
10926 r.receiver = app.thread.asBinder();
10927 r.curApp = app;
10928 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010929 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930
10931 // Tell the application to launch this receiver.
10932 r.intent.setComponent(r.curComponent);
10933
10934 boolean started = false;
10935 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010936 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 "Delivering to component " + r.curComponent
10938 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010939 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10941 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010942 if (DEBUG_BROADCAST) Slog.v(TAG,
10943 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 started = true;
10945 } finally {
10946 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010947 if (DEBUG_BROADCAST) Slog.v(TAG,
10948 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949 r.receiver = null;
10950 r.curApp = null;
10951 app.curReceiver = null;
10952 }
10953 }
10954
10955 }
10956
Jeff Brown4d94a762010-09-23 11:33:28 -070010957 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010958 Intent intent, int resultCode, String data, Bundle extras,
10959 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010960 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 if (app != null && app.thread != null) {
10962 // If we have an app thread, do the call through that so it is
10963 // correctly ordered with other one-way calls.
10964 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010965 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010967 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 }
10969 }
10970
Jeff Brown4d94a762010-09-23 11:33:28 -070010971 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010972 BroadcastFilter filter, boolean ordered) {
10973 boolean skip = false;
10974 if (filter.requiredPermission != null) {
10975 int perm = checkComponentPermission(filter.requiredPermission,
10976 r.callingPid, r.callingUid, -1);
10977 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010978 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 + r.intent.toString()
10980 + " from " + r.callerPackage + " (pid="
10981 + r.callingPid + ", uid=" + r.callingUid + ")"
10982 + " requires " + filter.requiredPermission
10983 + " due to registered receiver " + filter);
10984 skip = true;
10985 }
10986 }
10987 if (r.requiredPermission != null) {
10988 int perm = checkComponentPermission(r.requiredPermission,
10989 filter.receiverList.pid, filter.receiverList.uid, -1);
10990 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010991 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 + r.intent.toString()
10993 + " to " + filter.receiverList.app
10994 + " (pid=" + filter.receiverList.pid
10995 + ", uid=" + filter.receiverList.uid + ")"
10996 + " requires " + r.requiredPermission
10997 + " due to sender " + r.callerPackage
10998 + " (uid " + r.callingUid + ")");
10999 skip = true;
11000 }
11001 }
11002
11003 if (!skip) {
11004 // If this is not being sent as an ordered broadcast, then we
11005 // don't want to touch the fields that keep track of the current
11006 // state of ordered broadcasts.
11007 if (ordered) {
11008 r.receiver = filter.receiverList.receiver.asBinder();
11009 r.curFilter = filter;
11010 filter.receiverList.curBroadcast = r;
11011 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011012 if (filter.receiverList.app != null) {
11013 // Bump hosting application to no longer be in background
11014 // scheduling class. Note that we can't do that if there
11015 // isn't an app... but we can only be in that case for
11016 // things that directly call the IActivityManager API, which
11017 // are already core system stuff so don't matter for this.
11018 r.curApp = filter.receiverList.app;
11019 filter.receiverList.app.curReceiver = r;
11020 updateOomAdjLocked();
11021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 }
11023 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011024 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011026 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011027 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011029 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011031 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011032 if (ordered) {
11033 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11034 }
11035 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011036 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 if (ordered) {
11038 r.receiver = null;
11039 r.curFilter = null;
11040 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011041 if (filter.receiverList.app != null) {
11042 filter.receiverList.app.curReceiver = null;
11043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 }
11045 }
11046 }
11047 }
11048
Dianne Hackborn12527f92009-11-11 17:39:50 -080011049 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11050 if (r.callingUid < 0) {
11051 // This was from a registerReceiver() call; ignore it.
11052 return;
11053 }
11054 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11055 MAX_BROADCAST_HISTORY-1);
11056 r.finishTime = SystemClock.uptimeMillis();
11057 mBroadcastHistory[0] = r;
11058 }
11059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 private final void processNextBroadcast(boolean fromMsg) {
11061 synchronized(this) {
11062 BroadcastRecord r;
11063
Joe Onorato8a9b2202010-02-26 18:56:32 -080011064 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011066 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067
11068 updateCpuStats();
11069
11070 if (fromMsg) {
11071 mBroadcastsScheduled = false;
11072 }
11073
11074 // First, deliver any non-serialized broadcasts right away.
11075 while (mParallelBroadcasts.size() > 0) {
11076 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011077 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011078 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011079 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011080 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 for (int i=0; i<N; i++) {
11082 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011083 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011084 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011086 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011088 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011089 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011090 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 }
11092
11093 // Now take care of the next serialized one...
11094
11095 // If we are waiting for a process to come up to handle the next
11096 // broadcast, then do nothing at this point. Just in case, we
11097 // check that the process we're waiting for still exists.
11098 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011099 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011100 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011101 + mPendingBroadcast.curApp);
11102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103
11104 boolean isDead;
11105 synchronized (mPidsSelfLocked) {
11106 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11107 }
11108 if (!isDead) {
11109 // It's still alive, so keep waiting
11110 return;
11111 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011112 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011114 mPendingBroadcast.state = BroadcastRecord.IDLE;
11115 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 mPendingBroadcast = null;
11117 }
11118 }
11119
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011120 boolean looped = false;
11121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 do {
11123 if (mOrderedBroadcasts.size() == 0) {
11124 // No more broadcasts pending, so all done!
11125 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011126 if (looped) {
11127 // If we had finished the last ordered broadcast, then
11128 // make sure all processes have correct oom and sched
11129 // adjustments.
11130 updateOomAdjLocked();
11131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132 return;
11133 }
11134 r = mOrderedBroadcasts.get(0);
11135 boolean forceReceive = false;
11136
11137 // Ensure that even if something goes awry with the timeout
11138 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011139 // and continue to make progress.
11140 //
11141 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011142 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011143 // one time heavy lifting after system upgrades and can take
11144 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011146 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011147 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 if ((numReceivers > 0) &&
11149 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011150 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 + " now=" + now
11152 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011153 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 + " intent=" + r.intent
11155 + " numReceivers=" + numReceivers
11156 + " nextReceiver=" + r.nextReceiver
11157 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011158 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 forceReceive = true;
11160 r.state = BroadcastRecord.IDLE;
11161 }
11162 }
11163
11164 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011165 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 "processNextBroadcast() called when not idle (state="
11167 + r.state + ")");
11168 return;
11169 }
11170
11171 if (r.receivers == null || r.nextReceiver >= numReceivers
11172 || r.resultAbort || forceReceive) {
11173 // No more receivers for this broadcast! Send the final
11174 // result if requested...
11175 if (r.resultTo != null) {
11176 try {
11177 if (DEBUG_BROADCAST) {
11178 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011179 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 + " seq=" + seq + " app=" + r.callerApp);
11181 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011182 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011184 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011186 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 }
11188 }
11189
Joe Onorato8a9b2202010-02-26 18:56:32 -080011190 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011191 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192
Joe Onorato8a9b2202010-02-26 18:56:32 -080011193 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011194 + r);
11195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011196 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011197 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 mOrderedBroadcasts.remove(0);
11199 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011200 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011201 continue;
11202 }
11203 } while (r == null);
11204
11205 // Get the next receiver...
11206 int recIdx = r.nextReceiver++;
11207
11208 // Keep track of when this receiver started, and make sure there
11209 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011210 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011212 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011213
Joe Onorato8a9b2202010-02-26 18:56:32 -080011214 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011215 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011216 }
11217 if (! mPendingBroadcastTimeoutMessage) {
11218 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011220 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11221 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222 }
11223
11224 Object nextReceiver = r.receivers.get(recIdx);
11225 if (nextReceiver instanceof BroadcastFilter) {
11226 // Simple case: this is a registered receiver who gets
11227 // a direct call.
11228 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011229 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011230 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011232 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 if (r.receiver == null || !r.ordered) {
11234 // The receiver has already finished, so schedule to
11235 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011236 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11237 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 r.state = BroadcastRecord.IDLE;
11239 scheduleBroadcastsLocked();
11240 }
11241 return;
11242 }
11243
11244 // Hard case: need to instantiate the receiver, possibly
11245 // starting its application process to host it.
11246
11247 ResolveInfo info =
11248 (ResolveInfo)nextReceiver;
11249
11250 boolean skip = false;
11251 int perm = checkComponentPermission(info.activityInfo.permission,
11252 r.callingPid, r.callingUid,
11253 info.activityInfo.exported
11254 ? -1 : info.activityInfo.applicationInfo.uid);
11255 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011256 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 + r.intent.toString()
11258 + " from " + r.callerPackage + " (pid=" + r.callingPid
11259 + ", uid=" + r.callingUid + ")"
11260 + " requires " + info.activityInfo.permission
11261 + " due to receiver " + info.activityInfo.packageName
11262 + "/" + info.activityInfo.name);
11263 skip = true;
11264 }
11265 if (r.callingUid != Process.SYSTEM_UID &&
11266 r.requiredPermission != null) {
11267 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011268 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 checkPermission(r.requiredPermission,
11270 info.activityInfo.applicationInfo.packageName);
11271 } catch (RemoteException e) {
11272 perm = PackageManager.PERMISSION_DENIED;
11273 }
11274 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011275 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 + r.intent + " to "
11277 + info.activityInfo.applicationInfo.packageName
11278 + " requires " + r.requiredPermission
11279 + " due to sender " + r.callerPackage
11280 + " (uid " + r.callingUid + ")");
11281 skip = true;
11282 }
11283 }
11284 if (r.curApp != null && r.curApp.crashing) {
11285 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011286 if (DEBUG_BROADCAST) Slog.v(TAG,
11287 "Skipping deliver ordered " + r + " to " + r.curApp
11288 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 skip = true;
11290 }
11291
11292 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011293 if (DEBUG_BROADCAST) Slog.v(TAG,
11294 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 r.receiver = null;
11296 r.curFilter = null;
11297 r.state = BroadcastRecord.IDLE;
11298 scheduleBroadcastsLocked();
11299 return;
11300 }
11301
11302 r.state = BroadcastRecord.APP_RECEIVE;
11303 String targetProcess = info.activityInfo.processName;
11304 r.curComponent = new ComponentName(
11305 info.activityInfo.applicationInfo.packageName,
11306 info.activityInfo.name);
11307 r.curReceiver = info.activityInfo;
11308
11309 // Is this receiver's application already running?
11310 ProcessRecord app = getProcessRecordLocked(targetProcess,
11311 info.activityInfo.applicationInfo.uid);
11312 if (app != null && app.thread != null) {
11313 try {
11314 processCurBroadcastLocked(r, app);
11315 return;
11316 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011317 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 + r.curComponent, e);
11319 }
11320
11321 // If a dead object exception was thrown -- fall through to
11322 // restart the application.
11323 }
11324
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011325 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011326 if (DEBUG_BROADCAST) Slog.v(TAG,
11327 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 if ((r.curApp=startProcessLocked(targetProcess,
11329 info.activityInfo.applicationInfo, true,
11330 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011331 "broadcast", r.curComponent,
11332 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11333 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 // Ah, this recipient is unavailable. Finish it if necessary,
11335 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011336 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 + info.activityInfo.applicationInfo.packageName + "/"
11338 + info.activityInfo.applicationInfo.uid + " for broadcast "
11339 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011340 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11342 r.resultExtras, r.resultAbort, true);
11343 scheduleBroadcastsLocked();
11344 r.state = BroadcastRecord.IDLE;
11345 return;
11346 }
11347
11348 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011349 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 }
11351 }
11352
11353 // =========================================================
11354 // INSTRUMENTATION
11355 // =========================================================
11356
11357 public boolean startInstrumentation(ComponentName className,
11358 String profileFile, int flags, Bundle arguments,
11359 IInstrumentationWatcher watcher) {
11360 // Refuse possible leaked file descriptors
11361 if (arguments != null && arguments.hasFileDescriptors()) {
11362 throw new IllegalArgumentException("File descriptors passed in Bundle");
11363 }
11364
11365 synchronized(this) {
11366 InstrumentationInfo ii = null;
11367 ApplicationInfo ai = null;
11368 try {
11369 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011370 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011371 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011372 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 } catch (PackageManager.NameNotFoundException e) {
11374 }
11375 if (ii == null) {
11376 reportStartInstrumentationFailure(watcher, className,
11377 "Unable to find instrumentation info for: " + className);
11378 return false;
11379 }
11380 if (ai == null) {
11381 reportStartInstrumentationFailure(watcher, className,
11382 "Unable to find instrumentation target package: " + ii.targetPackage);
11383 return false;
11384 }
11385
11386 int match = mContext.getPackageManager().checkSignatures(
11387 ii.targetPackage, ii.packageName);
11388 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11389 String msg = "Permission Denial: starting instrumentation "
11390 + className + " from pid="
11391 + Binder.getCallingPid()
11392 + ", uid=" + Binder.getCallingPid()
11393 + " not allowed because package " + ii.packageName
11394 + " does not have a signature matching the target "
11395 + ii.targetPackage;
11396 reportStartInstrumentationFailure(watcher, className, msg);
11397 throw new SecurityException(msg);
11398 }
11399
11400 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011401 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 ProcessRecord app = addAppLocked(ai);
11403 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011404 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 app.instrumentationProfileFile = profileFile;
11406 app.instrumentationArguments = arguments;
11407 app.instrumentationWatcher = watcher;
11408 app.instrumentationResultClass = className;
11409 Binder.restoreCallingIdentity(origId);
11410 }
11411
11412 return true;
11413 }
11414
11415 /**
11416 * Report errors that occur while attempting to start Instrumentation. Always writes the
11417 * error to the logs, but if somebody is watching, send the report there too. This enables
11418 * the "am" command to report errors with more information.
11419 *
11420 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11421 * @param cn The component name of the instrumentation.
11422 * @param report The error report.
11423 */
11424 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11425 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011426 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 try {
11428 if (watcher != null) {
11429 Bundle results = new Bundle();
11430 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11431 results.putString("Error", report);
11432 watcher.instrumentationStatus(cn, -1, results);
11433 }
11434 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011435 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 }
11437 }
11438
11439 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11440 if (app.instrumentationWatcher != null) {
11441 try {
11442 // NOTE: IInstrumentationWatcher *must* be oneway here
11443 app.instrumentationWatcher.instrumentationFinished(
11444 app.instrumentationClass,
11445 resultCode,
11446 results);
11447 } catch (RemoteException e) {
11448 }
11449 }
11450 app.instrumentationWatcher = null;
11451 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011452 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 app.instrumentationProfileFile = null;
11454 app.instrumentationArguments = null;
11455
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011456 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 }
11458
11459 public void finishInstrumentation(IApplicationThread target,
11460 int resultCode, Bundle results) {
11461 // Refuse possible leaked file descriptors
11462 if (results != null && results.hasFileDescriptors()) {
11463 throw new IllegalArgumentException("File descriptors passed in Intent");
11464 }
11465
11466 synchronized(this) {
11467 ProcessRecord app = getRecordForAppLocked(target);
11468 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011469 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 return;
11471 }
11472 final long origId = Binder.clearCallingIdentity();
11473 finishInstrumentationLocked(app, resultCode, results);
11474 Binder.restoreCallingIdentity(origId);
11475 }
11476 }
11477
11478 // =========================================================
11479 // CONFIGURATION
11480 // =========================================================
11481
11482 public ConfigurationInfo getDeviceConfigurationInfo() {
11483 ConfigurationInfo config = new ConfigurationInfo();
11484 synchronized (this) {
11485 config.reqTouchScreen = mConfiguration.touchscreen;
11486 config.reqKeyboardType = mConfiguration.keyboard;
11487 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011488 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11489 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11491 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011492 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11493 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011494 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11495 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011496 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011497 }
11498 return config;
11499 }
11500
11501 public Configuration getConfiguration() {
11502 Configuration ci;
11503 synchronized(this) {
11504 ci = new Configuration(mConfiguration);
11505 }
11506 return ci;
11507 }
11508
11509 public void updateConfiguration(Configuration values) {
11510 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11511 "updateConfiguration()");
11512
11513 synchronized(this) {
11514 if (values == null && mWindowManager != null) {
11515 // sentinel: fetch the current configuration from the window manager
11516 values = mWindowManager.computeNewConfiguration();
11517 }
11518
11519 final long origId = Binder.clearCallingIdentity();
11520 updateConfigurationLocked(values, null);
11521 Binder.restoreCallingIdentity(origId);
11522 }
11523 }
11524
11525 /**
11526 * Do either or both things: (1) change the current configuration, and (2)
11527 * make sure the given activity is running with the (now) current
11528 * configuration. Returns true if the activity has been left running, or
11529 * false if <var>starting</var> is being destroyed to match the new
11530 * configuration.
11531 */
11532 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011533 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 int changes = 0;
11535
11536 boolean kept = true;
11537
11538 if (values != null) {
11539 Configuration newConfig = new Configuration(mConfiguration);
11540 changes = newConfig.updateFrom(values);
11541 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011542 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011543 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 }
11545
Doug Zongker2bec3d42009-12-04 12:52:44 -080011546 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547
11548 if (values.locale != null) {
11549 saveLocaleLocked(values.locale,
11550 !values.locale.equals(mConfiguration.locale),
11551 values.userSetLocale);
11552 }
11553
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011554 mConfigurationSeq++;
11555 if (mConfigurationSeq <= 0) {
11556 mConfigurationSeq = 1;
11557 }
11558 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011560 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011561
11562 AttributeCache ac = AttributeCache.instance();
11563 if (ac != null) {
11564 ac.updateConfiguration(mConfiguration);
11565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011567 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11568 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11569 msg.obj = new Configuration(mConfiguration);
11570 mHandler.sendMessage(msg);
11571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011573 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11574 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 try {
11576 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011577 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011578 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011579 app.thread.scheduleConfigurationChanged(mConfiguration);
11580 }
11581 } catch (Exception e) {
11582 }
11583 }
11584 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011585 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11586 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011587 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11588 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011589 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11590 broadcastIntentLocked(null, null,
11591 new Intent(Intent.ACTION_LOCALE_CHANGED),
11592 null, null, 0, null, null,
11593 null, false, false, MY_PID, Process.SYSTEM_UID);
11594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595 }
11596 }
11597
11598 if (changes != 0 && starting == null) {
11599 // If the configuration changed, and the caller is not already
11600 // in the process of starting an activity, then find the top
11601 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011602 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 }
11604
11605 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011606 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011607 if (kept) {
11608 // If this didn't result in the starting activity being
11609 // destroyed, then we need to make sure at this point that all
11610 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011613 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 }
11615 }
11616
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011617 if (values != null && mWindowManager != null) {
11618 mWindowManager.setNewConfiguration(mConfiguration);
11619 }
11620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 return kept;
11622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011623
11624 /**
11625 * Save the locale. You must be inside a synchronized (this) block.
11626 */
11627 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11628 if(isDiff) {
11629 SystemProperties.set("user.language", l.getLanguage());
11630 SystemProperties.set("user.region", l.getCountry());
11631 }
11632
11633 if(isPersist) {
11634 SystemProperties.set("persist.sys.language", l.getLanguage());
11635 SystemProperties.set("persist.sys.country", l.getCountry());
11636 SystemProperties.set("persist.sys.localevar", l.getVariant());
11637 }
11638 }
11639
11640 // =========================================================
11641 // LIFETIME MANAGEMENT
11642 // =========================================================
11643
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011644 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11645 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011646 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011647 // This adjustment has already been computed. If we are calling
11648 // from the top, we may have already computed our adjustment with
11649 // an earlier hidden adjustment that isn't really for us... if
11650 // so, use the new hidden adjustment.
11651 if (!recursed && app.hidden) {
11652 app.curAdj = hiddenAdj;
11653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011654 return app.curAdj;
11655 }
11656
11657 if (app.thread == null) {
11658 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011659 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011660 return (app.curAdj=EMPTY_APP_ADJ);
11661 }
11662
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011663 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11664 // The max adjustment doesn't allow this app to be anything
11665 // below foreground, so it is not worth doing work for it.
11666 app.adjType = "fixed";
11667 app.adjSeq = mAdjSeq;
11668 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011669 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011670 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11671 return (app.curAdj=app.maxAdj);
11672 }
11673
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011674 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011675 app.adjSource = null;
11676 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011677 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011678 app.empty = false;
11679 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680
The Android Open Source Project4df24232009-03-05 14:34:35 -080011681 // Determine the importance of the process, starting with most
11682 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011684 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011685 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011686 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 // The last app on the list is the foreground app.
11688 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011689 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011690 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011691 } else if (app.instrumentationClass != null) {
11692 // Don't want to kill running instrumentation.
11693 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011694 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011695 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 } else if (app.curReceiver != null ||
11697 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11698 // An app that is currently receiving a broadcast also
11699 // counts as being in the foreground.
11700 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011701 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011702 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011703 } else if (app.executingServices.size() > 0) {
11704 // An app that is currently executing a service callback also
11705 // counts as being in the foreground.
11706 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011707 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011708 app.adjType = "exec-service";
11709 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011711 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011712 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011713 app.adjType = "foreground-service";
11714 } else if (app.forcingToForeground != null) {
11715 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011716 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011717 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011718 app.adjType = "force-foreground";
11719 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011720 } else if (app == mHeavyWeightProcess) {
11721 // We don't want to kill the current heavy-weight process.
11722 adj = HEAVY_WEIGHT_APP_ADJ;
11723 schedGroup = Process.THREAD_GROUP_DEFAULT;
11724 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011725 } else if (app == mHomeProcess) {
11726 // This process is hosting what we currently consider to be the
11727 // home app, so we don't want to let it go into the background.
11728 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011729 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011730 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 } else if ((N=app.activities.size()) != 0) {
11732 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011733 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011734 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011735 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011736 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011737 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011739 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011740 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011741 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011743 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011744 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 break;
11746 }
11747 }
11748 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011749 // A very not-needed process. If this is lower in the lru list,
11750 // we will push it in to the empty bucket.
11751 app.hidden = true;
11752 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011753 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011754 adj = hiddenAdj;
11755 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011756 }
11757
Joe Onorato8a9b2202010-02-26 18:56:32 -080011758 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011759
The Android Open Source Project4df24232009-03-05 14:34:35 -080011760 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 // there are applications dependent on our services or providers, but
11762 // this gives us a baseline and makes sure we don't get into an
11763 // infinite recursion.
11764 app.adjSeq = mAdjSeq;
11765 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766
Christopher Tate6fa95972009-06-05 18:43:55 -070011767 if (mBackupTarget != null && app == mBackupTarget.app) {
11768 // If possible we want to avoid killing apps while they're being backed up
11769 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011770 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011771 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011772 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011773 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011774 }
11775 }
11776
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011777 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11778 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 final long now = SystemClock.uptimeMillis();
11780 // This process is more important if the top activity is
11781 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011782 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011783 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011784 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 if (s.startRequested) {
11786 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11787 // This service has seen some activity within
11788 // recent memory, so we will keep its process ahead
11789 // of the background processes.
11790 if (adj > SECONDARY_SERVER_ADJ) {
11791 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011792 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011793 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 }
11795 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011796 // If we have let the service slide into the background
11797 // state, still have some text describing what it is doing
11798 // even though the service no longer has an impact.
11799 if (adj > SECONDARY_SERVER_ADJ) {
11800 app.adjType = "started-bg-services";
11801 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011802 // Don't kill this process because it is doing work; it
11803 // has said it is doing work.
11804 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011805 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011806 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11807 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011808 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 = s.connections.values().iterator();
11810 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011811 ArrayList<ConnectionRecord> clist = kt.next();
11812 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11813 // XXX should compute this based on the max of
11814 // all connected clients.
11815 ConnectionRecord cr = clist.get(i);
11816 if (cr.binding.client == app) {
11817 // Binding to ourself is not interesting.
11818 continue;
11819 }
11820 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11821 ProcessRecord client = cr.binding.client;
11822 int myHiddenAdj = hiddenAdj;
11823 if (myHiddenAdj > client.hiddenAdj) {
11824 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11825 myHiddenAdj = client.hiddenAdj;
11826 } else {
11827 myHiddenAdj = VISIBLE_APP_ADJ;
11828 }
11829 }
11830 int clientAdj = computeOomAdjLocked(
11831 client, myHiddenAdj, TOP_APP, true);
11832 if (adj > clientAdj) {
11833 adj = clientAdj >= VISIBLE_APP_ADJ
11834 ? clientAdj : VISIBLE_APP_ADJ;
11835 if (!client.hidden) {
11836 app.hidden = false;
11837 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011838 if (client.keeping) {
11839 app.keeping = true;
11840 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011841 app.adjType = "service";
11842 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11843 .REASON_SERVICE_IN_USE;
11844 app.adjSource = cr.binding.client;
11845 app.adjTarget = s.name;
11846 }
11847 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11848 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11849 schedGroup = Process.THREAD_GROUP_DEFAULT;
11850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011851 }
11852 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011853 ActivityRecord a = cr.activity;
11854 //if (a != null) {
11855 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11856 //}
11857 if (a != null && adj > FOREGROUND_APP_ADJ &&
11858 (a.state == ActivityState.RESUMED
11859 || a.state == ActivityState.PAUSING)) {
11860 adj = FOREGROUND_APP_ADJ;
11861 schedGroup = Process.THREAD_GROUP_DEFAULT;
11862 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011863 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011864 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11865 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011866 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011867 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011869 }
11870 }
11871 }
11872 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011873
Dianne Hackborn287952c2010-09-22 22:34:31 -070011874 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011875 // would like to avoid killing it unless it would prevent the current
11876 // application from running. By default we put the process in
11877 // with the rest of the background processes; as we scan through
11878 // its services we may bump it up from there.
11879 if (adj > hiddenAdj) {
11880 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011881 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011882 app.adjType = "bg-services";
11883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011884 }
11885
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011886 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11887 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011888 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011889 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11890 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011891 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 if (cpr.clients.size() != 0) {
11893 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11894 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11895 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011896 if (client == app) {
11897 // Being our own client is not interesting.
11898 continue;
11899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011900 int myHiddenAdj = hiddenAdj;
11901 if (myHiddenAdj > client.hiddenAdj) {
11902 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11903 myHiddenAdj = client.hiddenAdj;
11904 } else {
11905 myHiddenAdj = FOREGROUND_APP_ADJ;
11906 }
11907 }
11908 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011909 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 if (adj > clientAdj) {
11911 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011912 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011913 if (!client.hidden) {
11914 app.hidden = false;
11915 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011916 if (client.keeping) {
11917 app.keeping = true;
11918 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011919 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011920 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11921 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011922 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011923 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011924 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011925 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11926 schedGroup = Process.THREAD_GROUP_DEFAULT;
11927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011928 }
11929 }
11930 // If the provider has external (non-framework) process
11931 // dependencies, ensure that its adjustment is at least
11932 // FOREGROUND_APP_ADJ.
11933 if (cpr.externals != 0) {
11934 if (adj > FOREGROUND_APP_ADJ) {
11935 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011936 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011937 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011938 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011939 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011940 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011941 }
11942 }
11943 }
11944 }
11945
11946 app.curRawAdj = adj;
11947
Joe Onorato8a9b2202010-02-26 18:56:32 -080011948 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011949 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11950 if (adj > app.maxAdj) {
11951 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011952 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011953 schedGroup = Process.THREAD_GROUP_DEFAULT;
11954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011956 if (adj < HIDDEN_APP_MIN_ADJ) {
11957 app.keeping = true;
11958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011959
11960 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011961 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011963 return adj;
11964 }
11965
11966 /**
11967 * Ask a given process to GC right now.
11968 */
11969 final void performAppGcLocked(ProcessRecord app) {
11970 try {
11971 app.lastRequestedGc = SystemClock.uptimeMillis();
11972 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011973 if (app.reportLowMemory) {
11974 app.reportLowMemory = false;
11975 app.thread.scheduleLowMemory();
11976 } else {
11977 app.thread.processInBackground();
11978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 }
11980 } catch (Exception e) {
11981 // whatever.
11982 }
11983 }
11984
11985 /**
11986 * Returns true if things are idle enough to perform GCs.
11987 */
Josh Bartel7f208742010-02-25 11:01:44 -060011988 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011989 return mParallelBroadcasts.size() == 0
11990 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011991 && (mSleeping || (mMainStack.mResumedActivity != null &&
11992 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011993 }
11994
11995 /**
11996 * Perform GCs on all processes that are waiting for it, but only
11997 * if things are idle.
11998 */
11999 final void performAppGcsLocked() {
12000 final int N = mProcessesToGc.size();
12001 if (N <= 0) {
12002 return;
12003 }
Josh Bartel7f208742010-02-25 11:01:44 -060012004 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012005 while (mProcessesToGc.size() > 0) {
12006 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012007 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012008 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12009 <= SystemClock.uptimeMillis()) {
12010 // To avoid spamming the system, we will GC processes one
12011 // at a time, waiting a few seconds between each.
12012 performAppGcLocked(proc);
12013 scheduleAppGcsLocked();
12014 return;
12015 } else {
12016 // It hasn't been long enough since we last GCed this
12017 // process... put it in the list to wait for its time.
12018 addProcessToGcListLocked(proc);
12019 break;
12020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012021 }
12022 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012023
12024 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 }
12026 }
12027
12028 /**
12029 * If all looks good, perform GCs on all processes waiting for them.
12030 */
12031 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012032 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 performAppGcsLocked();
12034 return;
12035 }
12036 // Still not idle, wait some more.
12037 scheduleAppGcsLocked();
12038 }
12039
12040 /**
12041 * Schedule the execution of all pending app GCs.
12042 */
12043 final void scheduleAppGcsLocked() {
12044 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012045
12046 if (mProcessesToGc.size() > 0) {
12047 // Schedule a GC for the time to the next process.
12048 ProcessRecord proc = mProcessesToGc.get(0);
12049 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12050
12051 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12052 long now = SystemClock.uptimeMillis();
12053 if (when < (now+GC_TIMEOUT)) {
12054 when = now + GC_TIMEOUT;
12055 }
12056 mHandler.sendMessageAtTime(msg, when);
12057 }
12058 }
12059
12060 /**
12061 * Add a process to the array of processes waiting to be GCed. Keeps the
12062 * list in sorted order by the last GC time. The process can't already be
12063 * on the list.
12064 */
12065 final void addProcessToGcListLocked(ProcessRecord proc) {
12066 boolean added = false;
12067 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12068 if (mProcessesToGc.get(i).lastRequestedGc <
12069 proc.lastRequestedGc) {
12070 added = true;
12071 mProcessesToGc.add(i+1, proc);
12072 break;
12073 }
12074 }
12075 if (!added) {
12076 mProcessesToGc.add(0, proc);
12077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012078 }
12079
12080 /**
12081 * Set up to ask a process to GC itself. This will either do it
12082 * immediately, or put it on the list of processes to gc the next
12083 * time things are idle.
12084 */
12085 final void scheduleAppGcLocked(ProcessRecord app) {
12086 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012087 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012088 return;
12089 }
12090 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012091 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 scheduleAppGcsLocked();
12093 }
12094 }
12095
Dianne Hackborn287952c2010-09-22 22:34:31 -070012096 final void checkExcessivePowerUsageLocked(boolean doKills) {
12097 updateCpuStatsNow();
12098
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012099 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012100 boolean doWakeKills = doKills;
12101 boolean doCpuKills = doKills;
12102 if (mLastPowerCheckRealtime == 0) {
12103 doWakeKills = false;
12104 }
12105 if (mLastPowerCheckUptime == 0) {
12106 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012107 }
12108 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012109 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012110 }
12111 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012112 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12113 final long curUptime = SystemClock.uptimeMillis();
12114 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12115 mLastPowerCheckRealtime = curRealtime;
12116 mLastPowerCheckUptime = curUptime;
12117 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12118 doWakeKills = false;
12119 }
12120 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12121 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012122 }
12123 int i = mLruProcesses.size();
12124 while (i > 0) {
12125 i--;
12126 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012127 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012128 long wtime;
12129 synchronized (stats) {
12130 wtime = stats.getProcessWakeTime(app.info.uid,
12131 app.pid, curRealtime);
12132 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012133 long wtimeUsed = wtime - app.lastWakeTime;
12134 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12135 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012136 StringBuilder sb = new StringBuilder(128);
12137 sb.append("Wake for ");
12138 app.toShortString(sb);
12139 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012140 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012141 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012142 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012143 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012144 sb.append((wtimeUsed*100)/realtimeSince);
12145 sb.append("%)");
12146 Slog.i(TAG, sb.toString());
12147 sb.setLength(0);
12148 sb.append("CPU for ");
12149 app.toShortString(sb);
12150 sb.append(": over ");
12151 TimeUtils.formatDuration(uptimeSince, sb);
12152 sb.append(" used ");
12153 TimeUtils.formatDuration(cputimeUsed, sb);
12154 sb.append(" (");
12155 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012156 sb.append("%)");
12157 Slog.i(TAG, sb.toString());
12158 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012159 // If a process has held a wake lock for more
12160 // than 50% of the time during this period,
12161 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012162 if (doWakeKills && realtimeSince > 0
12163 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12164 synchronized (stats) {
12165 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12166 realtimeSince, wtimeUsed);
12167 }
12168 Slog.w(TAG, "Excessive wake lock in " + app.processName
12169 + " (pid " + app.pid + "): held " + wtimeUsed
12170 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012171 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12172 app.processName, app.setAdj, "excessive wake lock");
12173 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012174 } else if (doCpuKills && uptimeSince > 0
12175 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12176 synchronized (stats) {
12177 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12178 uptimeSince, cputimeUsed);
12179 }
12180 Slog.w(TAG, "Excessive CPU in " + app.processName
12181 + " (pid " + app.pid + "): used " + cputimeUsed
12182 + " during " + uptimeSince);
12183 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12184 app.processName, app.setAdj, "excessive cpu");
12185 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012186 } else {
12187 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012188 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012189 }
12190 }
12191 }
12192 }
12193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 private final boolean updateOomAdjLocked(
12195 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12196 app.hiddenAdj = hiddenAdj;
12197
12198 if (app.thread == null) {
12199 return true;
12200 }
12201
Dianne Hackborn287952c2010-09-22 22:34:31 -070012202 final boolean wasKeeping = app.keeping;
12203
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012204 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012206 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 if (app.curRawAdj != app.setRawAdj) {
12208 if (app.curRawAdj > FOREGROUND_APP_ADJ
12209 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12210 // If this app is transitioning from foreground to
12211 // non-foreground, have it do a gc.
12212 scheduleAppGcLocked(app);
12213 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12214 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12215 // Likewise do a gc when an app is moving in to the
12216 // background (such as a service stopping).
12217 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012218 }
12219
12220 if (wasKeeping && !app.keeping) {
12221 // This app is no longer something we want to keep. Note
12222 // its current wake lock time to later know to kill it if
12223 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012224 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12225 synchronized (stats) {
12226 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12227 app.pid, SystemClock.elapsedRealtime());
12228 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012229 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012230 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232 app.setRawAdj = app.curRawAdj;
12233 }
12234 if (adj != app.setAdj) {
12235 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012236 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012237 TAG, "Set app " + app.processName +
12238 " oom adj to " + adj);
12239 app.setAdj = adj;
12240 } else {
12241 return false;
12242 }
12243 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012244 if (app.setSchedGroup != app.curSchedGroup) {
12245 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012246 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012247 "Setting process group of " + app.processName
12248 + " to " + app.curSchedGroup);
12249 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012250 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012251 try {
12252 Process.setProcessGroup(app.pid, app.curSchedGroup);
12253 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012254 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012255 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012256 e.printStackTrace();
12257 } finally {
12258 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012259 }
12260 }
12261 if (false) {
12262 if (app.thread != null) {
12263 try {
12264 app.thread.setSchedulingGroup(app.curSchedGroup);
12265 } catch (RemoteException e) {
12266 }
12267 }
12268 }
12269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012270 }
12271
12272 return true;
12273 }
12274
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012275 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012276 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012278 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012279 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012280 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012281 }
12282 }
12283 return resumedActivity;
12284 }
12285
12286 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012287 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012288 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12289 int curAdj = app.curAdj;
12290 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12291 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12292
12293 mAdjSeq++;
12294
12295 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12296 if (res) {
12297 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12298 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12299 if (nowHidden != wasHidden) {
12300 // Changed to/from hidden state, so apps after it in the LRU
12301 // list may also be changed.
12302 updateOomAdjLocked();
12303 }
12304 }
12305 return res;
12306 }
12307
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012308 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012309 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012310 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012311 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12312
12313 if (false) {
12314 RuntimeException e = new RuntimeException();
12315 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012316 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012317 }
12318
12319 mAdjSeq++;
12320
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012321 // Let's determine how many processes we have running vs.
12322 // how many slots we have for background processes; we may want
12323 // to put multiple processes in a slot of there are enough of
12324 // them.
12325 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12326 int factor = (mLruProcesses.size()-4)/numSlots;
12327 if (factor < 1) factor = 1;
12328 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012329 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012331 // First try updating the OOM adjustment for each of the
12332 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012333 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012334 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12335 while (i > 0) {
12336 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012337 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012338 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012339 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012340 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012342 step++;
12343 if (step >= factor) {
12344 step = 0;
12345 curHiddenAdj++;
12346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012348 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012349 if (!app.killedBackground) {
12350 numHidden++;
12351 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012352 Slog.i(TAG, "No longer want " + app.processName
12353 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012354 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12355 app.processName, app.setAdj, "too many background");
12356 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012357 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012358 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012359 }
12360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012361 } else {
12362 didOomAdj = false;
12363 }
12364 }
12365
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012366 // If we return false, we will fall back on killing processes to
12367 // have a fixed limit. Do this if a limit has been requested; else
12368 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012369 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12370 }
12371
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012372 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 synchronized (this) {
12374 int i;
12375
12376 // First remove any unused application processes whose package
12377 // has been removed.
12378 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12379 final ProcessRecord app = mRemovedProcesses.get(i);
12380 if (app.activities.size() == 0
12381 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012382 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012383 TAG, "Exiting empty application process "
12384 + app.processName + " ("
12385 + (app.thread != null ? app.thread.asBinder() : null)
12386 + ")\n");
12387 if (app.pid > 0 && app.pid != MY_PID) {
12388 Process.killProcess(app.pid);
12389 } else {
12390 try {
12391 app.thread.scheduleExit();
12392 } catch (Exception e) {
12393 // Ignore exceptions.
12394 }
12395 }
12396 cleanUpApplicationRecordLocked(app, false, -1);
12397 mRemovedProcesses.remove(i);
12398
12399 if (app.persistent) {
12400 if (app.persistent) {
12401 addAppLocked(app.info);
12402 }
12403 }
12404 }
12405 }
12406
12407 // Now try updating the OOM adjustment for each of the
12408 // application processes based on their current state.
12409 // If the setOomAdj() API is not supported, then go with our
12410 // back-up plan...
12411 if (!updateOomAdjLocked()) {
12412
12413 // Count how many processes are running services.
12414 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012415 for (i=mLruProcesses.size()-1; i>=0; i--) {
12416 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417
12418 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012419 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012420 // Don't count processes holding services against our
12421 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012422 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012423 TAG, "Not trimming app " + app + " with services: "
12424 + app.services);
12425 numServiceProcs++;
12426 }
12427 }
12428
12429 int curMaxProcs = mProcessLimit;
12430 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12431 if (mAlwaysFinishActivities) {
12432 curMaxProcs = 1;
12433 }
12434 curMaxProcs += numServiceProcs;
12435
12436 // Quit as many processes as we can to get down to the desired
12437 // process count. First remove any processes that no longer
12438 // have activites running in them.
12439 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012440 i<mLruProcesses.size()
12441 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012442 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012443 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012444 // Quit an application only if it is not currently
12445 // running any activities.
12446 if (!app.persistent && app.activities.size() == 0
12447 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012448 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012449 TAG, "Exiting empty application process "
12450 + app.processName + " ("
12451 + (app.thread != null ? app.thread.asBinder() : null)
12452 + ")\n");
12453 if (app.pid > 0 && app.pid != MY_PID) {
12454 Process.killProcess(app.pid);
12455 } else {
12456 try {
12457 app.thread.scheduleExit();
12458 } catch (Exception e) {
12459 // Ignore exceptions.
12460 }
12461 }
12462 // todo: For now we assume the application is not buggy
12463 // or evil, and will quit as a result of our request.
12464 // Eventually we need to drive this off of the death
12465 // notification, and kill the process if it takes too long.
12466 cleanUpApplicationRecordLocked(app, false, i);
12467 i--;
12468 }
12469 }
12470
12471 // If we still have too many processes, now from the least
12472 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012473 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012474 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012475 " of " + curMaxProcs + " processes");
12476 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012477 i<mLruProcesses.size()
12478 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012479 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012480 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012481 // Quit the application only if we have a state saved for
12482 // all of its activities.
12483 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012484 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 int NUMA = app.activities.size();
12486 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012487 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012488 TAG, "Looking to quit " + app.processName);
12489 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012490 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012491 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012492 TAG, " " + r.intent.getComponent().flattenToShortString()
12493 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12494 canQuit = (r.haveState || !r.stateNotNeeded)
12495 && !r.visible && r.stopped;
12496 }
12497 if (canQuit) {
12498 // Finish all of the activities, and then the app itself.
12499 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012500 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012501 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012502 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012503 }
12504 r.resultTo = null;
12505 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012506 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012507 + app.processName + " ("
12508 + (app.thread != null ? app.thread.asBinder() : null)
12509 + ")\n");
12510 if (app.pid > 0 && app.pid != MY_PID) {
12511 Process.killProcess(app.pid);
12512 } else {
12513 try {
12514 app.thread.scheduleExit();
12515 } catch (Exception e) {
12516 // Ignore exceptions.
12517 }
12518 }
12519 // todo: For now we assume the application is not buggy
12520 // or evil, and will quit as a result of our request.
12521 // Eventually we need to drive this off of the death
12522 // notification, and kill the process if it takes too long.
12523 cleanUpApplicationRecordLocked(app, false, i);
12524 i--;
12525 //dump();
12526 }
12527 }
12528
12529 }
12530
12531 int curMaxActivities = MAX_ACTIVITIES;
12532 if (mAlwaysFinishActivities) {
12533 curMaxActivities = 1;
12534 }
12535
12536 // Finally, if there are too many activities now running, try to
12537 // finish as many as we can to get back down to the limit.
12538 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012539 i<mMainStack.mLRUActivities.size()
12540 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012542 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012543 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012544
12545 // We can finish this one if we have its icicle saved and
12546 // it is not persistent.
12547 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012548 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012549 final int origSize = mMainStack.mLRUActivities.size();
12550 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012551
12552 // This will remove it from the LRU list, so keep
12553 // our index at the same value. Note that this check to
12554 // see if the size changes is just paranoia -- if
12555 // something unexpected happens, we don't want to end up
12556 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012557 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012558 i--;
12559 }
12560 }
12561 }
12562 }
12563 }
12564
12565 /** This method sends the specified signal to each of the persistent apps */
12566 public void signalPersistentProcesses(int sig) throws RemoteException {
12567 if (sig != Process.SIGNAL_USR1) {
12568 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12569 }
12570
12571 synchronized (this) {
12572 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12573 != PackageManager.PERMISSION_GRANTED) {
12574 throw new SecurityException("Requires permission "
12575 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12576 }
12577
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012578 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12579 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012580 if (r.thread != null && r.persistent) {
12581 Process.sendSignal(r.pid, sig);
12582 }
12583 }
12584 }
12585 }
12586
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012587 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012588 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012589
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012590 try {
12591 synchronized (this) {
12592 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12593 // its own permission.
12594 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12595 != PackageManager.PERMISSION_GRANTED) {
12596 throw new SecurityException("Requires permission "
12597 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012598 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012599
12600 if (start && fd == null) {
12601 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012602 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012603
12604 ProcessRecord proc = null;
12605 try {
12606 int pid = Integer.parseInt(process);
12607 synchronized (mPidsSelfLocked) {
12608 proc = mPidsSelfLocked.get(pid);
12609 }
12610 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012611 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012612
12613 if (proc == null) {
12614 HashMap<String, SparseArray<ProcessRecord>> all
12615 = mProcessNames.getMap();
12616 SparseArray<ProcessRecord> procs = all.get(process);
12617 if (procs != null && procs.size() > 0) {
12618 proc = procs.valueAt(0);
12619 }
12620 }
12621
12622 if (proc == null || proc.thread == null) {
12623 throw new IllegalArgumentException("Unknown process: " + process);
12624 }
12625
12626 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12627 if (isSecure) {
12628 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12629 throw new SecurityException("Process not debuggable: " + proc);
12630 }
12631 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012632
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012633 proc.thread.profilerControl(start, path, fd);
12634 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012635 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012636 }
12637 } catch (RemoteException e) {
12638 throw new IllegalStateException("Process disappeared");
12639 } finally {
12640 if (fd != null) {
12641 try {
12642 fd.close();
12643 } catch (IOException e) {
12644 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012645 }
12646 }
12647 }
Andy McFadden824c5102010-07-09 16:26:57 -070012648
12649 public boolean dumpHeap(String process, boolean managed,
12650 String path, ParcelFileDescriptor fd) throws RemoteException {
12651
12652 try {
12653 synchronized (this) {
12654 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12655 // its own permission (same as profileControl).
12656 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12657 != PackageManager.PERMISSION_GRANTED) {
12658 throw new SecurityException("Requires permission "
12659 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12660 }
12661
12662 if (fd == null) {
12663 throw new IllegalArgumentException("null fd");
12664 }
12665
12666 ProcessRecord proc = null;
12667 try {
12668 int pid = Integer.parseInt(process);
12669 synchronized (mPidsSelfLocked) {
12670 proc = mPidsSelfLocked.get(pid);
12671 }
12672 } catch (NumberFormatException e) {
12673 }
12674
12675 if (proc == null) {
12676 HashMap<String, SparseArray<ProcessRecord>> all
12677 = mProcessNames.getMap();
12678 SparseArray<ProcessRecord> procs = all.get(process);
12679 if (procs != null && procs.size() > 0) {
12680 proc = procs.valueAt(0);
12681 }
12682 }
12683
12684 if (proc == null || proc.thread == null) {
12685 throw new IllegalArgumentException("Unknown process: " + process);
12686 }
12687
12688 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12689 if (isSecure) {
12690 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12691 throw new SecurityException("Process not debuggable: " + proc);
12692 }
12693 }
12694
12695 proc.thread.dumpHeap(managed, path, fd);
12696 fd = null;
12697 return true;
12698 }
12699 } catch (RemoteException e) {
12700 throw new IllegalStateException("Process disappeared");
12701 } finally {
12702 if (fd != null) {
12703 try {
12704 fd.close();
12705 } catch (IOException e) {
12706 }
12707 }
12708 }
12709 }
12710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12712 public void monitor() {
12713 synchronized (this) { }
12714 }
12715}