blob: 7905dc6399e60cb22b595e5d4d27a85210bc3f7c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
79import android.net.Uri;
80import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080081import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070083import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080086import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.FileUtils;
88import android.os.Handler;
89import android.os.IBinder;
90import android.os.IPermissionController;
91import android.os.Looper;
92import android.os.Message;
93import android.os.Parcel;
94import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070096import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.RemoteException;
98import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070099import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.SystemClock;
101import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.Config;
104import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800105import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800106import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.PrintWriterPrinter;
108import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700109import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.view.Gravity;
111import android.view.LayoutInflater;
112import android.view.View;
113import android.view.WindowManager;
114import android.view.WindowManagerPolicy;
115
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700116import java.io.BufferedInputStream;
117import java.io.BufferedOutputStream;
118import java.io.DataInputStream;
119import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.File;
121import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700122import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200125import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800126import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.PrintWriter;
128import java.lang.IllegalStateException;
129import java.lang.ref.WeakReference;
130import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700131import java.util.Collections;
132import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.HashMap;
134import java.util.HashSet;
135import java.util.Iterator;
136import java.util.List;
137import java.util.Locale;
138import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700139import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700140import java.util.concurrent.atomic.AtomicBoolean;
141import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700143public final class ActivityManagerService extends ActivityManagerNative
144 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final String TAG = "ActivityManager";
146 static final boolean DEBUG = false;
147 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
148 static final boolean DEBUG_SWITCH = localLOGV || false;
149 static final boolean DEBUG_TASKS = localLOGV || false;
150 static final boolean DEBUG_PAUSE = localLOGV || false;
151 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
152 static final boolean DEBUG_TRANSITION = localLOGV || false;
153 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700154 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700156 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_VISBILITY = localLOGV || false;
158 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700159 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800160 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700162 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700163 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700164 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700165 static final boolean DEBUG_POWER = localLOGV || false;
166 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 static final boolean VALIDATE_TOKENS = false;
168 static final boolean SHOW_ACTIVITY_START_TIME = true;
169
170 // Control over CPU and battery monitoring.
171 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
172 static final boolean MONITOR_CPU_USAGE = true;
173 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
174 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
175 static final boolean MONITOR_THREAD_CPU_USAGE = false;
176
Dianne Hackborn1655be42009-05-08 14:29:01 -0700177 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700178 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 private static final String SYSTEM_SECURE = "ro.secure";
181
182 // This is the maximum number of application processes we would like
183 // to have running. Due to the asynchronous nature of things, we can
184 // temporarily go beyond this limit.
185 static final int MAX_PROCESSES = 2;
186
187 // Set to false to leave processes running indefinitely, relying on
188 // the kernel killing them as resources are required.
189 static final boolean ENFORCE_PROCESS_LIMIT = false;
190
191 // This is the maximum number of activities that we would like to have
192 // running at a given time.
193 static final int MAX_ACTIVITIES = 20;
194
195 // Maximum number of recent tasks that we can remember.
196 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700197
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700198 // Amount of time after a call to stopAppSwitches() during which we will
199 // prevent further untrusted switches from happening.
200 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
Dianne Hackborn287952c2010-09-22 22:34:31 -0700212 // The rate at which we check for apps using excessive power -- 15 mins.
213 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
214
215 // The minimum sample duration we will allow before deciding we have
216 // enough data on wake locks to start killing things.
217 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
218
219 // The minimum sample duration we will allow before deciding we have
220 // enough data on CPU usage to start killing things.
221 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // How long we allow a receiver to run before giving up on it.
224 static final int BROADCAST_TIMEOUT = 10*1000;
225
226 // How long we wait for a service to finish executing.
227 static final int SERVICE_TIMEOUT = 20*1000;
228
229 // How long a service needs to be running until restarting its process
230 // is no longer considered to be a relaunch of the service.
231 static final int SERVICE_RESTART_DURATION = 5*1000;
232
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700233 // How long a service needs to be running until it will start back at
234 // SERVICE_RESTART_DURATION after being killed.
235 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
236
237 // Multiplying factor to increase restart duration time by, for each time
238 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
239 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
240
241 // The minimum amount of time between restarting services that we allow.
242 // That is, when multiple services are restarting, we won't allow each
243 // to restart less than this amount of time from the last one.
244 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Maximum amount of time for there to be no activity on a service before
247 // we consider it non-essential and allow its process to go on the
248 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700249 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250
251 // How long we wait until we timeout on key dispatching.
252 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
253
254 // The minimum time we allow between crashes, for us to consider this
255 // application to be bad and stop and its services and reject broadcasts.
256 static final int MIN_CRASH_INTERVAL = 60*1000;
257
258 // How long we wait until we timeout on key dispatching during instrumentation.
259 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
260
261 // OOM adjustments for processes in various states:
262
263 // This is a process without anything currently running in it. Definitely
264 // the first to go! Value set in system/rootdir/init.rc on startup.
265 // This value is initalized in the constructor, careful when refering to
266 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269 // This is a process only hosting activities that are not visible,
270 // so it can be killed without any disruption. Value set in
271 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 static int HIDDEN_APP_MIN_ADJ;
274
The Android Open Source Project4df24232009-03-05 14:34:35 -0800275 // This is a process holding the home application -- we want to try
276 // avoiding killing it, even if it would normally be in the background,
277 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800279
Christopher Tate6fa95972009-06-05 18:43:55 -0700280 // This is a process currently hosting a backup operation. Killing it
281 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 // This is a process holding a secondary server -- killing it will not
285 // have much of an impact as far as the user is concerned. Value set in
286 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700289 // This is a process with a heavy-weight application. It is in the
290 // background, but we want to try to avoid killing it. Value set in
291 // system/rootdir/init.rc on startup.
292 static final int HEAVY_WEIGHT_APP_ADJ;
293
294 // This is a process only hosting components that are perceptible to the
295 // user, and we really want to avoid killing them, but they are not
296 // immediately visible. An example is background music playback. Value set in
297 // system/rootdir/init.rc on startup.
298 static final int PERCEPTIBLE_APP_ADJ;
299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 // This is a process only hosting activities that are visible to the
301 // user, so we'd prefer they don't disappear. Value set in
302 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800303 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304
305 // This is the process running the current foreground app. We'd really
306 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 // This is a process running a core server, such as telephony. Definitely
310 // don't want to kill it, but doing so is not completely fatal.
311 static final int CORE_SERVER_ADJ = -12;
312
313 // The system process runs at the default adjustment.
314 static final int SYSTEM_ADJ = -16;
315
316 // Memory pages are 4K.
317 static final int PAGE_SIZE = 4*1024;
318
319 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800320 static final int EMPTY_APP_MEM;
321 static final int HIDDEN_APP_MEM;
322 static final int HOME_APP_MEM;
323 static final int BACKUP_APP_MEM;
324 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700325 static final int HEAVY_WEIGHT_APP_MEM;
326 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327 static final int VISIBLE_APP_MEM;
328 static final int FOREGROUND_APP_MEM;
329
330 // The minimum number of hidden apps we want to be able to keep around,
331 // without empty apps being able to push them out of memory.
332 static final int MIN_HIDDEN_APPS = 2;
333
Dianne Hackborn8633e682010-04-22 16:03:41 -0700334 // The maximum number of hidden processes we will keep around before
335 // killing them; this is just a control to not let us go too crazy with
336 // keeping around processes on devices with large amounts of RAM.
337 static final int MAX_HIDDEN_APPS = 15;
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700340 // been idle for less than 15 seconds.
341 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342
343 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700344 // been idle for less than 120 seconds.
345 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700347 static int getIntProp(String name, boolean allowZero) {
348 String str = SystemProperties.get(name);
349 if (str == null) {
350 throw new IllegalArgumentException("Property not defined: " + name);
351 }
352 int val = Integer.valueOf(str);
353 if (val == 0 && !allowZero) {
354 throw new IllegalArgumentException("Property must not be zero: " + name);
355 }
356 return val;
357 }
358
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800359 static {
360 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700361 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
362 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
363 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
364 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
365 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
366 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
367 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
368 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
369 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
370 // These days we use the last empty slot for hidden apps as well.
371 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
372 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
373 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
374 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
375 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
376 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
377 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
378 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
379 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
380 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382
Dan Egnor42471dd2010-01-07 17:25:22 -0800383 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
385 static final String[] EMPTY_STRING_ARRAY = new String[0];
386
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700387 public ActivityStack mMainStack;
388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700390 * Description of a request to start a new activity, which has been held
391 * due to app switches being disabled.
392 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700393 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700394 ActivityRecord r;
395 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700396 Uri[] grantedUriPermissions;
397 int grantedMode;
398 boolean onlyIfNeeded;
399 }
400
401 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
402 = new ArrayList<PendingActivityLaunch>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * Activity we have told the window manager to have key focus.
435 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700436 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * List of intents that were used to start the most recent tasks.
439 */
440 final ArrayList<TaskRecord> mRecentTasks
441 = new ArrayList<TaskRecord>();
442
443 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 * All of the applications we currently have running organized by name.
445 * The keys are strings of the application package name (as
446 * returned by the package manager), and the keys are ApplicationRecord
447 * objects.
448 */
449 final ProcessMap<ProcessRecord> mProcessNames
450 = new ProcessMap<ProcessRecord>();
451
452 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700453 * The currently running heavy-weight process, if any.
454 */
455 ProcessRecord mHeavyWeightProcess = null;
456
457 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 * The last time that various processes have crashed.
459 */
460 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
461
462 /**
463 * Set of applications that we consider to be bad, and will reject
464 * incoming broadcasts from (which the user has no control over).
465 * Processes are added to this set when they have crashed twice within
466 * a minimum amount of time; they are removed from it when they are
467 * later restarted (hopefully due to some user action). The value is the
468 * time it was added to the list.
469 */
470 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
471
472 /**
473 * All of the processes we currently have running organized by pid.
474 * The keys are the pid running the application.
475 *
476 * <p>NOTE: This object is protected by its own lock, NOT the global
477 * activity manager lock!
478 */
479 final SparseArray<ProcessRecord> mPidsSelfLocked
480 = new SparseArray<ProcessRecord>();
481
482 /**
483 * All of the processes that have been forced to be foreground. The key
484 * is the pid of the caller who requested it (we hold a death
485 * link on it).
486 */
487 abstract class ForegroundToken implements IBinder.DeathRecipient {
488 int pid;
489 IBinder token;
490 }
491 final SparseArray<ForegroundToken> mForegroundProcesses
492 = new SparseArray<ForegroundToken>();
493
494 /**
495 * List of records for processes that someone had tried to start before the
496 * system was ready. We don't start them at that point, but ensure they
497 * are started by the time booting is complete.
498 */
499 final ArrayList<ProcessRecord> mProcessesOnHold
500 = new ArrayList<ProcessRecord>();
501
502 /**
503 * List of records for processes that we have started and are waiting
504 * for them to call back. This is really only needed when running in
505 * single processes mode, in which case we do not have a unique pid for
506 * each process.
507 */
508 final ArrayList<ProcessRecord> mStartingProcesses
509 = new ArrayList<ProcessRecord>();
510
511 /**
512 * List of persistent applications that are in the process
513 * of being started.
514 */
515 final ArrayList<ProcessRecord> mPersistentStartingProcesses
516 = new ArrayList<ProcessRecord>();
517
518 /**
519 * Processes that are being forcibly torn down.
520 */
521 final ArrayList<ProcessRecord> mRemovedProcesses
522 = new ArrayList<ProcessRecord>();
523
524 /**
525 * List of running applications, sorted by recent usage.
526 * The first entry in the list is the least recently used.
527 * It contains ApplicationRecord objects. This list does NOT include
528 * any persistent application records (since we never want to exit them).
529 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800530 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 = new ArrayList<ProcessRecord>();
532
533 /**
534 * List of processes that should gc as soon as things are idle.
535 */
536 final ArrayList<ProcessRecord> mProcessesToGc
537 = new ArrayList<ProcessRecord>();
538
539 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800540 * This is the process holding what we currently consider to be
541 * the "home" activity.
542 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700543 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800544
545 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 * Set of PendingResultRecord objects that are currently active.
547 */
548 final HashSet mPendingResultRecords = new HashSet();
549
550 /**
551 * Set of IntentSenderRecord objects that are currently active.
552 */
553 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
554 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
555
556 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700557 * Fingerprints (String.hashCode()) of stack traces that we've
558 * already logged DropBox entries for. Guarded by itself. If
559 * something (rogue user app) forces this over
560 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
561 */
562 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
563 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
564
565 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700566 * Strict Mode background batched logging state.
567 *
568 * The string buffer is guarded by itself, and its lock is also
569 * used to determine if another batched write is already
570 * in-flight.
571 */
572 private final StringBuilder mStrictModeBuffer = new StringBuilder();
573
574 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700575 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
576 */
577 private boolean mPendingBroadcastTimeoutMessage;
578
579 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 * Intent broadcast that we have tried to start, but are
581 * waiting for its application's process to be created. We only
582 * need one (instead of a list) because we always process broadcasts
583 * one at a time, so no others can be started while waiting for this
584 * one.
585 */
586 BroadcastRecord mPendingBroadcast = null;
587
588 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700589 * The receiver index that is pending, to restart the broadcast if needed.
590 */
591 int mPendingBroadcastRecvIndex;
592
593 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 * Keeps track of all IIntentReceivers that have been registered for
595 * broadcasts. Hash keys are the receiver IBinder, hash value is
596 * a ReceiverList.
597 */
598 final HashMap mRegisteredReceivers = new HashMap();
599
600 /**
601 * Resolver for broadcast intents to registered receivers.
602 * Holds BroadcastFilter (subclass of IntentFilter).
603 */
604 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
605 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
606 @Override
607 protected boolean allowFilterResult(
608 BroadcastFilter filter, List<BroadcastFilter> dest) {
609 IBinder target = filter.receiverList.receiver.asBinder();
610 for (int i=dest.size()-1; i>=0; i--) {
611 if (dest.get(i).receiverList.receiver.asBinder() == target) {
612 return false;
613 }
614 }
615 return true;
616 }
617 };
618
619 /**
620 * State of all active sticky broadcasts. Keys are the action of the
621 * sticky Intent, values are an ArrayList of all broadcasted intents with
622 * that action (which should usually be one).
623 */
624 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
625 new HashMap<String, ArrayList<Intent>>();
626
627 /**
628 * All currently running services.
629 */
630 final HashMap<ComponentName, ServiceRecord> mServices =
631 new HashMap<ComponentName, ServiceRecord>();
632
633 /**
634 * All currently running services indexed by the Intent used to start them.
635 */
636 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
637 new HashMap<Intent.FilterComparison, ServiceRecord>();
638
639 /**
640 * All currently bound service connections. Keys are the IBinder of
641 * the client's IServiceConnection.
642 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700643 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
644 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645
646 /**
647 * List of services that we have been asked to start,
648 * but haven't yet been able to. It is used to hold start requests
649 * while waiting for their corresponding application thread to get
650 * going.
651 */
652 final ArrayList<ServiceRecord> mPendingServices
653 = new ArrayList<ServiceRecord>();
654
655 /**
656 * List of services that are scheduled to restart following a crash.
657 */
658 final ArrayList<ServiceRecord> mRestartingServices
659 = new ArrayList<ServiceRecord>();
660
661 /**
662 * List of services that are in the process of being stopped.
663 */
664 final ArrayList<ServiceRecord> mStoppingServices
665 = new ArrayList<ServiceRecord>();
666
667 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700668 * Backup/restore process management
669 */
670 String mBackupAppName = null;
671 BackupRecord mBackupTarget = null;
672
673 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 * List of PendingThumbnailsRecord objects of clients who are still
675 * waiting to receive all of the thumbnails for a task.
676 */
677 final ArrayList mPendingThumbnails = new ArrayList();
678
679 /**
680 * List of HistoryRecord objects that have been finished and must
681 * still report back to a pending thumbnail receiver.
682 */
683 final ArrayList mCancelledThumbnails = new ArrayList();
684
685 /**
686 * All of the currently running global content providers. Keys are a
687 * string containing the provider name and values are a
688 * ContentProviderRecord object containing the data about it. Note
689 * that a single provider may be published under multiple names, so
690 * there may be multiple entries here for a single one in mProvidersByClass.
691 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700692 final HashMap<String, ContentProviderRecord> mProvidersByName
693 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694
695 /**
696 * All of the currently running global content providers. Keys are a
697 * string containing the provider's implementation class and values are a
698 * ContentProviderRecord object containing the data about it.
699 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700700 final HashMap<String, ContentProviderRecord> mProvidersByClass
701 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702
703 /**
704 * List of content providers who have clients waiting for them. The
705 * application is currently being launched and the provider will be
706 * removed from this list once it is published.
707 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700708 final ArrayList<ContentProviderRecord> mLaunchingProviders
709 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 /**
712 * Global set of specific Uri permissions that have been granted.
713 */
714 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
715 = new SparseArray<HashMap<Uri, UriPermission>>();
716
717 /**
718 * Thread-local storage used to carry caller permissions over through
719 * indirect content-provider access.
720 * @see #ActivityManagerService.openContentUri()
721 */
722 private class Identity {
723 public int pid;
724 public int uid;
725
726 Identity(int _pid, int _uid) {
727 pid = _pid;
728 uid = _uid;
729 }
730 }
731 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
732
733 /**
734 * All information we have collected about the runtime performance of
735 * any user id that can impact battery performance.
736 */
737 final BatteryStatsService mBatteryStatsService;
738
739 /**
740 * information about component usage
741 */
742 final UsageStatsService mUsageStatsService;
743
744 /**
745 * Current configuration information. HistoryRecord objects are given
746 * a reference to this object to indicate which configuration they are
747 * currently running in, so this object must be kept immutable.
748 */
749 Configuration mConfiguration = new Configuration();
750
751 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800752 * Current sequencing integer of the configuration, for skipping old
753 * configurations.
754 */
755 int mConfigurationSeq = 0;
756
757 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700758 * Hardware-reported OpenGLES version.
759 */
760 final int GL_ES_VERSION;
761
762 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 * List of initialization arguments to pass to all processes when binding applications to them.
764 * For example, references to the commonly used services.
765 */
766 HashMap<String, IBinder> mAppBindArgs;
767
768 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700769 * Temporary to avoid allocations. Protected by main lock.
770 */
771 final StringBuilder mStringBuilder = new StringBuilder(256);
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * Used to control how we initialize the service.
775 */
776 boolean mStartRunning = false;
777 ComponentName mTopComponent;
778 String mTopAction;
779 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700780 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 boolean mSystemReady = false;
782 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700783 boolean mWaitingUpdate = false;
784 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700785 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700786 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 Context mContext;
789
790 int mFactoryTest;
791
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700792 boolean mCheckedForSetup;
793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700795 * The time at which we will allow normal application switches again,
796 * after a call to {@link #stopAppSwitches()}.
797 */
798 long mAppSwitchesAllowedTime;
799
800 /**
801 * This is set to true after the first switch after mAppSwitchesAllowedTime
802 * is set; any switches after that will clear the time.
803 */
804 boolean mDidAppSwitch;
805
806 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700807 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700808 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 long mLastPowerCheckRealtime;
810
811 /**
812 * Last time (in uptime) at which we checked for power usage.
813 */
814 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700815
816 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 * Set while we are wanting to sleep, to prevent any
818 * activities from being started/resumed.
819 */
820 boolean mSleeping = false;
821
822 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700823 * Set if we are shutting down the system, similar to sleeping.
824 */
825 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826
827 /**
828 * Task identifier that activities are currently being started
829 * in. Incremented each time a new task is created.
830 * todo: Replace this with a TokenSpace class that generates non-repeating
831 * integers that won't wrap.
832 */
833 int mCurTask = 1;
834
835 /**
836 * Current sequence id for oom_adj computation traversal.
837 */
838 int mAdjSeq = 0;
839
840 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700841 * Current sequence id for process LRU updating.
842 */
843 int mLruSeq = 0;
844
845 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
847 * is set, indicating the user wants processes started in such a way
848 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
849 * running in each process (thus no pre-initialized process, etc).
850 */
851 boolean mSimpleProcessManagement = false;
852
853 /**
854 * System monitoring: number of processes that died since the last
855 * N procs were started.
856 */
857 int[] mProcDeaths = new int[20];
858
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700859 /**
860 * This is set if we had to do a delayed dexopt of an app before launching
861 * it, to increasing the ANR timeouts in that case.
862 */
863 boolean mDidDexOpt;
864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 String mDebugApp = null;
866 boolean mWaitForDebugger = false;
867 boolean mDebugTransient = false;
868 String mOrigDebugApp = null;
869 boolean mOrigWaitForDebugger = false;
870 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700871 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 final RemoteCallbackList<IActivityWatcher> mWatchers
874 = new RemoteCallbackList<IActivityWatcher>();
875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 /**
877 * Callback of last caller to {@link #requestPss}.
878 */
879 Runnable mRequestPssCallback;
880
881 /**
882 * Remaining processes for which we are waiting results from the last
883 * call to {@link #requestPss}.
884 */
885 final ArrayList<ProcessRecord> mRequestPssList
886 = new ArrayList<ProcessRecord>();
887
888 /**
889 * Runtime statistics collection thread. This object's lock is used to
890 * protect all related state.
891 */
892 final Thread mProcessStatsThread;
893
894 /**
895 * Used to collect process stats when showing not responding dialog.
896 * Protected by mProcessStatsThread.
897 */
898 final ProcessStats mProcessStats = new ProcessStats(
899 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700900 final AtomicLong mLastCpuTime = new AtomicLong(0);
901 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 long mLastWriteTime = 0;
904
905 /**
906 * Set to true after the system has finished booting.
907 */
908 boolean mBooted = false;
909
910 int mProcessLimit = 0;
911
912 WindowManagerService mWindowManager;
913
914 static ActivityManagerService mSelf;
915 static ActivityThread mSystemThread;
916
917 private final class AppDeathRecipient implements IBinder.DeathRecipient {
918 final ProcessRecord mApp;
919 final int mPid;
920 final IApplicationThread mAppThread;
921
922 AppDeathRecipient(ProcessRecord app, int pid,
923 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800924 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 TAG, "New death recipient " + this
926 + " for thread " + thread.asBinder());
927 mApp = app;
928 mPid = pid;
929 mAppThread = thread;
930 }
931
932 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800933 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 TAG, "Death received in " + this
935 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 synchronized(ActivityManagerService.this) {
937 appDiedLocked(mApp, mPid, mAppThread);
938 }
939 }
940 }
941
942 static final int SHOW_ERROR_MSG = 1;
943 static final int SHOW_NOT_RESPONDING_MSG = 2;
944 static final int SHOW_FACTORY_ERROR_MSG = 3;
945 static final int UPDATE_CONFIGURATION_MSG = 4;
946 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
947 static final int WAIT_FOR_DEBUGGER_MSG = 6;
948 static final int BROADCAST_INTENT_MSG = 7;
949 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 static final int SERVICE_TIMEOUT_MSG = 12;
951 static final int UPDATE_TIME_ZONE = 13;
952 static final int SHOW_UID_ERROR_MSG = 14;
953 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700955 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700956 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800957 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700958 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
959 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700960 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700961 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700962 static final int CLEAR_DNS_CACHE = 28;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963
964 AlertDialog mUidAlert;
965
966 final Handler mHandler = new Handler() {
967 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800968 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 //}
970
971 public void handleMessage(Message msg) {
972 switch (msg.what) {
973 case SHOW_ERROR_MSG: {
974 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 synchronized (ActivityManagerService.this) {
976 ProcessRecord proc = (ProcessRecord)data.get("app");
977 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800978 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 return;
980 }
981 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700982 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800983 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 d.show();
985 proc.crashDialog = d;
986 } else {
987 // The device is asleep, so just pretend that the user
988 // saw a crash dialog and hit "force quit".
989 res.set(0);
990 }
991 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700992
993 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 } break;
995 case SHOW_NOT_RESPONDING_MSG: {
996 synchronized (ActivityManagerService.this) {
997 HashMap data = (HashMap) msg.obj;
998 ProcessRecord proc = (ProcessRecord)data.get("app");
999 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001000 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 return;
1002 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001003
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001004 Intent intent = new Intent("android.intent.action.ANR");
1005 if (!mProcessesReady) {
1006 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1007 }
1008 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001009 null, null, 0, null, null, null,
1010 false, false, MY_PID, Process.SYSTEM_UID);
1011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001013 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 d.show();
1015 proc.anrDialog = d;
1016 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001017
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001018 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001020 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1021 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1022 synchronized (ActivityManagerService.this) {
1023 ProcessRecord proc = (ProcessRecord) data.get("app");
1024 if (proc == null) {
1025 Slog.e(TAG, "App not found when showing strict mode dialog.");
1026 break;
1027 }
1028 if (proc.crashDialog != null) {
1029 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1030 return;
1031 }
1032 AppErrorResult res = (AppErrorResult) data.get("result");
1033 if (!mSleeping && !mShuttingDown) {
1034 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1035 d.show();
1036 proc.crashDialog = d;
1037 } else {
1038 // The device is asleep, so just pretend that the user
1039 // saw a crash dialog and hit "force quit".
1040 res.set(0);
1041 }
1042 }
1043 ensureBootCompleted();
1044 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 case SHOW_FACTORY_ERROR_MSG: {
1046 Dialog d = new FactoryErrorDialog(
1047 mContext, msg.getData().getCharSequence("msg"));
1048 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001049 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 } break;
1051 case UPDATE_CONFIGURATION_MSG: {
1052 final ContentResolver resolver = mContext.getContentResolver();
1053 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1054 } break;
1055 case GC_BACKGROUND_PROCESSES_MSG: {
1056 synchronized (ActivityManagerService.this) {
1057 performAppGcsIfAppropriateLocked();
1058 }
1059 } break;
1060 case WAIT_FOR_DEBUGGER_MSG: {
1061 synchronized (ActivityManagerService.this) {
1062 ProcessRecord app = (ProcessRecord)msg.obj;
1063 if (msg.arg1 != 0) {
1064 if (!app.waitedForDebugger) {
1065 Dialog d = new AppWaitingForDebuggerDialog(
1066 ActivityManagerService.this,
1067 mContext, app);
1068 app.waitDialog = d;
1069 app.waitedForDebugger = true;
1070 d.show();
1071 }
1072 } else {
1073 if (app.waitDialog != null) {
1074 app.waitDialog.dismiss();
1075 app.waitDialog = null;
1076 }
1077 }
1078 }
1079 } break;
1080 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001081 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 TAG, "Received BROADCAST_INTENT_MSG");
1083 processNextBroadcast(true);
1084 } break;
1085 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001086 synchronized (ActivityManagerService.this) {
1087 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001091 if (mDidDexOpt) {
1092 mDidDexOpt = false;
1093 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1094 nmsg.obj = msg.obj;
1095 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1096 return;
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 serviceTimeout((ProcessRecord)msg.obj);
1099 } break;
1100 case UPDATE_TIME_ZONE: {
1101 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001102 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1103 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 if (r.thread != null) {
1105 try {
1106 r.thread.updateTimeZone();
1107 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001108 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 }
1110 }
1111 }
1112 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001113 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001114 case CLEAR_DNS_CACHE: {
1115 synchronized (ActivityManagerService.this) {
1116 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1117 ProcessRecord r = mLruProcesses.get(i);
1118 if (r.thread != null) {
1119 try {
1120 r.thread.clearDnsCache();
1121 } catch (RemoteException ex) {
1122 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1123 }
1124 }
1125 }
1126 }
1127 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 case SHOW_UID_ERROR_MSG: {
1129 // XXX This is a temporary dialog, no need to localize.
1130 AlertDialog d = new BaseErrorDialog(mContext);
1131 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1132 d.setCancelable(false);
1133 d.setTitle("System UIDs Inconsistent");
1134 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001135 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1137 mUidAlert = d;
1138 d.show();
1139 } break;
1140 case IM_FEELING_LUCKY_MSG: {
1141 if (mUidAlert != null) {
1142 mUidAlert.dismiss();
1143 mUidAlert = null;
1144 }
1145 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001147 if (mDidDexOpt) {
1148 mDidDexOpt = false;
1149 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1150 nmsg.obj = msg.obj;
1151 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1152 return;
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 ProcessRecord app = (ProcessRecord)msg.obj;
1155 synchronized (ActivityManagerService.this) {
1156 processStartTimedOutLocked(app);
1157 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001158 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001159 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1160 synchronized (ActivityManagerService.this) {
1161 doPendingActivityLaunchesLocked(true);
1162 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001163 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001164 case KILL_APPLICATION_MSG: {
1165 synchronized (ActivityManagerService.this) {
1166 int uid = msg.arg1;
1167 boolean restart = (msg.arg2 == 1);
1168 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001169 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001170 }
1171 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001172 case FINALIZE_PENDING_INTENT_MSG: {
1173 ((PendingIntentRecord)msg.obj).completeFinalize();
1174 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001175 case POST_HEAVY_NOTIFICATION_MSG: {
1176 INotificationManager inm = NotificationManager.getService();
1177 if (inm == null) {
1178 return;
1179 }
1180
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001181 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001182 ProcessRecord process = root.app;
1183 if (process == null) {
1184 return;
1185 }
1186
1187 try {
1188 Context context = mContext.createPackageContext(process.info.packageName, 0);
1189 String text = mContext.getString(R.string.heavy_weight_notification,
1190 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1191 Notification notification = new Notification();
1192 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1193 notification.when = 0;
1194 notification.flags = Notification.FLAG_ONGOING_EVENT;
1195 notification.tickerText = text;
1196 notification.defaults = 0; // please be quiet
1197 notification.sound = null;
1198 notification.vibrate = null;
1199 notification.setLatestEventInfo(context, text,
1200 mContext.getText(R.string.heavy_weight_notification_detail),
1201 PendingIntent.getActivity(mContext, 0, root.intent,
1202 PendingIntent.FLAG_CANCEL_CURRENT));
1203
1204 try {
1205 int[] outId = new int[1];
1206 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1207 notification, outId);
1208 } catch (RuntimeException e) {
1209 Slog.w(ActivityManagerService.TAG,
1210 "Error showing notification for heavy-weight app", e);
1211 } catch (RemoteException e) {
1212 }
1213 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001214 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001215 }
1216 } break;
1217 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1218 INotificationManager inm = NotificationManager.getService();
1219 if (inm == null) {
1220 return;
1221 }
1222 try {
1223 inm.cancelNotification("android",
1224 R.string.heavy_weight_notification);
1225 } catch (RuntimeException e) {
1226 Slog.w(ActivityManagerService.TAG,
1227 "Error canceling notification for service", e);
1228 } catch (RemoteException e) {
1229 }
1230 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001231 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1232 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001233 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001234 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001235 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1236 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001237 }
1238 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240 }
1241 };
1242
1243 public static void setSystemProcess() {
1244 try {
1245 ActivityManagerService m = mSelf;
1246
1247 ServiceManager.addService("activity", m);
1248 ServiceManager.addService("meminfo", new MemBinder(m));
1249 if (MONITOR_CPU_USAGE) {
1250 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 ServiceManager.addService("permission", new PermissionController(m));
1253
1254 ApplicationInfo info =
1255 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001256 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001257 mSystemThread.installSystemApplicationInfo(info);
1258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 synchronized (mSelf) {
1260 ProcessRecord app = mSelf.newProcessRecordLocked(
1261 mSystemThread.getApplicationThread(), info,
1262 info.processName);
1263 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001264 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 app.maxAdj = SYSTEM_ADJ;
1266 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1267 synchronized (mSelf.mPidsSelfLocked) {
1268 mSelf.mPidsSelfLocked.put(app.pid, app);
1269 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001270 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 }
1272 } catch (PackageManager.NameNotFoundException e) {
1273 throw new RuntimeException(
1274 "Unable to find android system package", e);
1275 }
1276 }
1277
1278 public void setWindowManager(WindowManagerService wm) {
1279 mWindowManager = wm;
1280 }
1281
1282 public static final Context main(int factoryTest) {
1283 AThread thr = new AThread();
1284 thr.start();
1285
1286 synchronized (thr) {
1287 while (thr.mService == null) {
1288 try {
1289 thr.wait();
1290 } catch (InterruptedException e) {
1291 }
1292 }
1293 }
1294
1295 ActivityManagerService m = thr.mService;
1296 mSelf = m;
1297 ActivityThread at = ActivityThread.systemMain();
1298 mSystemThread = at;
1299 Context context = at.getSystemContext();
1300 m.mContext = context;
1301 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001302 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303
1304 m.mBatteryStatsService.publish(context);
1305 m.mUsageStatsService.publish(context);
1306
1307 synchronized (thr) {
1308 thr.mReady = true;
1309 thr.notifyAll();
1310 }
1311
1312 m.startRunning(null, null, null, null);
1313
1314 return context;
1315 }
1316
1317 public static ActivityManagerService self() {
1318 return mSelf;
1319 }
1320
1321 static class AThread extends Thread {
1322 ActivityManagerService mService;
1323 boolean mReady = false;
1324
1325 public AThread() {
1326 super("ActivityManager");
1327 }
1328
1329 public void run() {
1330 Looper.prepare();
1331
1332 android.os.Process.setThreadPriority(
1333 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001334 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335
1336 ActivityManagerService m = new ActivityManagerService();
1337
1338 synchronized (this) {
1339 mService = m;
1340 notifyAll();
1341 }
1342
1343 synchronized (this) {
1344 while (!mReady) {
1345 try {
1346 wait();
1347 } catch (InterruptedException e) {
1348 }
1349 }
1350 }
1351
1352 Looper.loop();
1353 }
1354 }
1355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 static class MemBinder extends Binder {
1357 ActivityManagerService mActivityManagerService;
1358 MemBinder(ActivityManagerService activityManagerService) {
1359 mActivityManagerService = activityManagerService;
1360 }
1361
1362 @Override
1363 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1364 ActivityManagerService service = mActivityManagerService;
1365 ArrayList<ProcessRecord> procs;
1366 synchronized (mActivityManagerService) {
1367 if (args != null && args.length > 0
1368 && args[0].charAt(0) != '-') {
1369 procs = new ArrayList<ProcessRecord>();
1370 int pid = -1;
1371 try {
1372 pid = Integer.parseInt(args[0]);
1373 } catch (NumberFormatException e) {
1374
1375 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001376 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1377 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 if (proc.pid == pid) {
1379 procs.add(proc);
1380 } else if (proc.processName.equals(args[0])) {
1381 procs.add(proc);
1382 }
1383 }
1384 if (procs.size() <= 0) {
1385 pw.println("No process found for: " + args[0]);
1386 return;
1387 }
1388 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001389 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 }
1391 }
1392 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1393 }
1394 }
1395
1396 static class CpuBinder extends Binder {
1397 ActivityManagerService mActivityManagerService;
1398 CpuBinder(ActivityManagerService activityManagerService) {
1399 mActivityManagerService = activityManagerService;
1400 }
1401
1402 @Override
1403 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1404 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001405 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1406 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1407 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 }
1409 }
1410 }
1411
1412 private ActivityManagerService() {
1413 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1414 if (v != null && Integer.getInteger(v) != 0) {
1415 mSimpleProcessManagement = true;
1416 }
1417 v = System.getenv("ANDROID_DEBUG_APP");
1418 if (v != null) {
1419 mSimpleProcessManagement = true;
1420 }
1421
Joe Onorato8a9b2202010-02-26 18:56:32 -08001422 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 File dataDir = Environment.getDataDirectory();
1425 File systemDir = new File(dataDir, "system");
1426 systemDir.mkdirs();
1427 mBatteryStatsService = new BatteryStatsService(new File(
1428 systemDir, "batterystats.bin").toString());
1429 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001430 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001431 mOnBattery = DEBUG_POWER ? true
1432 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001433 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001435 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001436 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437
Jack Palevichb90d28c2009-07-22 15:35:24 -07001438 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1439 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1440
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001441 mConfiguration.setToDefaults();
1442 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 mProcessStats.init();
1444
1445 // Add ourself to the Watchdog monitors.
1446 Watchdog.getInstance().addMonitor(this);
1447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 mProcessStatsThread = new Thread("ProcessStats") {
1449 public void run() {
1450 while (true) {
1451 try {
1452 try {
1453 synchronized(this) {
1454 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001455 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001457 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 // + ", write delay=" + nextWriteDelay);
1459 if (nextWriteDelay < nextCpuDelay) {
1460 nextCpuDelay = nextWriteDelay;
1461 }
1462 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001463 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 this.wait(nextCpuDelay);
1465 }
1466 }
1467 } catch (InterruptedException e) {
1468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 updateCpuStatsNow();
1470 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001471 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 }
1473 }
1474 }
1475 };
1476 mProcessStatsThread.start();
1477 }
1478
1479 @Override
1480 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1481 throws RemoteException {
1482 try {
1483 return super.onTransact(code, data, reply, flags);
1484 } catch (RuntimeException e) {
1485 // The activity manager only throws security exceptions, so let's
1486 // log all others.
1487 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001488 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 }
1490 throw e;
1491 }
1492 }
1493
1494 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001495 final long now = SystemClock.uptimeMillis();
1496 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1497 return;
1498 }
1499 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1500 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 mProcessStatsThread.notify();
1502 }
1503 }
1504 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 void updateCpuStatsNow() {
1507 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001508 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 final long now = SystemClock.uptimeMillis();
1510 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001513 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1514 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 haveNewCpuStats = true;
1516 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001517 //Slog.i(TAG, mProcessStats.printCurrentState());
1518 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 // + mProcessStats.getTotalCpuPercent() + "%");
1520
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 if ("true".equals(SystemProperties.get("events.cpu"))) {
1523 int user = mProcessStats.getLastUserTime();
1524 int system = mProcessStats.getLastSystemTime();
1525 int iowait = mProcessStats.getLastIoWaitTime();
1526 int irq = mProcessStats.getLastIrqTime();
1527 int softIrq = mProcessStats.getLastSoftIrqTime();
1528 int idle = mProcessStats.getLastIdleTime();
1529
1530 int total = user + system + iowait + irq + softIrq + idle;
1531 if (total == 0) total = 1;
1532
Doug Zongker2bec3d42009-12-04 12:52:44 -08001533 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 ((user+system+iowait+irq+softIrq) * 100) / total,
1535 (user * 100) / total,
1536 (system * 100) / total,
1537 (iowait * 100) / total,
1538 (irq * 100) / total,
1539 (softIrq * 100) / total);
1540 }
1541 }
1542
Amith Yamasanie43530a2009-08-21 13:11:37 -07001543 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001544 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001545 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 synchronized(mPidsSelfLocked) {
1547 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001548 if (mOnBattery) {
1549 int perc = bstats.startAddingCpuLocked();
1550 int totalUTime = 0;
1551 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001552 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001554 ProcessStats.Stats st = mProcessStats.getStats(i);
1555 if (!st.working) {
1556 continue;
1557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001559 int otherUTime = (st.rel_utime*perc)/100;
1560 int otherSTime = (st.rel_stime*perc)/100;
1561 totalUTime += otherUTime;
1562 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 if (pr != null) {
1564 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001565 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1566 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001567 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001568 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001569 } else {
1570 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001571 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001572 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001573 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1574 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001575 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 }
1578 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001579 bstats.finishAddingCpuLocked(perc, totalUTime,
1580 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 }
1582 }
1583 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1586 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001587 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 }
1589 }
1590 }
1591 }
1592
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001593 @Override
1594 public void batteryNeedsCpuUpdate() {
1595 updateCpuStatsNow();
1596 }
1597
1598 @Override
1599 public void batteryPowerChanged(boolean onBattery) {
1600 // When plugging in, update the CPU stats first before changing
1601 // the plug state.
1602 updateCpuStatsNow();
1603 synchronized (this) {
1604 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001605 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001606 }
1607 }
1608 }
1609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 /**
1611 * Initialize the application bind args. These are passed to each
1612 * process when the bindApplication() IPC is sent to the process. They're
1613 * lazily setup to make sure the services are running when they're asked for.
1614 */
1615 private HashMap<String, IBinder> getCommonServicesLocked() {
1616 if (mAppBindArgs == null) {
1617 mAppBindArgs = new HashMap<String, IBinder>();
1618
1619 // Setup the application init args
1620 mAppBindArgs.put("package", ServiceManager.getService("package"));
1621 mAppBindArgs.put("window", ServiceManager.getService("window"));
1622 mAppBindArgs.put(Context.ALARM_SERVICE,
1623 ServiceManager.getService(Context.ALARM_SERVICE));
1624 }
1625 return mAppBindArgs;
1626 }
1627
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001628 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 if (mFocusedActivity != r) {
1630 mFocusedActivity = r;
1631 mWindowManager.setFocusedApp(r, true);
1632 }
1633 }
1634
Dianne Hackborn906497c2010-05-10 15:57:38 -07001635 private final void updateLruProcessInternalLocked(ProcessRecord app,
1636 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001638 int lrui = mLruProcesses.indexOf(app);
1639 if (lrui >= 0) mLruProcesses.remove(lrui);
1640
1641 int i = mLruProcesses.size()-1;
1642 int skipTop = 0;
1643
Dianne Hackborn906497c2010-05-10 15:57:38 -07001644 app.lruSeq = mLruSeq;
1645
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001646 // compute the new weight for this process.
1647 if (updateActivityTime) {
1648 app.lastActivityTime = SystemClock.uptimeMillis();
1649 }
1650 if (app.activities.size() > 0) {
1651 // If this process has activities, we more strongly want to keep
1652 // it around.
1653 app.lruWeight = app.lastActivityTime;
1654 } else if (app.pubProviders.size() > 0) {
1655 // If this process contains content providers, we want to keep
1656 // it a little more strongly.
1657 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1658 // Also don't let it kick out the first few "real" hidden processes.
1659 skipTop = MIN_HIDDEN_APPS;
1660 } else {
1661 // If this process doesn't have activities, we less strongly
1662 // want to keep it around, and generally want to avoid getting
1663 // in front of any very recently used activities.
1664 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1665 // Also don't let it kick out the first few "real" hidden processes.
1666 skipTop = MIN_HIDDEN_APPS;
1667 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001668
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001669 while (i >= 0) {
1670 ProcessRecord p = mLruProcesses.get(i);
1671 // If this app shouldn't be in front of the first N background
1672 // apps, then skip over that many that are currently hidden.
1673 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1674 skipTop--;
1675 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001676 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001677 mLruProcesses.add(i+1, app);
1678 break;
1679 }
1680 i--;
1681 }
1682 if (i < 0) {
1683 mLruProcesses.add(0, app);
1684 }
1685
Dianne Hackborn906497c2010-05-10 15:57:38 -07001686 // If the app is currently using a content provider or service,
1687 // bump those processes as well.
1688 if (app.connections.size() > 0) {
1689 for (ConnectionRecord cr : app.connections) {
1690 if (cr.binding != null && cr.binding.service != null
1691 && cr.binding.service.app != null
1692 && cr.binding.service.app.lruSeq != mLruSeq) {
1693 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1694 updateActivityTime, i+1);
1695 }
1696 }
1697 }
1698 if (app.conProviders.size() > 0) {
1699 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1700 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1701 updateLruProcessInternalLocked(cpr.app, oomAdj,
1702 updateActivityTime, i+1);
1703 }
1704 }
1705 }
1706
Joe Onorato8a9b2202010-02-26 18:56:32 -08001707 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 if (oomAdj) {
1709 updateOomAdjLocked();
1710 }
1711 }
1712
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001713 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001714 boolean oomAdj, boolean updateActivityTime) {
1715 mLruSeq++;
1716 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1717 }
1718
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001719 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 String processName, int uid) {
1721 if (uid == Process.SYSTEM_UID) {
1722 // The system gets to run in any process. If there are multiple
1723 // processes with the same uid, just pick the first (this
1724 // should never happen).
1725 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1726 processName);
1727 return procs != null ? procs.valueAt(0) : null;
1728 }
1729 ProcessRecord proc = mProcessNames.get(processName, uid);
1730 return proc;
1731 }
1732
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001733 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001734 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001735 try {
1736 if (pm.performDexOpt(packageName)) {
1737 mDidDexOpt = true;
1738 }
1739 } catch (RemoteException e) {
1740 }
1741 }
1742
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001743 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 int transit = mWindowManager.getPendingAppTransition();
1745 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1746 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1747 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1748 }
1749
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001750 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001752 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1754 // We don't have to do anything more if:
1755 // (1) There is an existing application record; and
1756 // (2) The caller doesn't think it is dead, OR there is no thread
1757 // object attached to it so we know it couldn't have crashed; and
1758 // (3) There is a pid assigned to it, so it is either starting or
1759 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001760 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 + " app=" + app + " knownToBeDead=" + knownToBeDead
1762 + " thread=" + (app != null ? app.thread : null)
1763 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001764 if (app != null && app.pid > 0) {
1765 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001766 // We already have the app running, or are waiting for it to
1767 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001768 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001769 return app;
1770 } else {
1771 // An application record is attached to a previous process,
1772 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001773 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001774 handleAppDiedLocked(app, true);
1775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 String hostingNameStr = hostingName != null
1779 ? hostingName.flattenToShortString() : null;
1780
1781 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1782 // If we are in the background, then check to see if this process
1783 // is bad. If so, we will just silently fail.
1784 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001785 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1786 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 return null;
1788 }
1789 } else {
1790 // When the user is explicitly starting a process, then clear its
1791 // crash count so that we won't make it bad until they see at
1792 // least one crash dialog again, and make the process good again
1793 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001794 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1795 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 mProcessCrashTimes.remove(info.processName, info.uid);
1797 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001798 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 info.processName);
1800 mBadProcesses.remove(info.processName, info.uid);
1801 if (app != null) {
1802 app.bad = false;
1803 }
1804 }
1805 }
1806
1807 if (app == null) {
1808 app = newProcessRecordLocked(null, info, processName);
1809 mProcessNames.put(processName, info.uid, app);
1810 } else {
1811 // If this is a new package in the process, add the package to the list
1812 app.addPackage(info.packageName);
1813 }
1814
1815 // If the system is not ready yet, then hold off on starting this
1816 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001817 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001818 && !isAllowedWhileBooting(info)
1819 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 if (!mProcessesOnHold.contains(app)) {
1821 mProcessesOnHold.add(app);
1822 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001823 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 return app;
1825 }
1826
1827 startProcessLocked(app, hostingType, hostingNameStr);
1828 return (app.pid != 0) ? app : null;
1829 }
1830
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001831 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1832 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1833 }
1834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 private final void startProcessLocked(ProcessRecord app,
1836 String hostingType, String hostingNameStr) {
1837 if (app.pid > 0 && app.pid != MY_PID) {
1838 synchronized (mPidsSelfLocked) {
1839 mPidsSelfLocked.remove(app.pid);
1840 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1841 }
1842 app.pid = 0;
1843 }
1844
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001845 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1846 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 mProcessesOnHold.remove(app);
1848
1849 updateCpuStats();
1850
1851 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1852 mProcDeaths[0] = 0;
1853
1854 try {
1855 int uid = app.info.uid;
1856 int[] gids = null;
1857 try {
1858 gids = mContext.getPackageManager().getPackageGids(
1859 app.info.packageName);
1860 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001861 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 }
1863 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1864 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1865 && mTopComponent != null
1866 && app.processName.equals(mTopComponent.getPackageName())) {
1867 uid = 0;
1868 }
1869 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1870 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1871 uid = 0;
1872 }
1873 }
1874 int debugFlags = 0;
1875 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1876 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1877 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001878 // Run the app in safe mode if its manifest requests so or the
1879 // system is booted in safe mode.
1880 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1881 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001882 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1885 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1886 }
1887 if ("1".equals(SystemProperties.get("debug.assert"))) {
1888 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1889 }
1890 int pid = Process.start("android.app.ActivityThread",
1891 mSimpleProcessManagement ? app.processName : null, uid, uid,
1892 gids, debugFlags, null);
1893 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1894 synchronized (bs) {
1895 if (bs.isOnBattery()) {
1896 app.batteryStats.incStartsLocked();
1897 }
1898 }
1899
Doug Zongker2bec3d42009-12-04 12:52:44 -08001900 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 app.processName, hostingType,
1902 hostingNameStr != null ? hostingNameStr : "");
1903
1904 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001905 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 }
1907
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001908 StringBuilder buf = mStringBuilder;
1909 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 buf.append("Start proc ");
1911 buf.append(app.processName);
1912 buf.append(" for ");
1913 buf.append(hostingType);
1914 if (hostingNameStr != null) {
1915 buf.append(" ");
1916 buf.append(hostingNameStr);
1917 }
1918 buf.append(": pid=");
1919 buf.append(pid);
1920 buf.append(" uid=");
1921 buf.append(uid);
1922 buf.append(" gids={");
1923 if (gids != null) {
1924 for (int gi=0; gi<gids.length; gi++) {
1925 if (gi != 0) buf.append(", ");
1926 buf.append(gids[gi]);
1927
1928 }
1929 }
1930 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001931 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 if (pid == 0 || pid == MY_PID) {
1933 // Processes are being emulated with threads.
1934 app.pid = MY_PID;
1935 app.removed = false;
1936 mStartingProcesses.add(app);
1937 } else if (pid > 0) {
1938 app.pid = pid;
1939 app.removed = false;
1940 synchronized (mPidsSelfLocked) {
1941 this.mPidsSelfLocked.put(pid, app);
1942 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1943 msg.obj = app;
1944 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1945 }
1946 } else {
1947 app.pid = 0;
1948 RuntimeException e = new RuntimeException(
1949 "Failure starting process " + app.processName
1950 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001951 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 }
1953 } catch (RuntimeException e) {
1954 // XXX do better error recovery.
1955 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001956 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 }
1958 }
1959
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001960 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 if (resumed) {
1962 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1963 } else {
1964 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1965 }
1966 }
1967
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001968 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001969 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1970 && mTopAction == null) {
1971 // We are running in factory test mode, but unable to find
1972 // the factory test app, so just sit around displaying the
1973 // error message and don't try to start anything.
1974 return false;
1975 }
1976 Intent intent = new Intent(
1977 mTopAction,
1978 mTopData != null ? Uri.parse(mTopData) : null);
1979 intent.setComponent(mTopComponent);
1980 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1981 intent.addCategory(Intent.CATEGORY_HOME);
1982 }
1983 ActivityInfo aInfo =
1984 intent.resolveActivityInfo(mContext.getPackageManager(),
1985 STOCK_PM_FLAGS);
1986 if (aInfo != null) {
1987 intent.setComponent(new ComponentName(
1988 aInfo.applicationInfo.packageName, aInfo.name));
1989 // Don't do this if the home app is currently being
1990 // instrumented.
1991 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1992 aInfo.applicationInfo.uid);
1993 if (app == null || app.instrumentationClass == null) {
1994 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001995 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001996 null, null, 0, 0, 0, false, false);
1997 }
1998 }
1999
2000
2001 return true;
2002 }
2003
2004 /**
2005 * Starts the "new version setup screen" if appropriate.
2006 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002007 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002008 // Only do this once per boot.
2009 if (mCheckedForSetup) {
2010 return;
2011 }
2012
2013 // We will show this screen if the current one is a different
2014 // version than the last one shown, and we are not running in
2015 // low-level factory test mode.
2016 final ContentResolver resolver = mContext.getContentResolver();
2017 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2018 Settings.Secure.getInt(resolver,
2019 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2020 mCheckedForSetup = true;
2021
2022 // See if we should be showing the platform update setup UI.
2023 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2024 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2025 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2026
2027 // We don't allow third party apps to replace this.
2028 ResolveInfo ri = null;
2029 for (int i=0; ris != null && i<ris.size(); i++) {
2030 if ((ris.get(i).activityInfo.applicationInfo.flags
2031 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2032 ri = ris.get(i);
2033 break;
2034 }
2035 }
2036
2037 if (ri != null) {
2038 String vers = ri.activityInfo.metaData != null
2039 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2040 : null;
2041 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2042 vers = ri.activityInfo.applicationInfo.metaData.getString(
2043 Intent.METADATA_SETUP_VERSION);
2044 }
2045 String lastVers = Settings.Secure.getString(
2046 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2047 if (vers != null && !vers.equals(lastVers)) {
2048 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2049 intent.setComponent(new ComponentName(
2050 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002051 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002052 null, null, 0, 0, 0, false, false);
2053 }
2054 }
2055 }
2056 }
2057
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002058 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002059 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002060
2061 final int identHash = System.identityHashCode(r);
2062 updateUsageStats(r, true);
2063
2064 int i = mWatchers.beginBroadcast();
2065 while (i > 0) {
2066 i--;
2067 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2068 if (w != null) {
2069 try {
2070 w.activityResuming(identHash);
2071 } catch (RemoteException e) {
2072 }
2073 }
2074 }
2075 mWatchers.finishBroadcast();
2076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002078 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002079 final int N = mPendingActivityLaunches.size();
2080 if (N <= 0) {
2081 return;
2082 }
2083 for (int i=0; i<N; i++) {
2084 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002085 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002086 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2087 doResume && i == (N-1));
2088 }
2089 mPendingActivityLaunches.clear();
2090 }
2091
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002092 public final int startActivity(IApplicationThread caller,
2093 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2094 int grantedMode, IBinder resultTo,
2095 String resultWho, int requestCode, boolean onlyIfNeeded,
2096 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002097 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002098 grantedUriPermissions, grantedMode, resultTo, resultWho,
2099 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002100 }
2101
2102 public final WaitResult startActivityAndWait(IApplicationThread caller,
2103 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2104 int grantedMode, IBinder resultTo,
2105 String resultWho, int requestCode, boolean onlyIfNeeded,
2106 boolean debug) {
2107 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002108 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002109 grantedUriPermissions, grantedMode, resultTo, resultWho,
2110 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002111 return res;
2112 }
2113
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002114 public final int startActivityWithConfig(IApplicationThread caller,
2115 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2116 int grantedMode, IBinder resultTo,
2117 String resultWho, int requestCode, boolean onlyIfNeeded,
2118 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002119 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002120 grantedUriPermissions, grantedMode, resultTo, resultWho,
2121 requestCode, onlyIfNeeded, debug, null, config);
2122 }
2123
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002124 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002125 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002126 IBinder resultTo, String resultWho, int requestCode,
2127 int flagsMask, int flagsValues) {
2128 // Refuse possible leaked file descriptors
2129 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2130 throw new IllegalArgumentException("File descriptors passed in Intent");
2131 }
2132
2133 IIntentSender sender = intent.getTarget();
2134 if (!(sender instanceof PendingIntentRecord)) {
2135 throw new IllegalArgumentException("Bad PendingIntent object");
2136 }
2137
2138 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002139
2140 synchronized (this) {
2141 // If this is coming from the currently resumed activity, it is
2142 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002143 if (mMainStack.mResumedActivity != null
2144 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002145 Binder.getCallingUid()) {
2146 mAppSwitchesAllowedTime = 0;
2147 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002148 }
2149
2150 return pir.sendInner(0, fillInIntent, resolvedType,
2151 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2152 }
2153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 public boolean startNextMatchingActivity(IBinder callingActivity,
2155 Intent intent) {
2156 // Refuse possible leaked file descriptors
2157 if (intent != null && intent.hasFileDescriptors() == true) {
2158 throw new IllegalArgumentException("File descriptors passed in Intent");
2159 }
2160
2161 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002162 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 if (index < 0) {
2164 return false;
2165 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002166 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167 if (r.app == null || r.app.thread == null) {
2168 // The caller is not running... d'oh!
2169 return false;
2170 }
2171 intent = new Intent(intent);
2172 // The caller is not allowed to change the data.
2173 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2174 // And we are resetting to find the next component...
2175 intent.setComponent(null);
2176
2177 ActivityInfo aInfo = null;
2178 try {
2179 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002180 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002182 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183
2184 // Look for the original activity in the list...
2185 final int N = resolves != null ? resolves.size() : 0;
2186 for (int i=0; i<N; i++) {
2187 ResolveInfo rInfo = resolves.get(i);
2188 if (rInfo.activityInfo.packageName.equals(r.packageName)
2189 && rInfo.activityInfo.name.equals(r.info.name)) {
2190 // We found the current one... the next matching is
2191 // after it.
2192 i++;
2193 if (i<N) {
2194 aInfo = resolves.get(i).activityInfo;
2195 }
2196 break;
2197 }
2198 }
2199 } catch (RemoteException e) {
2200 }
2201
2202 if (aInfo == null) {
2203 // Nobody who is next!
2204 return false;
2205 }
2206
2207 intent.setComponent(new ComponentName(
2208 aInfo.applicationInfo.packageName, aInfo.name));
2209 intent.setFlags(intent.getFlags()&~(
2210 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2211 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2212 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2213 Intent.FLAG_ACTIVITY_NEW_TASK));
2214
2215 // Okay now we need to start the new activity, replacing the
2216 // currently running activity. This is a little tricky because
2217 // we want to start the new one as if the current one is finished,
2218 // but not finish the current one first so that there is no flicker.
2219 // And thus...
2220 final boolean wasFinishing = r.finishing;
2221 r.finishing = true;
2222
2223 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002224 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 final String resultWho = r.resultWho;
2226 final int requestCode = r.requestCode;
2227 r.resultTo = null;
2228 if (resultTo != null) {
2229 resultTo.removeResultsLocked(r, resultWho, requestCode);
2230 }
2231
2232 final long origId = Binder.clearCallingIdentity();
2233 // XXX we are not dealing with propagating grantedUriPermissions...
2234 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002235 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002237 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 Binder.restoreCallingIdentity(origId);
2239
2240 r.finishing = wasFinishing;
2241 if (res != START_SUCCESS) {
2242 return false;
2243 }
2244 return true;
2245 }
2246 }
2247
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002248 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 Intent intent, String resolvedType, IBinder resultTo,
2250 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002251
2252 // This is so super not safe, that only the system (or okay root)
2253 // can do it.
2254 final int callingUid = Binder.getCallingUid();
2255 if (callingUid != 0 && callingUid != Process.myUid()) {
2256 throw new SecurityException(
2257 "startActivityInPackage only available to the system");
2258 }
2259
The Android Open Source Project4df24232009-03-05 14:34:35 -08002260 final boolean componentSpecified = intent.getComponent() != null;
2261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 // Don't modify the client's object!
2263 intent = new Intent(intent);
2264
2265 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 ActivityInfo aInfo;
2267 try {
2268 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002269 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002271 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 aInfo = rInfo != null ? rInfo.activityInfo : null;
2273 } catch (RemoteException e) {
2274 aInfo = null;
2275 }
2276
2277 if (aInfo != null) {
2278 // Store the found target back into the intent, because now that
2279 // we have it we never want to do this again. For example, if the
2280 // user navigates back to this point in the history, we should
2281 // always restart the exact same activity.
2282 intent.setComponent(new ComponentName(
2283 aInfo.applicationInfo.packageName, aInfo.name));
2284 }
2285
2286 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002287 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002288 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002289 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 }
2291 }
2292
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002293 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002294 // Remove any existing entries that are the same kind of task.
2295 int N = mRecentTasks.size();
2296 for (int i=0; i<N; i++) {
2297 TaskRecord tr = mRecentTasks.get(i);
2298 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2299 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2300 mRecentTasks.remove(i);
2301 i--;
2302 N--;
2303 if (task.intent == null) {
2304 // If the new recent task we are adding is not fully
2305 // specified, then replace it with the existing recent task.
2306 task = tr;
2307 }
2308 }
2309 }
2310 if (N >= MAX_RECENT_TASKS) {
2311 mRecentTasks.remove(N-1);
2312 }
2313 mRecentTasks.add(0, task);
2314 }
2315
2316 public void setRequestedOrientation(IBinder token,
2317 int requestedOrientation) {
2318 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002319 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 if (index < 0) {
2321 return;
2322 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002323 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 final long origId = Binder.clearCallingIdentity();
2325 mWindowManager.setAppOrientation(r, requestedOrientation);
2326 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002327 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 r.mayFreezeScreenLocked(r.app) ? r : null);
2329 if (config != null) {
2330 r.frozenBeforeDestroy = true;
2331 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002332 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 }
2334 }
2335 Binder.restoreCallingIdentity(origId);
2336 }
2337 }
2338
2339 public int getRequestedOrientation(IBinder token) {
2340 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002341 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 if (index < 0) {
2343 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2344 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002345 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 return mWindowManager.getAppOrientation(r);
2347 }
2348 }
2349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 /**
2351 * This is the internal entry point for handling Activity.finish().
2352 *
2353 * @param token The Binder token referencing the Activity we want to finish.
2354 * @param resultCode Result code, if any, from this Activity.
2355 * @param resultData Result data (Intent), if any, from this Activity.
2356 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002357 * @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 -08002358 */
2359 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2360 // Refuse possible leaked file descriptors
2361 if (resultData != null && resultData.hasFileDescriptors() == true) {
2362 throw new IllegalArgumentException("File descriptors passed in Intent");
2363 }
2364
2365 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002366 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 if (next != null) {
2370 // ask watcher if this is allowed
2371 boolean resumeOK = true;
2372 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002373 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002375 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 }
2377
2378 if (!resumeOK) {
2379 return false;
2380 }
2381 }
2382 }
2383 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002384 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 resultData, "app-request");
2386 Binder.restoreCallingIdentity(origId);
2387 return res;
2388 }
2389 }
2390
Dianne Hackborn860755f2010-06-03 18:47:52 -07002391 public final void finishHeavyWeightApp() {
2392 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2393 != PackageManager.PERMISSION_GRANTED) {
2394 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2395 + Binder.getCallingPid()
2396 + ", uid=" + Binder.getCallingUid()
2397 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2398 Slog.w(TAG, msg);
2399 throw new SecurityException(msg);
2400 }
2401
2402 synchronized(this) {
2403 if (mHeavyWeightProcess == null) {
2404 return;
2405 }
2406
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002407 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002408 mHeavyWeightProcess.activities);
2409 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002410 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002411 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002412 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002413 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002414 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002415 null, "finish-heavy");
2416 }
2417 }
2418 }
2419
2420 mHeavyWeightProcess = null;
2421 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2422 }
2423 }
2424
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002425 public void crashApplication(int uid, int initialPid, String packageName,
2426 String message) {
2427 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2428 != PackageManager.PERMISSION_GRANTED) {
2429 String msg = "Permission Denial: crashApplication() from pid="
2430 + Binder.getCallingPid()
2431 + ", uid=" + Binder.getCallingUid()
2432 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2433 Slog.w(TAG, msg);
2434 throw new SecurityException(msg);
2435 }
2436
2437 synchronized(this) {
2438 ProcessRecord proc = null;
2439
2440 // Figure out which process to kill. We don't trust that initialPid
2441 // still has any relation to current pids, so must scan through the
2442 // list.
2443 synchronized (mPidsSelfLocked) {
2444 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2445 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2446 if (p.info.uid != uid) {
2447 continue;
2448 }
2449 if (p.pid == initialPid) {
2450 proc = p;
2451 break;
2452 }
2453 for (String str : p.pkgList) {
2454 if (str.equals(packageName)) {
2455 proc = p;
2456 }
2457 }
2458 }
2459 }
2460
2461 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002462 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002463 + " initialPid=" + initialPid
2464 + " packageName=" + packageName);
2465 return;
2466 }
2467
2468 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002469 if (proc.pid == Process.myPid()) {
2470 Log.w(TAG, "crashApplication: trying to crash self!");
2471 return;
2472 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002473 long ident = Binder.clearCallingIdentity();
2474 try {
2475 proc.thread.scheduleCrash(message);
2476 } catch (RemoteException e) {
2477 }
2478 Binder.restoreCallingIdentity(ident);
2479 }
2480 }
2481 }
2482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483 public final void finishSubActivity(IBinder token, String resultWho,
2484 int requestCode) {
2485 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002486 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 if (index < 0) {
2488 return;
2489 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002490 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491
2492 final long origId = Binder.clearCallingIdentity();
2493
2494 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002495 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2496 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 if (r.resultTo == self && r.requestCode == requestCode) {
2498 if ((r.resultWho == null && resultWho == null) ||
2499 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002500 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 Activity.RESULT_CANCELED, null, "request-sub");
2502 }
2503 }
2504 }
2505
2506 Binder.restoreCallingIdentity(origId);
2507 }
2508 }
2509
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002510 public boolean willActivityBeVisible(IBinder token) {
2511 synchronized(this) {
2512 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2514 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002515 if (r == token) {
2516 return true;
2517 }
2518 if (r.fullscreen && !r.finishing) {
2519 return false;
2520 }
2521 }
2522 return true;
2523 }
2524 }
2525
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002526 public void overridePendingTransition(IBinder token, String packageName,
2527 int enterAnim, int exitAnim) {
2528 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002529 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002530 if (index < 0) {
2531 return;
2532 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002534
2535 final long origId = Binder.clearCallingIdentity();
2536
2537 if (self.state == ActivityState.RESUMED
2538 || self.state == ActivityState.PAUSING) {
2539 mWindowManager.overridePendingAppTransition(packageName,
2540 enterAnim, exitAnim);
2541 }
2542
2543 Binder.restoreCallingIdentity(origId);
2544 }
2545 }
2546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 * Main function for removing an existing process from the activity manager
2549 * as a result of that process going away. Clears out all connections
2550 * to the process.
2551 */
2552 private final void handleAppDiedLocked(ProcessRecord app,
2553 boolean restarting) {
2554 cleanUpApplicationRecordLocked(app, restarting, -1);
2555 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002556 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
2558
2559 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2561 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2562 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002564 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2565 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 }
2567
2568 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570
2571 boolean atTop = true;
2572 boolean hasVisibleActivities = false;
2573
2574 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002575 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002576 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 TAG, "Removing app " + app + " from history with " + i + " entries");
2578 while (i > 0) {
2579 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2583 if (r.app == app) {
2584 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002585 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 TAG, "Removing this entry! frozen=" + r.haveState
2587 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002588 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589
2590 r.inHistory = false;
2591 mWindowManager.removeAppToken(r);
2592 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002595 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596
2597 } else {
2598 // We have the current state for this activity, so
2599 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002600 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 TAG, "Keeping entry, setting app to null");
2602 if (r.visible) {
2603 hasVisibleActivities = true;
2604 }
2605 r.app = null;
2606 r.nowVisible = false;
2607 if (!r.haveState) {
2608 r.icicle = null;
2609 }
2610 }
2611
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002612 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 r.state = ActivityState.STOPPED;
2614 }
2615 atTop = false;
2616 }
2617
2618 app.activities.clear();
2619
2620 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002621 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 + " running instrumentation " + app.instrumentationClass);
2623 Bundle info = new Bundle();
2624 info.putString("shortMsg", "Process crashed.");
2625 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2626 }
2627
2628 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002629 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 // If there was nothing to resume, and we are not already
2631 // restarting this process, but there is a visible activity that
2632 // is hosted by the process... then make sure all visible
2633 // activities are running, taking care of restarting this
2634 // process.
2635 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002636 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 }
2638 }
2639 }
2640 }
2641
2642 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2643 IBinder threadBinder = thread.asBinder();
2644
2645 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002646 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2647 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2649 return i;
2650 }
2651 }
2652 return -1;
2653 }
2654
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002655 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 IApplicationThread thread) {
2657 if (thread == null) {
2658 return null;
2659 }
2660
2661 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002662 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 }
2664
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002665 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666 IApplicationThread thread) {
2667
2668 mProcDeaths[0]++;
2669
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002670 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2671 synchronized (stats) {
2672 stats.noteProcessDiedLocked(app.info.uid, pid);
2673 }
2674
Magnus Edlund7bb25812010-02-24 15:45:06 +01002675 // Clean up already done if the process has been re-started.
2676 if (app.pid == pid && app.thread != null &&
2677 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002678 if (!app.killedBackground) {
2679 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2680 + ") has died.");
2681 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002682 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002683 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 TAG, "Dying app: " + app + ", pid: " + pid
2685 + ", thread: " + thread.asBinder());
2686 boolean doLowMem = app.instrumentationClass == null;
2687 handleAppDiedLocked(app, false);
2688
2689 if (doLowMem) {
2690 // If there are no longer any background processes running,
2691 // and the app that died was not running instrumentation,
2692 // then tell everyone we are now low on memory.
2693 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002694 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2695 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2697 haveBg = true;
2698 break;
2699 }
2700 }
2701
2702 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002704 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002705 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002706 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2707 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002708 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002709 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2710 // The low memory report is overriding any current
2711 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002712 // heavy/important/visible/foreground processes first.
2713 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002714 rec.lastRequestedGc = 0;
2715 } else {
2716 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002718 rec.reportLowMemory = true;
2719 rec.lastLowMemory = now;
2720 mProcessesToGc.remove(rec);
2721 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
2723 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002724 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 }
2726 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002727 } else if (app.pid != pid) {
2728 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002729 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002730 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002731 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002732 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002733 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 + thread.asBinder());
2735 }
2736 }
2737
Dan Egnor42471dd2010-01-07 17:25:22 -08002738 /**
2739 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002740 * @param clearTraces causes the dump file to be erased prior to the new
2741 * traces being written, if true; when false, the new traces will be
2742 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002743 * @param firstPids of dalvik VM processes to dump stack traces for first
2744 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002745 * @return file containing stack traces, or null if no dump file is configured
2746 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002747 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2748 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002749 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2750 if (tracesPath == null || tracesPath.length() == 0) {
2751 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002753
2754 File tracesFile = new File(tracesPath);
2755 try {
2756 File tracesDir = tracesFile.getParentFile();
2757 if (!tracesDir.exists()) tracesFile.mkdirs();
2758 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2759
Christopher Tate6ee412d2010-05-28 12:01:56 -07002760 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002761 tracesFile.createNewFile();
2762 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2763 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002764 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002765 return null;
2766 }
2767
2768 // Use a FileObserver to detect when traces finish writing.
2769 // The order of traces is considered important to maintain for legibility.
2770 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2771 public synchronized void onEvent(int event, String path) { notify(); }
2772 };
2773
2774 try {
2775 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002776
2777 // First collect all of the stacks of the most important pids.
2778 try {
2779 int num = firstPids.size();
2780 for (int i = 0; i < num; i++) {
2781 synchronized (observer) {
2782 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2783 observer.wait(200); // Wait for write-close, give up after 200msec
2784 }
2785 }
2786 } catch (InterruptedException e) {
2787 Log.wtf(TAG, e);
2788 }
2789
2790 // Next measure CPU usage.
2791 if (processStats != null) {
2792 processStats.init();
2793 System.gc();
2794 processStats.update();
2795 try {
2796 synchronized (processStats) {
2797 processStats.wait(500); // measure over 1/2 second.
2798 }
2799 } catch (InterruptedException e) {
2800 }
2801 processStats.update();
2802
2803 // We'll take the stack crawls of just the top apps using CPU.
2804 final int N = processStats.countWorkingStats();
2805 int numProcs = 0;
2806 for (int i=0; i<N && numProcs<5; i++) {
2807 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2808 if (lastPids.indexOfKey(stats.pid) >= 0) {
2809 numProcs++;
2810 try {
2811 synchronized (observer) {
2812 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2813 observer.wait(200); // Wait for write-close, give up after 200msec
2814 }
2815 } catch (InterruptedException e) {
2816 Log.wtf(TAG, e);
2817 }
2818
2819 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002820 }
2821 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002822
2823 return tracesFile;
2824
Dan Egnor42471dd2010-01-07 17:25:22 -08002825 } finally {
2826 observer.stopWatching();
2827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 }
2829
Jeff Brown4d94a762010-09-23 11:33:28 -07002830 private final class AppNotResponding implements Runnable {
2831 private final ProcessRecord mApp;
2832 private final String mAnnotation;
2833
2834 public AppNotResponding(ProcessRecord app, String annotation) {
2835 mApp = app;
2836 mAnnotation = annotation;
2837 }
2838
2839 @Override
2840 public void run() {
2841 appNotResponding(mApp, null, null, mAnnotation);
2842 }
2843 }
2844
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002845 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2846 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002847 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2848 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2849
Dianne Hackborn287952c2010-09-22 22:34:31 -07002850 if (mController != null) {
2851 try {
2852 // 0 == continue, -1 = kill process immediately
2853 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2854 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2855 } catch (RemoteException e) {
2856 mController = null;
2857 }
2858 }
2859
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002860 long anrTime = SystemClock.uptimeMillis();
2861 if (MONITOR_CPU_USAGE) {
2862 updateCpuStatsNow();
2863 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002864
2865 synchronized (this) {
2866 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2867 if (mShuttingDown) {
2868 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2869 return;
2870 } else if (app.notResponding) {
2871 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2872 return;
2873 } else if (app.crashing) {
2874 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2875 return;
2876 }
2877
2878 // In case we come through here for the same app before completing
2879 // this one, mark as anring now so we will bail out.
2880 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002881
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002882 // Log the ANR to the event log.
2883 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2884 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002885
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002886 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002887 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002888
2889 int parentPid = app.pid;
2890 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002891 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002892
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002893 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002894
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002895 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2896 ProcessRecord r = mLruProcesses.get(i);
2897 if (r != null && r.thread != null) {
2898 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002899 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2900 if (r.persistent) {
2901 firstPids.add(pid);
2902 } else {
2903 lastPids.put(pid, Boolean.TRUE);
2904 }
2905 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 }
2908 }
2909
Dan Egnor42471dd2010-01-07 17:25:22 -08002910 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002911 StringBuilder info = mStringBuilder;
2912 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002913 info.append("ANR in ").append(app.processName);
2914 if (activity != null && activity.shortComponentName != null) {
2915 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002916 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002917 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002919 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002921 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002922 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924
Dianne Hackborn287952c2010-09-22 22:34:31 -07002925 final ProcessStats processStats = new ProcessStats(true);
2926
2927 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2928
Dan Egnor42471dd2010-01-07 17:25:22 -08002929 String cpuInfo = null;
2930 if (MONITOR_CPU_USAGE) {
2931 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002932 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002933 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002934 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002935 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002936 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 }
2938
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002939 info.append(processStats.printCurrentState(anrTime));
2940
Joe Onorato8a9b2202010-02-26 18:56:32 -08002941 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002942 if (tracesFile == null) {
2943 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2944 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2945 }
2946
2947 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2948
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002949 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002951 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2952 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002954 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2955 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 }
2957 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002958 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 }
2960 }
2961
Dan Egnor42471dd2010-01-07 17:25:22 -08002962 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2963 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2964 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002965
2966 synchronized (this) {
2967 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2968 Process.killProcess(app.pid);
2969 return;
2970 }
2971
2972 // Set the app's notResponding state, and look up the errorReportReceiver
2973 makeAppNotRespondingLocked(app,
2974 activity != null ? activity.shortComponentName : null,
2975 annotation != null ? "ANR " + annotation : "ANR",
2976 info.toString());
2977
2978 // Bring up the infamous App Not Responding dialog
2979 Message msg = Message.obtain();
2980 HashMap map = new HashMap();
2981 msg.what = SHOW_NOT_RESPONDING_MSG;
2982 msg.obj = map;
2983 map.put("app", app);
2984 if (activity != null) {
2985 map.put("activity", activity);
2986 }
2987
2988 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002992 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2993 if (!mLaunchWarningShown) {
2994 mLaunchWarningShown = true;
2995 mHandler.post(new Runnable() {
2996 @Override
2997 public void run() {
2998 synchronized (ActivityManagerService.this) {
2999 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3000 d.show();
3001 mHandler.postDelayed(new Runnable() {
3002 @Override
3003 public void run() {
3004 synchronized (ActivityManagerService.this) {
3005 d.dismiss();
3006 mLaunchWarningShown = false;
3007 }
3008 }
3009 }, 4000);
3010 }
3011 }
3012 });
3013 }
3014 }
3015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 public boolean clearApplicationUserData(final String packageName,
3017 final IPackageDataObserver observer) {
3018 int uid = Binder.getCallingUid();
3019 int pid = Binder.getCallingPid();
3020 long callingId = Binder.clearCallingIdentity();
3021 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003022 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 int pkgUid = -1;
3024 synchronized(this) {
3025 try {
3026 pkgUid = pm.getPackageUid(packageName);
3027 } catch (RemoteException e) {
3028 }
3029 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003030 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 return false;
3032 }
3033 if (uid == pkgUid || checkComponentPermission(
3034 android.Manifest.permission.CLEAR_APP_USER_DATA,
3035 pid, uid, -1)
3036 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003037 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 } else {
3039 throw new SecurityException(pid+" does not have permission:"+
3040 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3041 "for process:"+packageName);
3042 }
3043 }
3044
3045 try {
3046 //clear application user data
3047 pm.clearApplicationUserData(packageName, observer);
3048 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3049 Uri.fromParts("package", packageName, null));
3050 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003051 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3052 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 } catch (RemoteException e) {
3054 }
3055 } finally {
3056 Binder.restoreCallingIdentity(callingId);
3057 }
3058 return true;
3059 }
3060
Dianne Hackborn03abb812010-01-04 18:43:19 -08003061 public void killBackgroundProcesses(final String packageName) {
3062 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3063 != PackageManager.PERMISSION_GRANTED &&
3064 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3065 != PackageManager.PERMISSION_GRANTED) {
3066 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 + Binder.getCallingPid()
3068 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003069 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003070 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003071 throw new SecurityException(msg);
3072 }
3073
3074 long callingId = Binder.clearCallingIdentity();
3075 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003076 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 int pkgUid = -1;
3078 synchronized(this) {
3079 try {
3080 pkgUid = pm.getPackageUid(packageName);
3081 } catch (RemoteException e) {
3082 }
3083 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003084 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 return;
3086 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003087 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003088 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003089 }
3090 } finally {
3091 Binder.restoreCallingIdentity(callingId);
3092 }
3093 }
3094
3095 public void forceStopPackage(final String packageName) {
3096 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3097 != PackageManager.PERMISSION_GRANTED) {
3098 String msg = "Permission Denial: forceStopPackage() from pid="
3099 + Binder.getCallingPid()
3100 + ", uid=" + Binder.getCallingUid()
3101 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003102 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003103 throw new SecurityException(msg);
3104 }
3105
3106 long callingId = Binder.clearCallingIdentity();
3107 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003108 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003109 int pkgUid = -1;
3110 synchronized(this) {
3111 try {
3112 pkgUid = pm.getPackageUid(packageName);
3113 } catch (RemoteException e) {
3114 }
3115 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003116 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003117 return;
3118 }
3119 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003120 }
3121 } finally {
3122 Binder.restoreCallingIdentity(callingId);
3123 }
3124 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003125
3126 /*
3127 * The pkg name and uid have to be specified.
3128 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3129 */
3130 public void killApplicationWithUid(String pkg, int uid) {
3131 if (pkg == null) {
3132 return;
3133 }
3134 // Make sure the uid is valid.
3135 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003136 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003137 return;
3138 }
3139 int callerUid = Binder.getCallingUid();
3140 // Only the system server can kill an application
3141 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003142 // Post an aysnc message to kill the application
3143 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3144 msg.arg1 = uid;
3145 msg.arg2 = 0;
3146 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003147 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003148 } else {
3149 throw new SecurityException(callerUid + " cannot kill pkg: " +
3150 pkg);
3151 }
3152 }
3153
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003154 public void closeSystemDialogs(String reason) {
3155 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003156 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003157 if (reason != null) {
3158 intent.putExtra("reason", reason);
3159 }
3160
3161 final int uid = Binder.getCallingUid();
3162 final long origId = Binder.clearCallingIdentity();
3163 synchronized (this) {
3164 int i = mWatchers.beginBroadcast();
3165 while (i > 0) {
3166 i--;
3167 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3168 if (w != null) {
3169 try {
3170 w.closingSystemDialogs(reason);
3171 } catch (RemoteException e) {
3172 }
3173 }
3174 }
3175 mWatchers.finishBroadcast();
3176
Dianne Hackbornffa42482009-09-23 22:20:11 -07003177 mWindowManager.closeSystemDialogs(reason);
3178
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003179 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3180 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003181 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003182 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003183 Activity.RESULT_CANCELED, null, "close-sys");
3184 }
3185 }
3186
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003187 broadcastIntentLocked(null, null, intent, null,
3188 null, 0, null, null, null, false, false, -1, uid);
3189 }
3190 Binder.restoreCallingIdentity(origId);
3191 }
3192
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003193 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003194 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003195 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3196 for (int i=pids.length-1; i>=0; i--) {
3197 infos[i] = new Debug.MemoryInfo();
3198 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003199 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003200 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003201 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003202
3203 public void killApplicationProcess(String processName, int uid) {
3204 if (processName == null) {
3205 return;
3206 }
3207
3208 int callerUid = Binder.getCallingUid();
3209 // Only the system server can kill an application
3210 if (callerUid == Process.SYSTEM_UID) {
3211 synchronized (this) {
3212 ProcessRecord app = getProcessRecordLocked(processName, uid);
3213 if (app != null) {
3214 try {
3215 app.thread.scheduleSuicide();
3216 } catch (RemoteException e) {
3217 // If the other end already died, then our work here is done.
3218 }
3219 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003220 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003221 + processName + " / " + uid);
3222 }
3223 }
3224 } else {
3225 throw new SecurityException(callerUid + " cannot kill app process: " +
3226 processName);
3227 }
3228 }
3229
Dianne Hackborn03abb812010-01-04 18:43:19 -08003230 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003231 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3233 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003234 if (!mProcessesReady) {
3235 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 intent.putExtra(Intent.EXTRA_UID, uid);
3238 broadcastIntentLocked(null, null, intent,
3239 null, null, 0, null, null, null,
3240 false, false, MY_PID, Process.SYSTEM_UID);
3241 }
3242
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003243 private final boolean killPackageProcessesLocked(String packageName, int uid,
3244 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003245 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246
Dianne Hackborn03abb812010-01-04 18:43:19 -08003247 // Remove all processes this package may have touched: all with the
3248 // same UID (except for the system or root user), and all whose name
3249 // matches the package name.
3250 final String procNamePrefix = packageName + ":";
3251 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3252 final int NA = apps.size();
3253 for (int ia=0; ia<NA; ia++) {
3254 ProcessRecord app = apps.valueAt(ia);
3255 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003256 if (doit) {
3257 procs.add(app);
3258 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003259 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3260 || app.processName.equals(packageName)
3261 || app.processName.startsWith(procNamePrefix)) {
3262 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003263 if (!doit) {
3264 return true;
3265 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003266 app.removed = true;
3267 procs.add(app);
3268 }
3269 }
3270 }
3271 }
3272
3273 int N = procs.size();
3274 for (int i=0; i<N; i++) {
3275 removeProcessLocked(procs.get(i), callerWillRestart);
3276 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003277 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003278 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003279
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003280 private final boolean forceStopPackageLocked(String name, int uid,
3281 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 int i, N;
3283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 if (uid < 0) {
3285 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003286 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 } catch (RemoteException e) {
3288 }
3289 }
3290
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003291 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003292 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003293
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003294 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3295 while (badApps.hasNext()) {
3296 SparseArray<Long> ba = badApps.next();
3297 if (ba.get(uid) != null) {
3298 badApps.remove();
3299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 }
3301 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003302
3303 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3304 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003306 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3307 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003309 if (!doit) {
3310 return true;
3311 }
3312 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 if (r.app != null) {
3315 r.app.removed = true;
3316 }
3317 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003318 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 }
3320 }
3321
3322 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3323 for (ServiceRecord service : mServices.values()) {
3324 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003325 if (!doit) {
3326 return true;
3327 }
3328 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003329 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 if (service.app != null) {
3331 service.app.removed = true;
3332 }
3333 service.app = null;
3334 services.add(service);
3335 }
3336 }
3337
3338 N = services.size();
3339 for (i=0; i<N; i++) {
3340 bringDownServiceLocked(services.get(i), true);
3341 }
3342
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003343 if (doit) {
3344 if (purgeCache) {
3345 AttributeCache ac = AttributeCache.instance();
3346 if (ac != null) {
3347 ac.removePackage(name);
3348 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003349 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003350 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003351 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003352
3353 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 }
3355
3356 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3357 final String name = app.processName;
3358 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003359 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 TAG, "Force removing process " + app + " (" + name
3361 + "/" + uid + ")");
3362
3363 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003364 if (mHeavyWeightProcess == app) {
3365 mHeavyWeightProcess = null;
3366 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 boolean needRestart = false;
3369 if (app.pid > 0 && app.pid != MY_PID) {
3370 int pid = app.pid;
3371 synchronized (mPidsSelfLocked) {
3372 mPidsSelfLocked.remove(pid);
3373 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3374 }
3375 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003376 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 Process.killProcess(pid);
3378
3379 if (app.persistent) {
3380 if (!callerWillRestart) {
3381 addAppLocked(app.info);
3382 } else {
3383 needRestart = true;
3384 }
3385 }
3386 } else {
3387 mRemovedProcesses.add(app);
3388 }
3389
3390 return needRestart;
3391 }
3392
3393 private final void processStartTimedOutLocked(ProcessRecord app) {
3394 final int pid = app.pid;
3395 boolean gone = false;
3396 synchronized (mPidsSelfLocked) {
3397 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3398 if (knownApp != null && knownApp.thread == null) {
3399 mPidsSelfLocked.remove(pid);
3400 gone = true;
3401 }
3402 }
3403
3404 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003405 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003406 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003407 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003409 if (mHeavyWeightProcess == app) {
3410 mHeavyWeightProcess = null;
3411 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3412 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003413 // Take care of any launching providers waiting for this process.
3414 checkAppInLaunchingProvidersLocked(app, true);
3415 // Take care of any services that are waiting for the process.
3416 for (int i=0; i<mPendingServices.size(); i++) {
3417 ServiceRecord sr = mPendingServices.get(i);
3418 if (app.info.uid == sr.appInfo.uid
3419 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003420 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003421 mPendingServices.remove(i);
3422 i--;
3423 bringDownServiceLocked(sr, true);
3424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003426 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003427 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003428 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003429 try {
3430 IBackupManager bm = IBackupManager.Stub.asInterface(
3431 ServiceManager.getService(Context.BACKUP_SERVICE));
3432 bm.agentDisconnected(app.info.packageName);
3433 } catch (RemoteException e) {
3434 // Can't happen; the backup manager is local
3435 }
3436 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003437 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003438 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003439 mPendingBroadcast.state = BroadcastRecord.IDLE;
3440 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003441 mPendingBroadcast = null;
3442 scheduleBroadcastsLocked();
3443 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003445 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 }
3447 }
3448
3449 private final boolean attachApplicationLocked(IApplicationThread thread,
3450 int pid) {
3451
3452 // Find the application record that is being attached... either via
3453 // the pid if we are running in multiple processes, or just pull the
3454 // next app record if we are emulating process with anonymous threads.
3455 ProcessRecord app;
3456 if (pid != MY_PID && pid >= 0) {
3457 synchronized (mPidsSelfLocked) {
3458 app = mPidsSelfLocked.get(pid);
3459 }
3460 } else if (mStartingProcesses.size() > 0) {
3461 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003462 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463 } else {
3464 app = null;
3465 }
3466
3467 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003468 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003470 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 if (pid > 0 && pid != MY_PID) {
3472 Process.killProcess(pid);
3473 } else {
3474 try {
3475 thread.scheduleExit();
3476 } catch (Exception e) {
3477 // Ignore exceptions.
3478 }
3479 }
3480 return false;
3481 }
3482
3483 // If this application record is still attached to a previous
3484 // process, clean it up now.
3485 if (app.thread != null) {
3486 handleAppDiedLocked(app, true);
3487 }
3488
3489 // Tell the process all about itself.
3490
Joe Onorato8a9b2202010-02-26 18:56:32 -08003491 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 TAG, "Binding process pid " + pid + " to record " + app);
3493
3494 String processName = app.processName;
3495 try {
3496 thread.asBinder().linkToDeath(new AppDeathRecipient(
3497 app, pid, thread), 0);
3498 } catch (RemoteException e) {
3499 app.resetPackageList();
3500 startProcessLocked(app, "link fail", processName);
3501 return false;
3502 }
3503
Doug Zongker2bec3d42009-12-04 12:52:44 -08003504 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505
3506 app.thread = thread;
3507 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003508 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3509 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 app.forcingToForeground = null;
3511 app.foregroundServices = false;
3512 app.debugging = false;
3513
3514 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3515
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003516 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003517 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003519 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003520 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003521 }
3522
Joe Onorato8a9b2202010-02-26 18:56:32 -08003523 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 TAG, "New app record " + app
3525 + " thread=" + thread.asBinder() + " pid=" + pid);
3526 try {
3527 int testMode = IApplicationThread.DEBUG_OFF;
3528 if (mDebugApp != null && mDebugApp.equals(processName)) {
3529 testMode = mWaitForDebugger
3530 ? IApplicationThread.DEBUG_WAIT
3531 : IApplicationThread.DEBUG_ON;
3532 app.debugging = true;
3533 if (mDebugTransient) {
3534 mDebugApp = mOrigDebugApp;
3535 mWaitForDebugger = mOrigWaitForDebugger;
3536 }
3537 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003538
Christopher Tate181fafa2009-05-14 11:12:14 -07003539 // If the app is being launched for restore or full backup, set it up specially
3540 boolean isRestrictedBackupMode = false;
3541 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3542 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3543 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3544 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003545
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003546 ensurePackageDexOpt(app.instrumentationInfo != null
3547 ? app.instrumentationInfo.packageName
3548 : app.info.packageName);
3549 if (app.instrumentationClass != null) {
3550 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003551 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003552 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003553 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003554 thread.bindApplication(processName, app.instrumentationInfo != null
3555 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 app.instrumentationClass, app.instrumentationProfileFile,
3557 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003558 isRestrictedBackupMode || !normalMode,
3559 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003560 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003561 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 } catch (Exception e) {
3563 // todo: Yikes! What should we do? For now we will try to
3564 // start another process, but that could easily get us in
3565 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003566 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567
3568 app.resetPackageList();
3569 startProcessLocked(app, "bind fail", processName);
3570 return false;
3571 }
3572
3573 // Remove this record from the list of starting applications.
3574 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003575 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3576 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 mProcessesOnHold.remove(app);
3578
3579 boolean badApp = false;
3580 boolean didSomething = false;
3581
3582 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003583 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003584 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3586 && processName.equals(hr.processName)) {
3587 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003588 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 didSomething = true;
3590 }
3591 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003592 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 + hr.intent.getComponent().flattenToShortString(), e);
3594 badApp = true;
3595 }
3596 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003597 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 }
3599 }
3600
3601 // Find any services that should be running in this process...
3602 if (!badApp && mPendingServices.size() > 0) {
3603 ServiceRecord sr = null;
3604 try {
3605 for (int i=0; i<mPendingServices.size(); i++) {
3606 sr = mPendingServices.get(i);
3607 if (app.info.uid != sr.appInfo.uid
3608 || !processName.equals(sr.processName)) {
3609 continue;
3610 }
3611
3612 mPendingServices.remove(i);
3613 i--;
3614 realStartServiceLocked(sr, app);
3615 didSomething = true;
3616 }
3617 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003618 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 + sr.shortName, e);
3620 badApp = true;
3621 }
3622 }
3623
3624 // Check if the next broadcast receiver is in this process...
3625 BroadcastRecord br = mPendingBroadcast;
3626 if (!badApp && br != null && br.curApp == app) {
3627 try {
3628 mPendingBroadcast = null;
3629 processCurBroadcastLocked(br, app);
3630 didSomething = true;
3631 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003632 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 + br.curComponent.flattenToShortString(), e);
3634 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003635 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3637 br.resultExtras, br.resultAbort, true);
3638 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003639 // We need to reset the state if we fails to start the receiver.
3640 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 }
3642 }
3643
Christopher Tate181fafa2009-05-14 11:12:14 -07003644 // Check whether the next backup agent is in this process...
3645 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003646 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003647 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003648 try {
3649 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3650 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003651 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003652 e.printStackTrace();
3653 }
3654 }
3655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 if (badApp) {
3657 // todo: Also need to kill application to deal with all
3658 // kinds of exceptions.
3659 handleAppDiedLocked(app, false);
3660 return false;
3661 }
3662
3663 if (!didSomething) {
3664 updateOomAdjLocked();
3665 }
3666
3667 return true;
3668 }
3669
3670 public final void attachApplication(IApplicationThread thread) {
3671 synchronized (this) {
3672 int callingPid = Binder.getCallingPid();
3673 final long origId = Binder.clearCallingIdentity();
3674 attachApplicationLocked(thread, callingPid);
3675 Binder.restoreCallingIdentity(origId);
3676 }
3677 }
3678
Dianne Hackborne88846e2009-09-30 21:34:25 -07003679 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003681 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 Binder.restoreCallingIdentity(origId);
3683 }
3684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003686 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003687 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 mWindowManager.enableScreenAfterBoot();
3689 }
3690
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003691 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003692 IntentFilter pkgFilter = new IntentFilter();
3693 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3694 pkgFilter.addDataScheme("package");
3695 mContext.registerReceiver(new BroadcastReceiver() {
3696 @Override
3697 public void onReceive(Context context, Intent intent) {
3698 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3699 if (pkgs != null) {
3700 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003701 synchronized (ActivityManagerService.this) {
3702 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3703 setResultCode(Activity.RESULT_OK);
3704 return;
3705 }
3706 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003707 }
3708 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003709 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003710 }, pkgFilter);
3711
3712 synchronized (this) {
3713 // Ensure that any processes we had put on hold are now started
3714 // up.
3715 final int NP = mProcessesOnHold.size();
3716 if (NP > 0) {
3717 ArrayList<ProcessRecord> procs =
3718 new ArrayList<ProcessRecord>(mProcessesOnHold);
3719 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003720 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3721 + procs.get(ip));
3722 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003723 }
3724 }
3725
3726 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003727 // Start looking for apps that are abusing wake locks.
3728 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003729 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003730 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003731 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003732 broadcastIntentLocked(null, null,
3733 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3734 null, null, 0, null, null,
3735 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3736 false, false, MY_PID, Process.SYSTEM_UID);
3737 }
3738 }
3739 }
3740
3741 final void ensureBootCompleted() {
3742 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003743 boolean enableScreen;
3744 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003745 booting = mBooting;
3746 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003747 enableScreen = !mBooted;
3748 mBooted = true;
3749 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003750
3751 if (booting) {
3752 finishBooting();
3753 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003754
3755 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003756 enableScreenAfterBoot();
3757 }
3758 }
3759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 public final void activityPaused(IBinder token, Bundle icicle) {
3761 // Refuse possible leaked file descriptors
3762 if (icicle != null && icicle.hasFileDescriptors()) {
3763 throw new IllegalArgumentException("File descriptors passed in Bundle");
3764 }
3765
3766 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003767 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003768 Binder.restoreCallingIdentity(origId);
3769 }
3770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 public final void activityStopped(IBinder token, Bitmap thumbnail,
3772 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003773 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 TAG, "Activity stopped: token=" + token);
3775
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003776 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777
3778 final long origId = Binder.clearCallingIdentity();
3779
3780 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003781 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003783 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 r.thumbnail = thumbnail;
3785 r.description = description;
3786 r.stopped = true;
3787 r.state = ActivityState.STOPPED;
3788 if (!r.finishing) {
3789 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003790 r.stack.destroyActivityLocked(r, true);
3791 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 }
3793 }
3794 }
3795 }
3796
3797 if (r != null) {
3798 sendPendingThumbnail(r, null, null, null, false);
3799 }
3800
3801 trimApplications();
3802
3803 Binder.restoreCallingIdentity(origId);
3804 }
3805
3806 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003807 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003808 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 }
3810
3811 public String getCallingPackage(IBinder token) {
3812 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003813 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003814 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 }
3816 }
3817
3818 public ComponentName getCallingActivity(IBinder token) {
3819 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003820 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 return r != null ? r.intent.getComponent() : null;
3822 }
3823 }
3824
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003825 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003826 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003828 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 if (r != null) {
3830 return r.resultTo;
3831 }
3832 }
3833 return null;
3834 }
3835
3836 public ComponentName getActivityClassForToken(IBinder token) {
3837 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003838 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003840 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 return r.intent.getComponent();
3842 }
3843 return null;
3844 }
3845 }
3846
3847 public String getPackageForToken(IBinder token) {
3848 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003849 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003851 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 return r.packageName;
3853 }
3854 return null;
3855 }
3856 }
3857
3858 public IIntentSender getIntentSender(int type,
3859 String packageName, IBinder token, String resultWho,
3860 int requestCode, Intent intent, String resolvedType, int flags) {
3861 // Refuse possible leaked file descriptors
3862 if (intent != null && intent.hasFileDescriptors() == true) {
3863 throw new IllegalArgumentException("File descriptors passed in Intent");
3864 }
3865
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003866 if (type == INTENT_SENDER_BROADCAST) {
3867 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3868 throw new IllegalArgumentException(
3869 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3870 }
3871 }
3872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 synchronized(this) {
3874 int callingUid = Binder.getCallingUid();
3875 try {
3876 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3877 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003878 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 .getPackageUid(packageName);
3880 if (uid != Binder.getCallingUid()) {
3881 String msg = "Permission Denial: getIntentSender() from pid="
3882 + Binder.getCallingPid()
3883 + ", uid=" + Binder.getCallingUid()
3884 + ", (need uid=" + uid + ")"
3885 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003886 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 throw new SecurityException(msg);
3888 }
3889 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003890
3891 return getIntentSenderLocked(type, packageName, callingUid,
3892 token, resultWho, requestCode, intent, resolvedType, flags);
3893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 } catch (RemoteException e) {
3895 throw new SecurityException(e);
3896 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003897 }
3898 }
3899
3900 IIntentSender getIntentSenderLocked(int type,
3901 String packageName, int callingUid, IBinder token, String resultWho,
3902 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003903 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003904 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003905 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003906 if (index < 0) {
3907 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003908 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003909 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003910 if (activity.finishing) {
3911 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003913 }
3914
3915 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3916 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3917 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3918 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3919 |PendingIntent.FLAG_UPDATE_CURRENT);
3920
3921 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3922 type, packageName, activity, resultWho,
3923 requestCode, intent, resolvedType, flags);
3924 WeakReference<PendingIntentRecord> ref;
3925 ref = mIntentSenderRecords.get(key);
3926 PendingIntentRecord rec = ref != null ? ref.get() : null;
3927 if (rec != null) {
3928 if (!cancelCurrent) {
3929 if (updateCurrent) {
3930 rec.key.requestIntent.replaceExtras(intent);
3931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 return rec;
3933 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003934 rec.canceled = true;
3935 mIntentSenderRecords.remove(key);
3936 }
3937 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 return rec;
3939 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003940 rec = new PendingIntentRecord(this, key, callingUid);
3941 mIntentSenderRecords.put(key, rec.ref);
3942 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3943 if (activity.pendingResults == null) {
3944 activity.pendingResults
3945 = new HashSet<WeakReference<PendingIntentRecord>>();
3946 }
3947 activity.pendingResults.add(rec.ref);
3948 }
3949 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 }
3951
3952 public void cancelIntentSender(IIntentSender sender) {
3953 if (!(sender instanceof PendingIntentRecord)) {
3954 return;
3955 }
3956 synchronized(this) {
3957 PendingIntentRecord rec = (PendingIntentRecord)sender;
3958 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003959 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 .getPackageUid(rec.key.packageName);
3961 if (uid != Binder.getCallingUid()) {
3962 String msg = "Permission Denial: cancelIntentSender() from pid="
3963 + Binder.getCallingPid()
3964 + ", uid=" + Binder.getCallingUid()
3965 + " is not allowed to cancel packges "
3966 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003967 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 throw new SecurityException(msg);
3969 }
3970 } catch (RemoteException e) {
3971 throw new SecurityException(e);
3972 }
3973 cancelIntentSenderLocked(rec, true);
3974 }
3975 }
3976
3977 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3978 rec.canceled = true;
3979 mIntentSenderRecords.remove(rec.key);
3980 if (cleanActivity && rec.key.activity != null) {
3981 rec.key.activity.pendingResults.remove(rec.ref);
3982 }
3983 }
3984
3985 public String getPackageForIntentSender(IIntentSender pendingResult) {
3986 if (!(pendingResult instanceof PendingIntentRecord)) {
3987 return null;
3988 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003989 try {
3990 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3991 return res.key.packageName;
3992 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 }
3994 return null;
3995 }
3996
3997 public void setProcessLimit(int max) {
3998 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3999 "setProcessLimit()");
4000 mProcessLimit = max;
4001 }
4002
4003 public int getProcessLimit() {
4004 return mProcessLimit;
4005 }
4006
4007 void foregroundTokenDied(ForegroundToken token) {
4008 synchronized (ActivityManagerService.this) {
4009 synchronized (mPidsSelfLocked) {
4010 ForegroundToken cur
4011 = mForegroundProcesses.get(token.pid);
4012 if (cur != token) {
4013 return;
4014 }
4015 mForegroundProcesses.remove(token.pid);
4016 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4017 if (pr == null) {
4018 return;
4019 }
4020 pr.forcingToForeground = null;
4021 pr.foregroundServices = false;
4022 }
4023 updateOomAdjLocked();
4024 }
4025 }
4026
4027 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4028 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4029 "setProcessForeground()");
4030 synchronized(this) {
4031 boolean changed = false;
4032
4033 synchronized (mPidsSelfLocked) {
4034 ProcessRecord pr = mPidsSelfLocked.get(pid);
4035 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004036 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 return;
4038 }
4039 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4040 if (oldToken != null) {
4041 oldToken.token.unlinkToDeath(oldToken, 0);
4042 mForegroundProcesses.remove(pid);
4043 pr.forcingToForeground = null;
4044 changed = true;
4045 }
4046 if (isForeground && token != null) {
4047 ForegroundToken newToken = new ForegroundToken() {
4048 public void binderDied() {
4049 foregroundTokenDied(this);
4050 }
4051 };
4052 newToken.pid = pid;
4053 newToken.token = token;
4054 try {
4055 token.linkToDeath(newToken, 0);
4056 mForegroundProcesses.put(pid, newToken);
4057 pr.forcingToForeground = token;
4058 changed = true;
4059 } catch (RemoteException e) {
4060 // If the process died while doing this, we will later
4061 // do the cleanup with the process death link.
4062 }
4063 }
4064 }
4065
4066 if (changed) {
4067 updateOomAdjLocked();
4068 }
4069 }
4070 }
4071
4072 // =========================================================
4073 // PERMISSIONS
4074 // =========================================================
4075
4076 static class PermissionController extends IPermissionController.Stub {
4077 ActivityManagerService mActivityManagerService;
4078 PermissionController(ActivityManagerService activityManagerService) {
4079 mActivityManagerService = activityManagerService;
4080 }
4081
4082 public boolean checkPermission(String permission, int pid, int uid) {
4083 return mActivityManagerService.checkPermission(permission, pid,
4084 uid) == PackageManager.PERMISSION_GRANTED;
4085 }
4086 }
4087
4088 /**
4089 * This can be called with or without the global lock held.
4090 */
4091 int checkComponentPermission(String permission, int pid, int uid,
4092 int reqUid) {
4093 // We might be performing an operation on behalf of an indirect binder
4094 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4095 // client identity accordingly before proceeding.
4096 Identity tlsIdentity = sCallerIdentity.get();
4097 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004098 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4100 uid = tlsIdentity.uid;
4101 pid = tlsIdentity.pid;
4102 }
4103
4104 // Root, system server and our own process get to do everything.
4105 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4106 !Process.supportsProcesses()) {
4107 return PackageManager.PERMISSION_GRANTED;
4108 }
4109 // If the target requires a specific UID, always fail for others.
4110 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004112 return PackageManager.PERMISSION_DENIED;
4113 }
4114 if (permission == null) {
4115 return PackageManager.PERMISSION_GRANTED;
4116 }
4117 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004118 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004119 .checkUidPermission(permission, uid);
4120 } catch (RemoteException e) {
4121 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004122 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 }
4124 return PackageManager.PERMISSION_DENIED;
4125 }
4126
4127 /**
4128 * As the only public entry point for permissions checking, this method
4129 * can enforce the semantic that requesting a check on a null global
4130 * permission is automatically denied. (Internally a null permission
4131 * string is used when calling {@link #checkComponentPermission} in cases
4132 * when only uid-based security is needed.)
4133 *
4134 * This can be called with or without the global lock held.
4135 */
4136 public int checkPermission(String permission, int pid, int uid) {
4137 if (permission == null) {
4138 return PackageManager.PERMISSION_DENIED;
4139 }
4140 return checkComponentPermission(permission, pid, uid, -1);
4141 }
4142
4143 /**
4144 * Binder IPC calls go through the public entry point.
4145 * This can be called with or without the global lock held.
4146 */
4147 int checkCallingPermission(String permission) {
4148 return checkPermission(permission,
4149 Binder.getCallingPid(),
4150 Binder.getCallingUid());
4151 }
4152
4153 /**
4154 * This can be called with or without the global lock held.
4155 */
4156 void enforceCallingPermission(String permission, String func) {
4157 if (checkCallingPermission(permission)
4158 == PackageManager.PERMISSION_GRANTED) {
4159 return;
4160 }
4161
4162 String msg = "Permission Denial: " + func + " from pid="
4163 + Binder.getCallingPid()
4164 + ", uid=" + Binder.getCallingUid()
4165 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004166 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 throw new SecurityException(msg);
4168 }
4169
4170 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004171 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4172 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4173 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4174 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4175 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004177 // Is the component private from the target uid?
4178 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4179
4180 // Acceptable if the there is no read permission needed from the
4181 // target or the target is holding the read permission.
4182 if (!readPerm) {
4183 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004185 == PackageManager.PERMISSION_GRANTED)) {
4186 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 }
4188 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004189
4190 // Acceptable if the there is no write permission needed from the
4191 // target or the target is holding the read permission.
4192 if (!writePerm) {
4193 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004195 == PackageManager.PERMISSION_GRANTED)) {
4196 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 }
4198 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004199
4200 // Acceptable if there is a path permission matching the URI that
4201 // the target holds the permission on.
4202 PathPermission[] pps = pi.pathPermissions;
4203 if (pps != null && (!readPerm || !writePerm)) {
4204 final String path = uri.getPath();
4205 int i = pps.length;
4206 while (i > 0 && (!readPerm || !writePerm)) {
4207 i--;
4208 PathPermission pp = pps[i];
4209 if (!readPerm) {
4210 final String pprperm = pp.getReadPermission();
4211 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4212 + pprperm + " for " + pp.getPath()
4213 + ": match=" + pp.match(path)
4214 + " check=" + pm.checkUidPermission(pprperm, uid));
4215 if (pprperm != null && pp.match(path) &&
4216 (pm.checkUidPermission(pprperm, uid)
4217 == PackageManager.PERMISSION_GRANTED)) {
4218 readPerm = true;
4219 }
4220 }
4221 if (!writePerm) {
4222 final String ppwperm = pp.getWritePermission();
4223 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4224 + ppwperm + " for " + pp.getPath()
4225 + ": match=" + pp.match(path)
4226 + " check=" + pm.checkUidPermission(ppwperm, uid));
4227 if (ppwperm != null && pp.match(path) &&
4228 (pm.checkUidPermission(ppwperm, uid)
4229 == PackageManager.PERMISSION_GRANTED)) {
4230 writePerm = true;
4231 }
4232 }
4233 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 } catch (RemoteException e) {
4236 return false;
4237 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004238
4239 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 }
4241
4242 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4243 int modeFlags) {
4244 // Root gets to do everything.
4245 if (uid == 0 || !Process.supportsProcesses()) {
4246 return true;
4247 }
4248 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4249 if (perms == null) return false;
4250 UriPermission perm = perms.get(uri);
4251 if (perm == null) return false;
4252 return (modeFlags&perm.modeFlags) == modeFlags;
4253 }
4254
4255 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4256 // Another redirected-binder-call permissions check as in
4257 // {@link checkComponentPermission}.
4258 Identity tlsIdentity = sCallerIdentity.get();
4259 if (tlsIdentity != null) {
4260 uid = tlsIdentity.uid;
4261 pid = tlsIdentity.pid;
4262 }
4263
4264 // Our own process gets to do everything.
4265 if (pid == MY_PID) {
4266 return PackageManager.PERMISSION_GRANTED;
4267 }
4268 synchronized(this) {
4269 return checkUriPermissionLocked(uri, uid, modeFlags)
4270 ? PackageManager.PERMISSION_GRANTED
4271 : PackageManager.PERMISSION_DENIED;
4272 }
4273 }
4274
Dianne Hackborn39792d22010-08-19 18:01:52 -07004275 /**
4276 * Check if the targetPkg can be granted permission to access uri by
4277 * the callingUid using the given modeFlags. Throws a security exception
4278 * if callingUid is not allowed to do this. Returns the uid of the target
4279 * if the URI permission grant should be performed; returns -1 if it is not
4280 * needed (for example targetPkg already has permission to access the URI).
4281 */
4282 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4283 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004284 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4285 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4286 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004287 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 }
4289
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004290 if (targetPkg != null) {
4291 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4292 "Checking grant " + targetPkg + " permission to " + uri);
4293 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004294
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004295 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296
4297 // If this is not a content: uri, we can't do anything with it.
4298 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004299 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004300 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004301 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 }
4303
4304 String name = uri.getAuthority();
4305 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004306 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 if (cpr != null) {
4308 pi = cpr.info;
4309 } else {
4310 try {
4311 pi = pm.resolveContentProvider(name,
4312 PackageManager.GET_URI_PERMISSION_PATTERNS);
4313 } catch (RemoteException ex) {
4314 }
4315 }
4316 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004317 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004318 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 }
4320
4321 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004322 if (targetPkg != null) {
4323 try {
4324 targetUid = pm.getPackageUid(targetPkg);
4325 if (targetUid < 0) {
4326 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4327 "Can't grant URI permission no uid for: " + targetPkg);
4328 return -1;
4329 }
4330 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004331 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004333 } else {
4334 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 }
4336
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004337 if (targetUid >= 0) {
4338 // First... does the target actually need this permission?
4339 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4340 // No need to grant the target this permission.
4341 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4342 "Target " + targetPkg + " already has full permission to " + uri);
4343 return -1;
4344 }
4345 } else {
4346 // First... there is no target package, so can anyone access it?
4347 boolean allowed = pi.exported;
4348 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4349 if (pi.readPermission != null) {
4350 allowed = false;
4351 }
4352 }
4353 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4354 if (pi.writePermission != null) {
4355 allowed = false;
4356 }
4357 }
4358 if (allowed) {
4359 return -1;
4360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 }
4362
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004363 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 if (!pi.grantUriPermissions) {
4365 throw new SecurityException("Provider " + pi.packageName
4366 + "/" + pi.name
4367 + " does not allow granting of Uri permissions (uri "
4368 + uri + ")");
4369 }
4370 if (pi.uriPermissionPatterns != null) {
4371 final int N = pi.uriPermissionPatterns.length;
4372 boolean allowed = false;
4373 for (int i=0; i<N; i++) {
4374 if (pi.uriPermissionPatterns[i] != null
4375 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4376 allowed = true;
4377 break;
4378 }
4379 }
4380 if (!allowed) {
4381 throw new SecurityException("Provider " + pi.packageName
4382 + "/" + pi.name
4383 + " does not allow granting of permission to path of Uri "
4384 + uri);
4385 }
4386 }
4387
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004388 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004389 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004390 if (callingUid != Process.myUid()) {
4391 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4392 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4393 throw new SecurityException("Uid " + callingUid
4394 + " does not have permission to uri " + uri);
4395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 }
4397 }
4398
Dianne Hackborn39792d22010-08-19 18:01:52 -07004399 return targetUid;
4400 }
4401
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004402 public int checkGrantUriPermission(int callingUid, String targetPkg,
4403 Uri uri, int modeFlags) {
4404 synchronized(this) {
4405 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4406 }
4407 }
4408
Dianne Hackborn39792d22010-08-19 18:01:52 -07004409 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4410 Uri uri, int modeFlags, UriPermissionOwner owner) {
4411 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4412 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4413 if (modeFlags == 0) {
4414 return;
4415 }
4416
4417 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004418 // to the uri, and the target doesn't. Let's now give this to
4419 // the target.
4420
Joe Onorato8a9b2202010-02-26 18:56:32 -08004421 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004422 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 HashMap<Uri, UriPermission> targetUris
4425 = mGrantedUriPermissions.get(targetUid);
4426 if (targetUris == null) {
4427 targetUris = new HashMap<Uri, UriPermission>();
4428 mGrantedUriPermissions.put(targetUid, targetUris);
4429 }
4430
4431 UriPermission perm = targetUris.get(uri);
4432 if (perm == null) {
4433 perm = new UriPermission(targetUid, uri);
4434 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004438 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 perm.globalModeFlags |= modeFlags;
4440 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004441 perm.readOwners.add(owner);
4442 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004444 perm.writeOwners.add(owner);
4445 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446 }
4447 }
4448
Dianne Hackborn39792d22010-08-19 18:01:52 -07004449 void grantUriPermissionLocked(int callingUid,
4450 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004451 if (targetPkg == null) {
4452 throw new NullPointerException("targetPkg");
4453 }
4454
Dianne Hackborn39792d22010-08-19 18:01:52 -07004455 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4456 if (targetUid < 0) {
4457 return;
4458 }
4459
4460 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4461 }
4462
4463 /**
4464 * Like checkGrantUriPermissionLocked, but takes an Intent.
4465 */
4466 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4467 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004468 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004469 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004470 + " from " + intent + "; flags=0x"
4471 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4472
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004473 if (targetPkg == null) {
4474 throw new NullPointerException("targetPkg");
4475 }
4476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004477 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004478 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 }
4480 Uri data = intent.getData();
4481 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004482 return -1;
4483 }
4484 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4485 intent.getFlags());
4486 }
4487
4488 /**
4489 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4490 */
4491 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4492 String targetPkg, Intent intent, UriPermissionOwner owner) {
4493 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4494 intent.getFlags(), owner);
4495 }
4496
4497 void grantUriPermissionFromIntentLocked(int callingUid,
4498 String targetPkg, Intent intent, UriPermissionOwner owner) {
4499 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4500 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 return;
4502 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004503
4504 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506
4507 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4508 Uri uri, int modeFlags) {
4509 synchronized(this) {
4510 final ProcessRecord r = getRecordForAppLocked(caller);
4511 if (r == null) {
4512 throw new SecurityException("Unable to find app for caller "
4513 + caller
4514 + " when granting permission to uri " + uri);
4515 }
4516 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004517 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 }
4519 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004520 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
4522
4523 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4524 null);
4525 }
4526 }
4527
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004528 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004529 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4530 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4531 HashMap<Uri, UriPermission> perms
4532 = mGrantedUriPermissions.get(perm.uid);
4533 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004534 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004535 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 perms.remove(perm.uri);
4537 if (perms.size() == 0) {
4538 mGrantedUriPermissions.remove(perm.uid);
4539 }
4540 }
4541 }
4542 }
4543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4545 int modeFlags) {
4546 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4547 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4548 if (modeFlags == 0) {
4549 return;
4550 }
4551
Joe Onorato8a9b2202010-02-26 18:56:32 -08004552 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004553 "Revoking all granted permissions to " + uri);
4554
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004555 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556
4557 final String authority = uri.getAuthority();
4558 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004559 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 if (cpr != null) {
4561 pi = cpr.info;
4562 } else {
4563 try {
4564 pi = pm.resolveContentProvider(authority,
4565 PackageManager.GET_URI_PERMISSION_PATTERNS);
4566 } catch (RemoteException ex) {
4567 }
4568 }
4569 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004570 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 return;
4572 }
4573
4574 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004575 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 // Right now, if you are not the original owner of the permission,
4577 // you are not allowed to revoke it.
4578 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4579 throw new SecurityException("Uid " + callingUid
4580 + " does not have permission to uri " + uri);
4581 //}
4582 }
4583
4584 // Go through all of the permissions and remove any that match.
4585 final List<String> SEGMENTS = uri.getPathSegments();
4586 if (SEGMENTS != null) {
4587 final int NS = SEGMENTS.size();
4588 int N = mGrantedUriPermissions.size();
4589 for (int i=0; i<N; i++) {
4590 HashMap<Uri, UriPermission> perms
4591 = mGrantedUriPermissions.valueAt(i);
4592 Iterator<UriPermission> it = perms.values().iterator();
4593 toploop:
4594 while (it.hasNext()) {
4595 UriPermission perm = it.next();
4596 Uri targetUri = perm.uri;
4597 if (!authority.equals(targetUri.getAuthority())) {
4598 continue;
4599 }
4600 List<String> targetSegments = targetUri.getPathSegments();
4601 if (targetSegments == null) {
4602 continue;
4603 }
4604 if (targetSegments.size() < NS) {
4605 continue;
4606 }
4607 for (int j=0; j<NS; j++) {
4608 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4609 continue toploop;
4610 }
4611 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004612 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004613 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 perm.clearModes(modeFlags);
4615 if (perm.modeFlags == 0) {
4616 it.remove();
4617 }
4618 }
4619 if (perms.size() == 0) {
4620 mGrantedUriPermissions.remove(
4621 mGrantedUriPermissions.keyAt(i));
4622 N--;
4623 i--;
4624 }
4625 }
4626 }
4627 }
4628
4629 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4630 int modeFlags) {
4631 synchronized(this) {
4632 final ProcessRecord r = getRecordForAppLocked(caller);
4633 if (r == null) {
4634 throw new SecurityException("Unable to find app for caller "
4635 + caller
4636 + " when revoking permission to uri " + uri);
4637 }
4638 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004639 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 return;
4641 }
4642
4643 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4644 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4645 if (modeFlags == 0) {
4646 return;
4647 }
4648
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004649 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650
4651 final String authority = uri.getAuthority();
4652 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004653 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 if (cpr != null) {
4655 pi = cpr.info;
4656 } else {
4657 try {
4658 pi = pm.resolveContentProvider(authority,
4659 PackageManager.GET_URI_PERMISSION_PATTERNS);
4660 } catch (RemoteException ex) {
4661 }
4662 }
4663 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004664 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 return;
4666 }
4667
4668 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4669 }
4670 }
4671
Dianne Hackborn7e269642010-08-25 19:50:20 -07004672 @Override
4673 public IBinder newUriPermissionOwner(String name) {
4674 synchronized(this) {
4675 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4676 return owner.getExternalTokenLocked();
4677 }
4678 }
4679
4680 @Override
4681 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4682 Uri uri, int modeFlags) {
4683 synchronized(this) {
4684 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4685 if (owner == null) {
4686 throw new IllegalArgumentException("Unknown owner: " + token);
4687 }
4688 if (fromUid != Binder.getCallingUid()) {
4689 if (Binder.getCallingUid() != Process.myUid()) {
4690 // Only system code can grant URI permissions on behalf
4691 // of other users.
4692 throw new SecurityException("nice try");
4693 }
4694 }
4695 if (targetPkg == null) {
4696 throw new IllegalArgumentException("null target");
4697 }
4698 if (uri == null) {
4699 throw new IllegalArgumentException("null uri");
4700 }
4701
4702 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4703 }
4704 }
4705
4706 @Override
4707 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4708 synchronized(this) {
4709 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4710 if (owner == null) {
4711 throw new IllegalArgumentException("Unknown owner: " + token);
4712 }
4713
4714 if (uri == null) {
4715 owner.removeUriPermissionsLocked(mode);
4716 } else {
4717 owner.removeUriPermissionLocked(uri, mode);
4718 }
4719 }
4720 }
4721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4723 synchronized (this) {
4724 ProcessRecord app =
4725 who != null ? getRecordForAppLocked(who) : null;
4726 if (app == null) return;
4727
4728 Message msg = Message.obtain();
4729 msg.what = WAIT_FOR_DEBUGGER_MSG;
4730 msg.obj = app;
4731 msg.arg1 = waiting ? 1 : 0;
4732 mHandler.sendMessage(msg);
4733 }
4734 }
4735
4736 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4737 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004738 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004740 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004741 }
4742
4743 // =========================================================
4744 // TASK MANAGEMENT
4745 // =========================================================
4746
4747 public List getTasks(int maxNum, int flags,
4748 IThumbnailReceiver receiver) {
4749 ArrayList list = new ArrayList();
4750
4751 PendingThumbnailsRecord pending = null;
4752 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004753 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754
4755 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004756 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4758 + ", receiver=" + receiver);
4759
4760 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4761 != PackageManager.PERMISSION_GRANTED) {
4762 if (receiver != null) {
4763 // If the caller wants to wait for pending thumbnails,
4764 // it ain't gonna get them.
4765 try {
4766 receiver.finished();
4767 } catch (RemoteException ex) {
4768 }
4769 }
4770 String msg = "Permission Denial: getTasks() from pid="
4771 + Binder.getCallingPid()
4772 + ", uid=" + Binder.getCallingUid()
4773 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004774 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 throw new SecurityException(msg);
4776 }
4777
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004778 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004779 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004780 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004781 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 CharSequence topDescription = null;
4783 TaskRecord curTask = null;
4784 int numActivities = 0;
4785 int numRunning = 0;
4786 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004787 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004789 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790
4791 // Initialize state for next task if needed.
4792 if (top == null ||
4793 (top.state == ActivityState.INITIALIZING
4794 && top.task == r.task)) {
4795 top = r;
4796 topDescription = r.description;
4797 curTask = r.task;
4798 numActivities = numRunning = 0;
4799 }
4800
4801 // Add 'r' into the current task.
4802 numActivities++;
4803 if (r.app != null && r.app.thread != null) {
4804 numRunning++;
4805 }
4806 if (topDescription == null) {
4807 topDescription = r.description;
4808 }
4809
Joe Onorato8a9b2202010-02-26 18:56:32 -08004810 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 TAG, r.intent.getComponent().flattenToShortString()
4812 + ": task=" + r.task);
4813
4814 // If the next one is a different task, generate a new
4815 // TaskInfo entry for what we have.
4816 if (next == null || next.task != curTask) {
4817 ActivityManager.RunningTaskInfo ci
4818 = new ActivityManager.RunningTaskInfo();
4819 ci.id = curTask.taskId;
4820 ci.baseActivity = r.intent.getComponent();
4821 ci.topActivity = top.intent.getComponent();
4822 ci.thumbnail = top.thumbnail;
4823 ci.description = topDescription;
4824 ci.numActivities = numActivities;
4825 ci.numRunning = numRunning;
4826 //System.out.println(
4827 // "#" + maxNum + ": " + " descr=" + ci.description);
4828 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004829 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 TAG, "State=" + top.state + "Idle=" + top.idle
4831 + " app=" + top.app
4832 + " thr=" + (top.app != null ? top.app.thread : null));
4833 if (top.state == ActivityState.RESUMED
4834 || top.state == ActivityState.PAUSING) {
4835 if (top.idle && top.app != null
4836 && top.app.thread != null) {
4837 topRecord = top;
4838 topThumbnail = top.app.thread;
4839 } else {
4840 top.thumbnailNeeded = true;
4841 }
4842 }
4843 if (pending == null) {
4844 pending = new PendingThumbnailsRecord(receiver);
4845 }
4846 pending.pendingRecords.add(top);
4847 }
4848 list.add(ci);
4849 maxNum--;
4850 top = null;
4851 }
4852 }
4853
4854 if (pending != null) {
4855 mPendingThumbnails.add(pending);
4856 }
4857 }
4858
Joe Onorato8a9b2202010-02-26 18:56:32 -08004859 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860
4861 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004862 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 try {
4864 topThumbnail.requestThumbnail(topRecord);
4865 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004866 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 sendPendingThumbnail(null, topRecord, null, null, true);
4868 }
4869 }
4870
4871 if (pending == null && receiver != null) {
4872 // In this case all thumbnails were available and the client
4873 // is being asked to be told when the remaining ones come in...
4874 // which is unusually, since the top-most currently running
4875 // activity should never have a canned thumbnail! Oh well.
4876 try {
4877 receiver.finished();
4878 } catch (RemoteException ex) {
4879 }
4880 }
4881
4882 return list;
4883 }
4884
4885 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4886 int flags) {
4887 synchronized (this) {
4888 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4889 "getRecentTasks()");
4890
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004891 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 final int N = mRecentTasks.size();
4894 ArrayList<ActivityManager.RecentTaskInfo> res
4895 = new ArrayList<ActivityManager.RecentTaskInfo>(
4896 maxNum < N ? maxNum : N);
4897 for (int i=0; i<N && maxNum > 0; i++) {
4898 TaskRecord tr = mRecentTasks.get(i);
4899 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4900 || (tr.intent == null)
4901 || ((tr.intent.getFlags()
4902 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4903 ActivityManager.RecentTaskInfo rti
4904 = new ActivityManager.RecentTaskInfo();
4905 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4906 rti.baseIntent = new Intent(
4907 tr.intent != null ? tr.intent : tr.affinityIntent);
4908 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004909
4910 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4911 // Check whether this activity is currently available.
4912 try {
4913 if (rti.origActivity != null) {
4914 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4915 continue;
4916 }
4917 } else if (rti.baseIntent != null) {
4918 if (pm.queryIntentActivities(rti.baseIntent,
4919 null, 0) == null) {
4920 continue;
4921 }
4922 }
4923 } catch (RemoteException e) {
4924 // Will never happen.
4925 }
4926 }
4927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 res.add(rti);
4929 maxNum--;
4930 }
4931 }
4932 return res;
4933 }
4934 }
4935
4936 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4937 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004938 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 TaskRecord jt = startTask;
4940
4941 // First look backwards
4942 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004943 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 if (r.task != jt) {
4945 jt = r.task;
4946 if (affinity.equals(jt.affinity)) {
4947 return j;
4948 }
4949 }
4950 }
4951
4952 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004953 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 jt = startTask;
4955 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004956 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 if (r.task != jt) {
4958 if (affinity.equals(jt.affinity)) {
4959 return j;
4960 }
4961 jt = r.task;
4962 }
4963 }
4964
4965 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004966 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 return N-1;
4968 }
4969
4970 return -1;
4971 }
4972
4973 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004974 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 */
4976 public void moveTaskToFront(int task) {
4977 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4978 "moveTaskToFront()");
4979
4980 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004981 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4982 Binder.getCallingUid(), "Task to front")) {
4983 return;
4984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 final long origId = Binder.clearCallingIdentity();
4986 try {
4987 int N = mRecentTasks.size();
4988 for (int i=0; i<N; i++) {
4989 TaskRecord tr = mRecentTasks.get(i);
4990 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004991 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 return;
4993 }
4994 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004995 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4996 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004998 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 return;
5000 }
5001 }
5002 } finally {
5003 Binder.restoreCallingIdentity(origId);
5004 }
5005 }
5006 }
5007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 public void moveTaskToBack(int task) {
5009 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5010 "moveTaskToBack()");
5011
5012 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005013 if (mMainStack.mResumedActivity != null
5014 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005015 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5016 Binder.getCallingUid(), "Task to back")) {
5017 return;
5018 }
5019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005020 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005021 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 Binder.restoreCallingIdentity(origId);
5023 }
5024 }
5025
5026 /**
5027 * Moves an activity, and all of the other activities within the same task, to the bottom
5028 * of the history stack. The activity's order within the task is unchanged.
5029 *
5030 * @param token A reference to the activity we wish to move
5031 * @param nonRoot If false then this only works if the activity is the root
5032 * of a task; if true it will work for any activity in a task.
5033 * @return Returns true if the move completed, false if not.
5034 */
5035 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5036 synchronized(this) {
5037 final long origId = Binder.clearCallingIdentity();
5038 int taskId = getTaskForActivityLocked(token, !nonRoot);
5039 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005040 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 }
5042 Binder.restoreCallingIdentity(origId);
5043 }
5044 return false;
5045 }
5046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005047 public void moveTaskBackwards(int task) {
5048 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5049 "moveTaskBackwards()");
5050
5051 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005052 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5053 Binder.getCallingUid(), "Task backwards")) {
5054 return;
5055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 final long origId = Binder.clearCallingIdentity();
5057 moveTaskBackwardsLocked(task);
5058 Binder.restoreCallingIdentity(origId);
5059 }
5060 }
5061
5062 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005063 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005064 }
5065
5066 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5067 synchronized(this) {
5068 return getTaskForActivityLocked(token, onlyRoot);
5069 }
5070 }
5071
5072 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005073 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 TaskRecord lastTask = null;
5075 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005076 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 if (r == token) {
5078 if (!onlyRoot || lastTask != r.task) {
5079 return r.task.taskId;
5080 }
5081 return -1;
5082 }
5083 lastTask = r.task;
5084 }
5085
5086 return -1;
5087 }
5088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 public void finishOtherInstances(IBinder token, ComponentName className) {
5090 synchronized(this) {
5091 final long origId = Binder.clearCallingIdentity();
5092
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005093 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 TaskRecord lastTask = null;
5095 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005096 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 if (r.realActivity.equals(className)
5098 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005099 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 null, "others")) {
5101 i--;
5102 N--;
5103 }
5104 }
5105 lastTask = r.task;
5106 }
5107
5108 Binder.restoreCallingIdentity(origId);
5109 }
5110 }
5111
5112 // =========================================================
5113 // THUMBNAILS
5114 // =========================================================
5115
5116 public void reportThumbnail(IBinder token,
5117 Bitmap thumbnail, CharSequence description) {
5118 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5119 final long origId = Binder.clearCallingIdentity();
5120 sendPendingThumbnail(null, token, thumbnail, description, true);
5121 Binder.restoreCallingIdentity(origId);
5122 }
5123
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005124 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 Bitmap thumbnail, CharSequence description, boolean always) {
5126 TaskRecord task = null;
5127 ArrayList receivers = null;
5128
5129 //System.out.println("Send pending thumbnail: " + r);
5130
5131 synchronized(this) {
5132 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005133 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 if (index < 0) {
5135 return;
5136 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005137 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139 if (thumbnail == null) {
5140 thumbnail = r.thumbnail;
5141 description = r.description;
5142 }
5143 if (thumbnail == null && !always) {
5144 // If there is no thumbnail, and this entry is not actually
5145 // going away, then abort for now and pick up the next
5146 // thumbnail we get.
5147 return;
5148 }
5149 task = r.task;
5150
5151 int N = mPendingThumbnails.size();
5152 int i=0;
5153 while (i<N) {
5154 PendingThumbnailsRecord pr =
5155 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5156 //System.out.println("Looking in " + pr.pendingRecords);
5157 if (pr.pendingRecords.remove(r)) {
5158 if (receivers == null) {
5159 receivers = new ArrayList();
5160 }
5161 receivers.add(pr);
5162 if (pr.pendingRecords.size() == 0) {
5163 pr.finished = true;
5164 mPendingThumbnails.remove(i);
5165 N--;
5166 continue;
5167 }
5168 }
5169 i++;
5170 }
5171 }
5172
5173 if (receivers != null) {
5174 final int N = receivers.size();
5175 for (int i=0; i<N; i++) {
5176 try {
5177 PendingThumbnailsRecord pr =
5178 (PendingThumbnailsRecord)receivers.get(i);
5179 pr.receiver.newThumbnail(
5180 task != null ? task.taskId : -1, thumbnail, description);
5181 if (pr.finished) {
5182 pr.receiver.finished();
5183 }
5184 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005185 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 }
5187 }
5188 }
5189 }
5190
5191 // =========================================================
5192 // CONTENT PROVIDERS
5193 // =========================================================
5194
5195 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5196 List providers = null;
5197 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005198 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005200 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 } catch (RemoteException ex) {
5202 }
5203 if (providers != null) {
5204 final int N = providers.size();
5205 for (int i=0; i<N; i++) {
5206 ProviderInfo cpi =
5207 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005208 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 if (cpr == null) {
5210 cpr = new ContentProviderRecord(cpi, app.info);
5211 mProvidersByClass.put(cpi.name, cpr);
5212 }
5213 app.pubProviders.put(cpi.name, cpr);
5214 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005215 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 }
5217 }
5218 return providers;
5219 }
5220
5221 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005222 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5224 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5225 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5226 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005227 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 return null;
5229 }
5230 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5231 cpi.exported ? -1 : cpi.applicationInfo.uid)
5232 == PackageManager.PERMISSION_GRANTED) {
5233 return null;
5234 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005235
5236 PathPermission[] pps = cpi.pathPermissions;
5237 if (pps != null) {
5238 int i = pps.length;
5239 while (i > 0) {
5240 i--;
5241 PathPermission pp = pps[i];
5242 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5243 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005244 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005245 return null;
5246 }
5247 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5248 cpi.exported ? -1 : cpi.applicationInfo.uid)
5249 == PackageManager.PERMISSION_GRANTED) {
5250 return null;
5251 }
5252 }
5253 }
5254
Dianne Hackbornb424b632010-08-18 15:59:05 -07005255 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5256 if (perms != null) {
5257 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5258 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5259 return null;
5260 }
5261 }
5262 }
5263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 String msg = "Permission Denial: opening provider " + cpi.name
5265 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5266 + ", uid=" + callingUid + ") requires "
5267 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005268 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 return msg;
5270 }
5271
5272 private final ContentProviderHolder getContentProviderImpl(
5273 IApplicationThread caller, String name) {
5274 ContentProviderRecord cpr;
5275 ProviderInfo cpi = null;
5276
5277 synchronized(this) {
5278 ProcessRecord r = null;
5279 if (caller != null) {
5280 r = getRecordForAppLocked(caller);
5281 if (r == null) {
5282 throw new SecurityException(
5283 "Unable to find app for caller " + caller
5284 + " (pid=" + Binder.getCallingPid()
5285 + ") when getting content provider " + name);
5286 }
5287 }
5288
5289 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005290 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 if (cpr != null) {
5292 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005293 String msg;
5294 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5295 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 }
5297
5298 if (r != null && cpr.canRunHere(r)) {
5299 // This provider has been published or is in the process
5300 // of being published... but it is also allowed to run
5301 // in the caller's process, so don't make a connection
5302 // and just let the caller instantiate its own instance.
5303 if (cpr.provider != null) {
5304 // don't give caller the provider object, it needs
5305 // to make its own.
5306 cpr = new ContentProviderRecord(cpr);
5307 }
5308 return cpr;
5309 }
5310
5311 final long origId = Binder.clearCallingIdentity();
5312
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005313 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 // return it right away.
5315 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005316 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005317 "Adding provider requested by "
5318 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005319 + cpr.info.processName);
5320 Integer cnt = r.conProviders.get(cpr);
5321 if (cnt == null) {
5322 r.conProviders.put(cpr, new Integer(1));
5323 } else {
5324 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005327 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5328 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005329 // make sure to count it as being accessed and thus
5330 // back up on the LRU list. This is good because
5331 // content providers are often expensive to start.
5332 updateLruProcessLocked(cpr.app, false, true);
5333 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005334 } else {
5335 cpr.externals++;
5336 }
5337
5338 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005339 updateOomAdjLocked(cpr.app);
5340 }
5341
5342 Binder.restoreCallingIdentity(origId);
5343
5344 } else {
5345 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005346 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005347 resolveContentProvider(name,
5348 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 } catch (RemoteException ex) {
5350 }
5351 if (cpi == null) {
5352 return null;
5353 }
5354
Dianne Hackbornb424b632010-08-18 15:59:05 -07005355 String msg;
5356 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5357 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 }
5359
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005360 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005361 && !cpi.processName.equals("system")) {
5362 // If this content provider does not run in the system
5363 // process, and the system is not yet ready to run other
5364 // processes, then fail fast instead of hanging.
5365 throw new IllegalArgumentException(
5366 "Attempt to launch content provider before system ready");
5367 }
5368
Dianne Hackborn860755f2010-06-03 18:47:52 -07005369 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 final boolean firstClass = cpr == null;
5371 if (firstClass) {
5372 try {
5373 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005374 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 getApplicationInfo(
5376 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005377 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005379 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005380 + cpi.name);
5381 return null;
5382 }
5383 cpr = new ContentProviderRecord(cpi, ai);
5384 } catch (RemoteException ex) {
5385 // pm is in same process, this will never happen.
5386 }
5387 }
5388
5389 if (r != null && cpr.canRunHere(r)) {
5390 // If this is a multiprocess provider, then just return its
5391 // info and allow the caller to instantiate it. Only do
5392 // this if the provider is the same user as the caller's
5393 // process, or can run as root (so can be in any process).
5394 return cpr;
5395 }
5396
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005397 if (DEBUG_PROVIDER) {
5398 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005399 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005400 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 }
5402
5403 // This is single process, and our app is now connecting to it.
5404 // See if we are already in the process of launching this
5405 // provider.
5406 final int N = mLaunchingProviders.size();
5407 int i;
5408 for (i=0; i<N; i++) {
5409 if (mLaunchingProviders.get(i) == cpr) {
5410 break;
5411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 }
5413
5414 // If the provider is not already being launched, then get it
5415 // started.
5416 if (i >= N) {
5417 final long origId = Binder.clearCallingIdentity();
5418 ProcessRecord proc = startProcessLocked(cpi.processName,
5419 cpr.appInfo, false, 0, "content provider",
5420 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005421 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 + cpi.applicationInfo.packageName + "/"
5425 + cpi.applicationInfo.uid + " for provider "
5426 + name + ": process is bad");
5427 return null;
5428 }
5429 cpr.launchingApp = proc;
5430 mLaunchingProviders.add(cpr);
5431 Binder.restoreCallingIdentity(origId);
5432 }
5433
5434 // Make sure the provider is published (the same provider class
5435 // may be published under multiple names).
5436 if (firstClass) {
5437 mProvidersByClass.put(cpi.name, cpr);
5438 }
5439 mProvidersByName.put(name, cpr);
5440
5441 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005442 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005443 "Adding provider requested by "
5444 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005445 + cpr.info.processName);
5446 Integer cnt = r.conProviders.get(cpr);
5447 if (cnt == null) {
5448 r.conProviders.put(cpr, new Integer(1));
5449 } else {
5450 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005452 cpr.clients.add(r);
5453 } else {
5454 cpr.externals++;
5455 }
5456 }
5457 }
5458
5459 // Wait for the provider to be published...
5460 synchronized (cpr) {
5461 while (cpr.provider == null) {
5462 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005463 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 + cpi.applicationInfo.packageName + "/"
5465 + cpi.applicationInfo.uid + " for provider "
5466 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005467 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 cpi.applicationInfo.packageName,
5469 cpi.applicationInfo.uid, name);
5470 return null;
5471 }
5472 try {
5473 cpr.wait();
5474 } catch (InterruptedException ex) {
5475 }
5476 }
5477 }
5478 return cpr;
5479 }
5480
5481 public final ContentProviderHolder getContentProvider(
5482 IApplicationThread caller, String name) {
5483 if (caller == null) {
5484 String msg = "null IApplicationThread when getting content provider "
5485 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005486 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 throw new SecurityException(msg);
5488 }
5489
5490 return getContentProviderImpl(caller, name);
5491 }
5492
5493 private ContentProviderHolder getContentProviderExternal(String name) {
5494 return getContentProviderImpl(null, name);
5495 }
5496
5497 /**
5498 * Drop a content provider from a ProcessRecord's bookkeeping
5499 * @param cpr
5500 */
5501 public void removeContentProvider(IApplicationThread caller, String name) {
5502 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005503 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005505 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005506 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005507 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 return;
5509 }
5510 final ProcessRecord r = getRecordForAppLocked(caller);
5511 if (r == null) {
5512 throw new SecurityException(
5513 "Unable to find app for caller " + caller +
5514 " when removing content provider " + name);
5515 }
5516 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005517 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005518 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005519 + r.info.processName + " from process "
5520 + localCpr.appInfo.processName);
5521 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005523 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005524 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 return;
5526 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005527 Integer cnt = r.conProviders.get(localCpr);
5528 if (cnt == null || cnt.intValue() <= 1) {
5529 localCpr.clients.remove(r);
5530 r.conProviders.remove(localCpr);
5531 } else {
5532 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 }
5535 updateOomAdjLocked();
5536 }
5537 }
5538
5539 private void removeContentProviderExternal(String name) {
5540 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005541 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 if(cpr == null) {
5543 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005544 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005545 return;
5546 }
5547
5548 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005549 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 localCpr.externals--;
5551 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005552 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 }
5554 updateOomAdjLocked();
5555 }
5556 }
5557
5558 public final void publishContentProviders(IApplicationThread caller,
5559 List<ContentProviderHolder> providers) {
5560 if (providers == null) {
5561 return;
5562 }
5563
5564 synchronized(this) {
5565 final ProcessRecord r = getRecordForAppLocked(caller);
5566 if (r == null) {
5567 throw new SecurityException(
5568 "Unable to find app for caller " + caller
5569 + " (pid=" + Binder.getCallingPid()
5570 + ") when publishing content providers");
5571 }
5572
5573 final long origId = Binder.clearCallingIdentity();
5574
5575 final int N = providers.size();
5576 for (int i=0; i<N; i++) {
5577 ContentProviderHolder src = providers.get(i);
5578 if (src == null || src.info == null || src.provider == null) {
5579 continue;
5580 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005581 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 if (dst != null) {
5583 mProvidersByClass.put(dst.info.name, dst);
5584 String names[] = dst.info.authority.split(";");
5585 for (int j = 0; j < names.length; j++) {
5586 mProvidersByName.put(names[j], dst);
5587 }
5588
5589 int NL = mLaunchingProviders.size();
5590 int j;
5591 for (j=0; j<NL; j++) {
5592 if (mLaunchingProviders.get(j) == dst) {
5593 mLaunchingProviders.remove(j);
5594 j--;
5595 NL--;
5596 }
5597 }
5598 synchronized (dst) {
5599 dst.provider = src.provider;
5600 dst.app = r;
5601 dst.notifyAll();
5602 }
5603 updateOomAdjLocked(r);
5604 }
5605 }
5606
5607 Binder.restoreCallingIdentity(origId);
5608 }
5609 }
5610
5611 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005612 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005613 synchronized (mSelf) {
5614 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5615 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005616 if (providers != null) {
5617 for (int i=providers.size()-1; i>=0; i--) {
5618 ProviderInfo pi = (ProviderInfo)providers.get(i);
5619 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5620 Slog.w(TAG, "Not installing system proc provider " + pi.name
5621 + ": not system .apk");
5622 providers.remove(i);
5623 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005624 }
5625 }
5626 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005627 if (providers != null) {
5628 mSystemThread.installSystemProviders(providers);
5629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 }
5631
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005632 /**
5633 * Allows app to retrieve the MIME type of a URI without having permission
5634 * to access its content provider.
5635 *
5636 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5637 *
5638 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5639 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5640 */
5641 public String getProviderMimeType(Uri uri) {
5642 final String name = uri.getAuthority();
5643 final long ident = Binder.clearCallingIdentity();
5644 ContentProviderHolder holder = null;
5645
5646 try {
5647 holder = getContentProviderExternal(name);
5648 if (holder != null) {
5649 return holder.provider.getType(uri);
5650 }
5651 } catch (RemoteException e) {
5652 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5653 return null;
5654 } finally {
5655 if (holder != null) {
5656 removeContentProviderExternal(name);
5657 }
5658 Binder.restoreCallingIdentity(ident);
5659 }
5660
5661 return null;
5662 }
5663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005664 // =========================================================
5665 // GLOBAL MANAGEMENT
5666 // =========================================================
5667
5668 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5669 ApplicationInfo info, String customProcess) {
5670 String proc = customProcess != null ? customProcess : info.processName;
5671 BatteryStatsImpl.Uid.Proc ps = null;
5672 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5673 synchronized (stats) {
5674 ps = stats.getProcessStatsLocked(info.uid, proc);
5675 }
5676 return new ProcessRecord(ps, thread, info, proc);
5677 }
5678
5679 final ProcessRecord addAppLocked(ApplicationInfo info) {
5680 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5681
5682 if (app == null) {
5683 app = newProcessRecordLocked(null, info, null);
5684 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005685 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 }
5687
5688 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5689 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5690 app.persistent = true;
5691 app.maxAdj = CORE_SERVER_ADJ;
5692 }
5693 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5694 mPersistentStartingProcesses.add(app);
5695 startProcessLocked(app, "added application", app.processName);
5696 }
5697
5698 return app;
5699 }
5700
5701 public void unhandledBack() {
5702 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5703 "unhandledBack()");
5704
5705 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005706 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005707 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005708 TAG, "Performing unhandledBack(): stack size = " + count);
5709 if (count > 1) {
5710 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005711 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5713 Binder.restoreCallingIdentity(origId);
5714 }
5715 }
5716 }
5717
5718 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5719 String name = uri.getAuthority();
5720 ContentProviderHolder cph = getContentProviderExternal(name);
5721 ParcelFileDescriptor pfd = null;
5722 if (cph != null) {
5723 // We record the binder invoker's uid in thread-local storage before
5724 // going to the content provider to open the file. Later, in the code
5725 // that handles all permissions checks, we look for this uid and use
5726 // that rather than the Activity Manager's own uid. The effect is that
5727 // we do the check against the caller's permissions even though it looks
5728 // to the content provider like the Activity Manager itself is making
5729 // the request.
5730 sCallerIdentity.set(new Identity(
5731 Binder.getCallingPid(), Binder.getCallingUid()));
5732 try {
5733 pfd = cph.provider.openFile(uri, "r");
5734 } catch (FileNotFoundException e) {
5735 // do nothing; pfd will be returned null
5736 } finally {
5737 // Ensure that whatever happens, we clean up the identity state
5738 sCallerIdentity.remove();
5739 }
5740
5741 // We've got the fd now, so we're done with the provider.
5742 removeContentProviderExternal(name);
5743 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005744 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005745 }
5746 return pfd;
5747 }
5748
5749 public void goingToSleep() {
5750 synchronized(this) {
5751 mSleeping = true;
5752 mWindowManager.setEventDispatching(false);
5753
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005754 if (mMainStack.mResumedActivity != null) {
5755 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005757 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005759
5760 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005761 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005762 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5763 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005764 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 }
5766 }
5767
Dianne Hackborn55280a92009-05-07 15:53:46 -07005768 public boolean shutdown(int timeout) {
5769 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5770 != PackageManager.PERMISSION_GRANTED) {
5771 throw new SecurityException("Requires permission "
5772 + android.Manifest.permission.SHUTDOWN);
5773 }
5774
5775 boolean timedout = false;
5776
5777 synchronized(this) {
5778 mShuttingDown = true;
5779 mWindowManager.setEventDispatching(false);
5780
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005781 if (mMainStack.mResumedActivity != null) {
5782 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005783 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005784 while (mMainStack.mResumedActivity != null
5785 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005786 long delay = endTime - System.currentTimeMillis();
5787 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005788 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005789 timedout = true;
5790 break;
5791 }
5792 try {
5793 this.wait();
5794 } catch (InterruptedException e) {
5795 }
5796 }
5797 }
5798 }
5799
5800 mUsageStatsService.shutdown();
5801 mBatteryStatsService.shutdown();
5802
5803 return timedout;
5804 }
5805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 public void wakingUp() {
5807 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005808 if (mMainStack.mGoingToSleep.isHeld()) {
5809 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 }
5811 mWindowManager.setEventDispatching(true);
5812 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005813 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005814 }
5815 }
5816
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005817 public void stopAppSwitches() {
5818 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5819 != PackageManager.PERMISSION_GRANTED) {
5820 throw new SecurityException("Requires permission "
5821 + android.Manifest.permission.STOP_APP_SWITCHES);
5822 }
5823
5824 synchronized(this) {
5825 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5826 + APP_SWITCH_DELAY_TIME;
5827 mDidAppSwitch = false;
5828 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5829 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5830 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5831 }
5832 }
5833
5834 public void resumeAppSwitches() {
5835 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5836 != PackageManager.PERMISSION_GRANTED) {
5837 throw new SecurityException("Requires permission "
5838 + android.Manifest.permission.STOP_APP_SWITCHES);
5839 }
5840
5841 synchronized(this) {
5842 // Note that we don't execute any pending app switches... we will
5843 // let those wait until either the timeout, or the next start
5844 // activity request.
5845 mAppSwitchesAllowedTime = 0;
5846 }
5847 }
5848
5849 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5850 String name) {
5851 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5852 return true;
5853 }
5854
5855 final int perm = checkComponentPermission(
5856 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5857 callingUid, -1);
5858 if (perm == PackageManager.PERMISSION_GRANTED) {
5859 return true;
5860 }
5861
Joe Onorato8a9b2202010-02-26 18:56:32 -08005862 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005863 return false;
5864 }
5865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 public void setDebugApp(String packageName, boolean waitForDebugger,
5867 boolean persistent) {
5868 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5869 "setDebugApp()");
5870
5871 // Note that this is not really thread safe if there are multiple
5872 // callers into it at the same time, but that's not a situation we
5873 // care about.
5874 if (persistent) {
5875 final ContentResolver resolver = mContext.getContentResolver();
5876 Settings.System.putString(
5877 resolver, Settings.System.DEBUG_APP,
5878 packageName);
5879 Settings.System.putInt(
5880 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5881 waitForDebugger ? 1 : 0);
5882 }
5883
5884 synchronized (this) {
5885 if (!persistent) {
5886 mOrigDebugApp = mDebugApp;
5887 mOrigWaitForDebugger = mWaitForDebugger;
5888 }
5889 mDebugApp = packageName;
5890 mWaitForDebugger = waitForDebugger;
5891 mDebugTransient = !persistent;
5892 if (packageName != null) {
5893 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005894 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 Binder.restoreCallingIdentity(origId);
5896 }
5897 }
5898 }
5899
5900 public void setAlwaysFinish(boolean enabled) {
5901 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5902 "setAlwaysFinish()");
5903
5904 Settings.System.putInt(
5905 mContext.getContentResolver(),
5906 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5907
5908 synchronized (this) {
5909 mAlwaysFinishActivities = enabled;
5910 }
5911 }
5912
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005913 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005915 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005917 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 }
5919 }
5920
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005921 public boolean isUserAMonkey() {
5922 // For now the fact that there is a controller implies
5923 // we have a monkey.
5924 synchronized (this) {
5925 return mController != null;
5926 }
5927 }
5928
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005929 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005930 synchronized (this) {
5931 mWatchers.register(watcher);
5932 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005933 }
5934
5935 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005936 synchronized (this) {
5937 mWatchers.unregister(watcher);
5938 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005939 }
5940
Daniel Sandler69a48172010-06-23 16:29:36 -04005941 public void setImmersive(IBinder token, boolean immersive) {
5942 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005943 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005944 if (index < 0) {
5945 throw new IllegalArgumentException();
5946 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005947 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005948 r.immersive = immersive;
5949 }
5950 }
5951
5952 public boolean isImmersive(IBinder token) {
5953 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005954 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005955 if (index < 0) {
5956 throw new IllegalArgumentException();
5957 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005958 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005959 return r.immersive;
5960 }
5961 }
5962
5963 public boolean isTopActivityImmersive() {
5964 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005965 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005966 return (r != null) ? r.immersive : false;
5967 }
5968 }
5969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 public final void enterSafeMode() {
5971 synchronized(this) {
5972 // It only makes sense to do this before the system is ready
5973 // and started launching other packages.
5974 if (!mSystemReady) {
5975 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005976 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 } catch (RemoteException e) {
5978 }
5979
5980 View v = LayoutInflater.from(mContext).inflate(
5981 com.android.internal.R.layout.safe_mode, null);
5982 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07005983 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5985 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5986 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5987 lp.format = v.getBackground().getOpacity();
5988 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5989 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5990 ((WindowManager)mContext.getSystemService(
5991 Context.WINDOW_SERVICE)).addView(v, lp);
5992 }
5993 }
5994 }
5995
5996 public void noteWakeupAlarm(IIntentSender sender) {
5997 if (!(sender instanceof PendingIntentRecord)) {
5998 return;
5999 }
6000 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6001 synchronized (stats) {
6002 if (mBatteryStatsService.isOnBattery()) {
6003 mBatteryStatsService.enforceCallingPermission();
6004 PendingIntentRecord rec = (PendingIntentRecord)sender;
6005 int MY_UID = Binder.getCallingUid();
6006 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6007 BatteryStatsImpl.Uid.Pkg pkg =
6008 stats.getPackageStatsLocked(uid, rec.key.packageName);
6009 pkg.incWakeupsLocked();
6010 }
6011 }
6012 }
6013
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006014 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006016 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006018 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 // XXX Note: don't acquire main activity lock here, because the window
6020 // manager calls in with its locks held.
6021
6022 boolean killed = false;
6023 synchronized (mPidsSelfLocked) {
6024 int[] types = new int[pids.length];
6025 int worstType = 0;
6026 for (int i=0; i<pids.length; i++) {
6027 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6028 if (proc != null) {
6029 int type = proc.setAdj;
6030 types[i] = type;
6031 if (type > worstType) {
6032 worstType = type;
6033 }
6034 }
6035 }
6036
6037 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6038 // then constrain it so we will kill all hidden procs.
6039 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6040 worstType = HIDDEN_APP_MIN_ADJ;
6041 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006042 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 for (int i=0; i<pids.length; i++) {
6044 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6045 if (proc == null) {
6046 continue;
6047 }
6048 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006049 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006050 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006051 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6052 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006054 proc.killedBackground = true;
6055 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 }
6057 }
6058 }
6059 return killed;
6060 }
6061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006062 public final void startRunning(String pkg, String cls, String action,
6063 String data) {
6064 synchronized(this) {
6065 if (mStartRunning) {
6066 return;
6067 }
6068 mStartRunning = true;
6069 mTopComponent = pkg != null && cls != null
6070 ? new ComponentName(pkg, cls) : null;
6071 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6072 mTopData = data;
6073 if (!mSystemReady) {
6074 return;
6075 }
6076 }
6077
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006078 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 }
6080
6081 private void retrieveSettings() {
6082 final ContentResolver resolver = mContext.getContentResolver();
6083 String debugApp = Settings.System.getString(
6084 resolver, Settings.System.DEBUG_APP);
6085 boolean waitForDebugger = Settings.System.getInt(
6086 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6087 boolean alwaysFinishActivities = Settings.System.getInt(
6088 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6089
6090 Configuration configuration = new Configuration();
6091 Settings.System.getConfiguration(resolver, configuration);
6092
6093 synchronized (this) {
6094 mDebugApp = mOrigDebugApp = debugApp;
6095 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6096 mAlwaysFinishActivities = alwaysFinishActivities;
6097 // This happens before any activities are started, so we can
6098 // change mConfiguration in-place.
6099 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006100 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006101 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 }
6103 }
6104
6105 public boolean testIsSystemReady() {
6106 // no need to synchronize(this) just to read & return the value
6107 return mSystemReady;
6108 }
6109
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006110 private static File getCalledPreBootReceiversFile() {
6111 File dataDir = Environment.getDataDirectory();
6112 File systemDir = new File(dataDir, "system");
6113 File fname = new File(systemDir, "called_pre_boots.dat");
6114 return fname;
6115 }
6116
6117 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6118 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6119 File file = getCalledPreBootReceiversFile();
6120 FileInputStream fis = null;
6121 try {
6122 fis = new FileInputStream(file);
6123 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6124 int vers = dis.readInt();
6125 String codename = dis.readUTF();
6126 if (vers == android.os.Build.VERSION.SDK_INT
6127 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6128 int num = dis.readInt();
6129 while (num > 0) {
6130 num--;
6131 String pkg = dis.readUTF();
6132 String cls = dis.readUTF();
6133 lastDoneReceivers.add(new ComponentName(pkg, cls));
6134 }
6135 }
6136 } catch (FileNotFoundException e) {
6137 } catch (IOException e) {
6138 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6139 } finally {
6140 if (fis != null) {
6141 try {
6142 fis.close();
6143 } catch (IOException e) {
6144 }
6145 }
6146 }
6147 return lastDoneReceivers;
6148 }
6149
6150 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6151 File file = getCalledPreBootReceiversFile();
6152 FileOutputStream fos = null;
6153 DataOutputStream dos = null;
6154 try {
6155 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6156 fos = new FileOutputStream(file);
6157 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6158 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6159 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6160 dos.writeInt(list.size());
6161 for (int i=0; i<list.size(); i++) {
6162 dos.writeUTF(list.get(i).getPackageName());
6163 dos.writeUTF(list.get(i).getClassName());
6164 }
6165 } catch (IOException e) {
6166 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6167 file.delete();
6168 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006169 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006170 if (dos != null) {
6171 try {
6172 dos.close();
6173 } catch (IOException e) {
6174 // TODO Auto-generated catch block
6175 e.printStackTrace();
6176 }
6177 }
6178 }
6179 }
6180
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006181 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 // In the simulator, startRunning will never have been called, which
6183 // normally sets a few crucial variables. Do it here instead.
6184 if (!Process.supportsProcesses()) {
6185 mStartRunning = true;
6186 mTopAction = Intent.ACTION_MAIN;
6187 }
6188
6189 synchronized(this) {
6190 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006191 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192 return;
6193 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006194
6195 // Check to see if there are any update receivers to run.
6196 if (!mDidUpdate) {
6197 if (mWaitingUpdate) {
6198 return;
6199 }
6200 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6201 List<ResolveInfo> ris = null;
6202 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006203 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006204 intent, null, 0);
6205 } catch (RemoteException e) {
6206 }
6207 if (ris != null) {
6208 for (int i=ris.size()-1; i>=0; i--) {
6209 if ((ris.get(i).activityInfo.applicationInfo.flags
6210 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6211 ris.remove(i);
6212 }
6213 }
6214 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006215
6216 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6217
6218 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006219 for (int i=0; i<ris.size(); i++) {
6220 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006221 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6222 if (lastDoneReceivers.contains(comp)) {
6223 ris.remove(i);
6224 i--;
6225 }
6226 }
6227
6228 for (int i=0; i<ris.size(); i++) {
6229 ActivityInfo ai = ris.get(i).activityInfo;
6230 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6231 doneReceivers.add(comp);
6232 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006233 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006234 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006235 finisher = new IIntentReceiver.Stub() {
6236 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006237 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006238 boolean sticky) {
6239 // The raw IIntentReceiver interface is called
6240 // with the AM lock held, so redispatch to
6241 // execute our code without the lock.
6242 mHandler.post(new Runnable() {
6243 public void run() {
6244 synchronized (ActivityManagerService.this) {
6245 mDidUpdate = true;
6246 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006247 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006248 systemReady(goingCallback);
6249 }
6250 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006251 }
6252 };
6253 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006254 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006255 broadcastIntentLocked(null, null, intent, null, finisher,
6256 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006257 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006258 mWaitingUpdate = true;
6259 }
6260 }
6261 }
6262 if (mWaitingUpdate) {
6263 return;
6264 }
6265 mDidUpdate = true;
6266 }
6267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 mSystemReady = true;
6269 if (!mStartRunning) {
6270 return;
6271 }
6272 }
6273
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006274 ArrayList<ProcessRecord> procsToKill = null;
6275 synchronized(mPidsSelfLocked) {
6276 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6277 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6278 if (!isAllowedWhileBooting(proc.info)){
6279 if (procsToKill == null) {
6280 procsToKill = new ArrayList<ProcessRecord>();
6281 }
6282 procsToKill.add(proc);
6283 }
6284 }
6285 }
6286
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006287 synchronized(this) {
6288 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006289 for (int i=procsToKill.size()-1; i>=0; i--) {
6290 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006291 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006292 removeProcessLocked(proc, true);
6293 }
6294 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006295
6296 // Now that we have cleaned up any update processes, we
6297 // are ready to start launching real processes and know that
6298 // we won't trample on them any more.
6299 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006300 }
6301
Joe Onorato8a9b2202010-02-26 18:56:32 -08006302 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006303 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 SystemClock.uptimeMillis());
6305
6306 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006307 // Make sure we have no pre-ready processes sitting around.
6308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6310 ResolveInfo ri = mContext.getPackageManager()
6311 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006312 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 CharSequence errorMsg = null;
6314 if (ri != null) {
6315 ActivityInfo ai = ri.activityInfo;
6316 ApplicationInfo app = ai.applicationInfo;
6317 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6318 mTopAction = Intent.ACTION_FACTORY_TEST;
6319 mTopData = null;
6320 mTopComponent = new ComponentName(app.packageName,
6321 ai.name);
6322 } else {
6323 errorMsg = mContext.getResources().getText(
6324 com.android.internal.R.string.factorytest_not_system);
6325 }
6326 } else {
6327 errorMsg = mContext.getResources().getText(
6328 com.android.internal.R.string.factorytest_no_action);
6329 }
6330 if (errorMsg != null) {
6331 mTopAction = null;
6332 mTopData = null;
6333 mTopComponent = null;
6334 Message msg = Message.obtain();
6335 msg.what = SHOW_FACTORY_ERROR_MSG;
6336 msg.getData().putCharSequence("msg", errorMsg);
6337 mHandler.sendMessage(msg);
6338 }
6339 }
6340 }
6341
6342 retrieveSettings();
6343
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006344 if (goingCallback != null) goingCallback.run();
6345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 synchronized (this) {
6347 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6348 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006349 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006350 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 if (apps != null) {
6352 int N = apps.size();
6353 int i;
6354 for (i=0; i<N; i++) {
6355 ApplicationInfo info
6356 = (ApplicationInfo)apps.get(i);
6357 if (info != null &&
6358 !info.packageName.equals("android")) {
6359 addAppLocked(info);
6360 }
6361 }
6362 }
6363 } catch (RemoteException ex) {
6364 // pm is in same process, this will never happen.
6365 }
6366 }
6367
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006368 // Start up initial activity.
6369 mBooting = true;
6370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006372 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 Message msg = Message.obtain();
6374 msg.what = SHOW_UID_ERROR_MSG;
6375 mHandler.sendMessage(msg);
6376 }
6377 } catch (RemoteException e) {
6378 }
6379
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006380 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 }
6382 }
6383
Dan Egnorb7f03672009-12-09 16:22:32 -08006384 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006385 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006387 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006388 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006389 startAppProblemLocked(app);
6390 app.stopFreezingAllLocked();
6391 return handleAppCrashLocked(app);
6392 }
6393
Dan Egnorb7f03672009-12-09 16:22:32 -08006394 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006395 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006397 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006398 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6399 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 startAppProblemLocked(app);
6401 app.stopFreezingAllLocked();
6402 }
6403
6404 /**
6405 * Generate a process error record, suitable for attachment to a ProcessRecord.
6406 *
6407 * @param app The ProcessRecord in which the error occurred.
6408 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6409 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006410 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 * @param shortMsg Short message describing the crash.
6412 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006413 * @param stackTrace Full crash stack trace, may be null.
6414 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006415 * @return Returns a fully-formed AppErrorStateInfo record.
6416 */
6417 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006418 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 report.condition = condition;
6422 report.processName = app.processName;
6423 report.pid = app.pid;
6424 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006425 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 report.shortMsg = shortMsg;
6427 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006428 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429
6430 return report;
6431 }
6432
Dan Egnor42471dd2010-01-07 17:25:22 -08006433 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434 synchronized (this) {
6435 app.crashing = false;
6436 app.crashingReport = null;
6437 app.notResponding = false;
6438 app.notRespondingReport = null;
6439 if (app.anrDialog == fromDialog) {
6440 app.anrDialog = null;
6441 }
6442 if (app.waitDialog == fromDialog) {
6443 app.waitDialog = null;
6444 }
6445 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006446 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006447 Slog.i(ActivityManagerService.TAG, "Killing "
6448 + app.processName + " (pid=" + app.pid + "): user's request");
6449 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6450 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 Process.killProcess(app.pid);
6452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 }
6454 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006455
Dan Egnorb7f03672009-12-09 16:22:32 -08006456 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 long now = SystemClock.uptimeMillis();
6458
6459 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6460 app.info.uid);
6461 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6462 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006463 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006465 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 app.info.processName, app.info.uid);
6467 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006468 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6469 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006471 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006472 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006473 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006474 }
6475 }
6476 if (!app.persistent) {
6477 // We don't want to start this process again until the user
6478 // explicitly does so... but for persistent process, we really
6479 // need to keep it running. If a persistent process is actually
6480 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006481 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 app.info.processName);
6483 mBadProcesses.put(app.info.processName, app.info.uid, now);
6484 app.bad = true;
6485 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6486 app.removed = true;
6487 removeProcessLocked(app, false);
6488 return false;
6489 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006490 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006491 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006492 if (r.app == app) {
6493 // If the top running activity is from this crashing
6494 // process, then terminate it to avoid getting in a loop.
6495 Slog.w(TAG, " Force finishing activity "
6496 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006497 int index = mMainStack.indexOfTokenLocked(r);
6498 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006499 Activity.RESULT_CANCELED, null, "crashed");
6500 // Also terminate an activities below it that aren't yet
6501 // stopped, to avoid a situation where one will get
6502 // re-start our crashing activity once it gets resumed again.
6503 index--;
6504 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006505 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006506 if (r.state == ActivityState.RESUMED
6507 || r.state == ActivityState.PAUSING
6508 || r.state == ActivityState.PAUSED) {
6509 if (!r.isHomeActivity) {
6510 Slog.w(TAG, " Force finishing activity "
6511 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006512 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006513 Activity.RESULT_CANCELED, null, "crashed");
6514 }
6515 }
6516 }
6517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 }
6519
6520 // Bump up the crash count of any services currently running in the proc.
6521 if (app.services.size() != 0) {
6522 // Any services running in the application need to be placed
6523 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006524 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006526 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006527 sr.crashCount++;
6528 }
6529 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006530
6531 // If the crashing process is what we consider to be the "home process" and it has been
6532 // replaced by a third-party app, clear the package preferred activities from packages
6533 // with a home activity running in the process to prevent a repeatedly crashing app
6534 // from blocking the user to manually clear the list.
6535 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6536 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6537 Iterator it = mHomeProcess.activities.iterator();
6538 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006539 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006540 if (r.isHomeActivity) {
6541 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6542 try {
6543 ActivityThread.getPackageManager()
6544 .clearPackagePreferredActivities(r.packageName);
6545 } catch (RemoteException c) {
6546 // pm is in same process, this will never happen.
6547 }
6548 }
6549 }
6550 }
6551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006552 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6553 return true;
6554 }
6555
6556 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006557 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6558 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006559 skipCurrentReceiverLocked(app);
6560 }
6561
6562 void skipCurrentReceiverLocked(ProcessRecord app) {
6563 boolean reschedule = false;
6564 BroadcastRecord r = app.curReceiver;
6565 if (r != null) {
6566 // The current broadcast is waiting for this app's receiver
6567 // to be finished. Looks like that's not going to happen, so
6568 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006569 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006570 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6571 r.resultExtras, r.resultAbort, true);
6572 reschedule = true;
6573 }
6574 r = mPendingBroadcast;
6575 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006576 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006577 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006578 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006579 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6580 r.resultExtras, r.resultAbort, true);
6581 reschedule = true;
6582 }
6583 if (reschedule) {
6584 scheduleBroadcastsLocked();
6585 }
6586 }
6587
Dan Egnor60d87622009-12-16 16:32:58 -08006588 /**
6589 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6590 * The application process will exit immediately after this call returns.
6591 * @param app object of the crashing app, null for the system server
6592 * @param crashInfo describing the exception
6593 */
6594 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6595 ProcessRecord r = findAppProcess(app);
6596
6597 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6598 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006599 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006600 crashInfo.exceptionClassName,
6601 crashInfo.exceptionMessage,
6602 crashInfo.throwFileName,
6603 crashInfo.throwLineNumber);
6604
Dan Egnor42471dd2010-01-07 17:25:22 -08006605 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006606
6607 crashApplication(r, crashInfo);
6608 }
6609
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006610 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006611 IBinder app,
6612 int violationMask,
6613 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006614 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006615
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006616 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006617 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006618 boolean logIt = true;
6619 synchronized (mAlreadyLoggedViolatedStacks) {
6620 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6621 logIt = false;
6622 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006623 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006624 // the relative pain numbers, without logging all
6625 // the stack traces repeatedly. We'd want to do
6626 // likewise in the client code, which also does
6627 // dup suppression, before the Binder call.
6628 } else {
6629 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6630 mAlreadyLoggedViolatedStacks.clear();
6631 }
6632 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6633 }
6634 }
6635 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006636 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006637 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006638 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006639
6640 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6641 AppErrorResult result = new AppErrorResult();
6642 synchronized (this) {
6643 final long origId = Binder.clearCallingIdentity();
6644
6645 Message msg = Message.obtain();
6646 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6647 HashMap<String, Object> data = new HashMap<String, Object>();
6648 data.put("result", result);
6649 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006650 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006651 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006652 msg.obj = data;
6653 mHandler.sendMessage(msg);
6654
6655 Binder.restoreCallingIdentity(origId);
6656 }
6657 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006658 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006659 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006660 }
6661
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006662 // Depending on the policy in effect, there could be a bunch of
6663 // these in quick succession so we try to batch these together to
6664 // minimize disk writes, number of dropbox entries, and maximize
6665 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006666 private void logStrictModeViolationToDropBox(
6667 ProcessRecord process,
6668 StrictMode.ViolationInfo info) {
6669 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006670 return;
6671 }
6672 final boolean isSystemApp = process == null ||
6673 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6674 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6675 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6676 final DropBoxManager dbox = (DropBoxManager)
6677 mContext.getSystemService(Context.DROPBOX_SERVICE);
6678
6679 // Exit early if the dropbox isn't configured to accept this report type.
6680 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6681
6682 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006683 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006684 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6685 synchronized (sb) {
6686 bufferWasEmpty = sb.length() == 0;
6687 appendDropBoxProcessHeaders(process, sb);
6688 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6689 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006690 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6691 if (info.violationNumThisLoop != 0) {
6692 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6693 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006694 if (info.numAnimationsRunning != 0) {
6695 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6696 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006697 if (info.broadcastIntentAction != null) {
6698 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6699 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006700 if (info != null && info.durationMillis != -1) {
6701 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006702 }
6703 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006704 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6705 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006706 }
6707 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006708
6709 // Only buffer up to ~64k. Various logging bits truncate
6710 // things at 128k.
6711 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006712 }
6713
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006714 // Flush immediately if the buffer's grown too large, or this
6715 // is a non-system app. Non-system apps are isolated with a
6716 // different tag & policy and not batched.
6717 //
6718 // Batching is useful during internal testing with
6719 // StrictMode settings turned up high. Without batching,
6720 // thousands of separate files could be created on boot.
6721 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006722 new Thread("Error dump: " + dropboxTag) {
6723 @Override
6724 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006725 String report;
6726 synchronized (sb) {
6727 report = sb.toString();
6728 sb.delete(0, sb.length());
6729 sb.trimToSize();
6730 }
6731 if (report.length() != 0) {
6732 dbox.addText(dropboxTag, report);
6733 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006734 }
6735 }.start();
6736 return;
6737 }
6738
6739 // System app batching:
6740 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006741 // An existing dropbox-writing thread is outstanding, so
6742 // we don't need to start it up. The existing thread will
6743 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006744 return;
6745 }
6746
6747 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6748 // (After this point, we shouldn't access AMS internal data structures.)
6749 new Thread("Error dump: " + dropboxTag) {
6750 @Override
6751 public void run() {
6752 // 5 second sleep to let stacks arrive and be batched together
6753 try {
6754 Thread.sleep(5000); // 5 seconds
6755 } catch (InterruptedException e) {}
6756
6757 String errorReport;
6758 synchronized (mStrictModeBuffer) {
6759 errorReport = mStrictModeBuffer.toString();
6760 if (errorReport.length() == 0) {
6761 return;
6762 }
6763 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6764 mStrictModeBuffer.trimToSize();
6765 }
6766 dbox.addText(dropboxTag, errorReport);
6767 }
6768 }.start();
6769 }
6770
Dan Egnor60d87622009-12-16 16:32:58 -08006771 /**
6772 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6773 * @param app object of the crashing app, null for the system server
6774 * @param tag reported by the caller
6775 * @param crashInfo describing the context of the error
6776 * @return true if the process should exit immediately (WTF is fatal)
6777 */
6778 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006779 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006780 ProcessRecord r = findAppProcess(app);
6781
6782 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6783 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006784 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006785 tag, crashInfo.exceptionMessage);
6786
Dan Egnor42471dd2010-01-07 17:25:22 -08006787 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006788
Doug Zongker43866e02010-01-07 12:09:54 -08006789 if (Settings.Secure.getInt(mContext.getContentResolver(),
6790 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006791 crashApplication(r, crashInfo);
6792 return true;
6793 } else {
6794 return false;
6795 }
6796 }
6797
6798 /**
6799 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6800 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6801 */
6802 private ProcessRecord findAppProcess(IBinder app) {
6803 if (app == null) {
6804 return null;
6805 }
6806
6807 synchronized (this) {
6808 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6809 final int NA = apps.size();
6810 for (int ia=0; ia<NA; ia++) {
6811 ProcessRecord p = apps.valueAt(ia);
6812 if (p.thread != null && p.thread.asBinder() == app) {
6813 return p;
6814 }
6815 }
6816 }
6817
Joe Onorato8a9b2202010-02-26 18:56:32 -08006818 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006819 return null;
6820 }
6821 }
6822
6823 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006824 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6825 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006826 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006827 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6828 // Note: ProcessRecord 'process' is guarded by the service
6829 // instance. (notably process.pkgList, which could otherwise change
6830 // concurrently during execution of this method)
6831 synchronized (this) {
6832 if (process == null || process.pid == MY_PID) {
6833 sb.append("Process: system_server\n");
6834 } else {
6835 sb.append("Process: ").append(process.processName).append("\n");
6836 }
6837 if (process == null) {
6838 return;
6839 }
Dan Egnora455d192010-03-12 08:52:28 -08006840 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006841 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006842 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6843 for (String pkg : process.pkgList) {
6844 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006845 try {
Dan Egnora455d192010-03-12 08:52:28 -08006846 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6847 if (pi != null) {
6848 sb.append(" v").append(pi.versionCode);
6849 if (pi.versionName != null) {
6850 sb.append(" (").append(pi.versionName).append(")");
6851 }
6852 }
6853 } catch (RemoteException e) {
6854 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006855 }
Dan Egnora455d192010-03-12 08:52:28 -08006856 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006857 }
Dan Egnora455d192010-03-12 08:52:28 -08006858 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006859 }
6860
6861 private static String processClass(ProcessRecord process) {
6862 if (process == null || process.pid == MY_PID) {
6863 return "system_server";
6864 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6865 return "system_app";
6866 } else {
6867 return "data_app";
6868 }
6869 }
6870
6871 /**
6872 * Write a description of an error (crash, WTF, ANR) to the drop box.
6873 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6874 * @param process which caused the error, null means the system server
6875 * @param activity which triggered the error, null if unknown
6876 * @param parent activity related to the error, null if unknown
6877 * @param subject line related to the error, null if absent
6878 * @param report in long form describing the error, null if absent
6879 * @param logFile to include in the report, null if none
6880 * @param crashInfo giving an application stack trace, null if absent
6881 */
6882 public void addErrorToDropBox(String eventType,
6883 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6884 final String report, final File logFile,
6885 final ApplicationErrorReport.CrashInfo crashInfo) {
6886 // NOTE -- this must never acquire the ActivityManagerService lock,
6887 // otherwise the watchdog may be prevented from resetting the system.
6888
6889 final String dropboxTag = processClass(process) + "_" + eventType;
6890 final DropBoxManager dbox = (DropBoxManager)
6891 mContext.getSystemService(Context.DROPBOX_SERVICE);
6892
6893 // Exit early if the dropbox isn't configured to accept this report type.
6894 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6895
6896 final StringBuilder sb = new StringBuilder(1024);
6897 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006898 if (activity != null) {
6899 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6900 }
6901 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6902 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6903 }
6904 if (parent != null && parent != activity) {
6905 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6906 }
6907 if (subject != null) {
6908 sb.append("Subject: ").append(subject).append("\n");
6909 }
6910 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006911 if (Debug.isDebuggerConnected()) {
6912 sb.append("Debugger: Connected\n");
6913 }
Dan Egnora455d192010-03-12 08:52:28 -08006914 sb.append("\n");
6915
6916 // Do the rest in a worker thread to avoid blocking the caller on I/O
6917 // (After this point, we shouldn't access AMS internal data structures.)
6918 Thread worker = new Thread("Error dump: " + dropboxTag) {
6919 @Override
6920 public void run() {
6921 if (report != null) {
6922 sb.append(report);
6923 }
6924 if (logFile != null) {
6925 try {
6926 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6927 } catch (IOException e) {
6928 Slog.e(TAG, "Error reading " + logFile, e);
6929 }
6930 }
6931 if (crashInfo != null && crashInfo.stackTrace != null) {
6932 sb.append(crashInfo.stackTrace);
6933 }
6934
6935 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6936 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6937 if (lines > 0) {
6938 sb.append("\n");
6939
6940 // Merge several logcat streams, and take the last N lines
6941 InputStreamReader input = null;
6942 try {
6943 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6944 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6945 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6946
6947 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6948 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6949 input = new InputStreamReader(logcat.getInputStream());
6950
6951 int num;
6952 char[] buf = new char[8192];
6953 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6954 } catch (IOException e) {
6955 Slog.e(TAG, "Error running logcat", e);
6956 } finally {
6957 if (input != null) try { input.close(); } catch (IOException e) {}
6958 }
6959 }
6960
6961 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006962 }
Dan Egnora455d192010-03-12 08:52:28 -08006963 };
6964
6965 if (process == null || process.pid == MY_PID) {
6966 worker.run(); // We may be about to die -- need to run this synchronously
6967 } else {
6968 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006969 }
6970 }
6971
6972 /**
6973 * Bring up the "unexpected error" dialog box for a crashing app.
6974 * Deal with edge cases (intercepts from instrumented applications,
6975 * ActivityController, error intent receivers, that sort of thing).
6976 * @param r the application crashing
6977 * @param crashInfo describing the failure
6978 */
6979 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006980 long timeMillis = System.currentTimeMillis();
6981 String shortMsg = crashInfo.exceptionClassName;
6982 String longMsg = crashInfo.exceptionMessage;
6983 String stackTrace = crashInfo.stackTrace;
6984 if (shortMsg != null && longMsg != null) {
6985 longMsg = shortMsg + ": " + longMsg;
6986 } else if (shortMsg != null) {
6987 longMsg = shortMsg;
6988 }
6989
Dan Egnor60d87622009-12-16 16:32:58 -08006990 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006991 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006992 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 try {
6994 String name = r != null ? r.processName : null;
6995 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006996 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006997 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006998 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006999 + " at watcher's request");
7000 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007001 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007002 }
7003 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007004 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007005 }
7006 }
7007
7008 final long origId = Binder.clearCallingIdentity();
7009
7010 // If this process is running instrumentation, finish it.
7011 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007012 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007014 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7015 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007016 Bundle info = new Bundle();
7017 info.putString("shortMsg", shortMsg);
7018 info.putString("longMsg", longMsg);
7019 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7020 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007021 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022 }
7023
Dan Egnor60d87622009-12-16 16:32:58 -08007024 // If we can't identify the process or it's already exceeded its crash quota,
7025 // quit right away without showing a crash dialog.
7026 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007028 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 }
7030
7031 Message msg = Message.obtain();
7032 msg.what = SHOW_ERROR_MSG;
7033 HashMap data = new HashMap();
7034 data.put("result", result);
7035 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 msg.obj = data;
7037 mHandler.sendMessage(msg);
7038
7039 Binder.restoreCallingIdentity(origId);
7040 }
7041
7042 int res = result.get();
7043
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007044 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 synchronized (this) {
7046 if (r != null) {
7047 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7048 SystemClock.uptimeMillis());
7049 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007050 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007051 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007052 }
7053 }
7054
7055 if (appErrorIntent != null) {
7056 try {
7057 mContext.startActivity(appErrorIntent);
7058 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007059 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007063
7064 Intent createAppErrorIntentLocked(ProcessRecord r,
7065 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7066 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007067 if (report == null) {
7068 return null;
7069 }
7070 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7071 result.setComponent(r.errorReportReceiver);
7072 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7073 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7074 return result;
7075 }
7076
Dan Egnorb7f03672009-12-09 16:22:32 -08007077 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7078 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007079 if (r.errorReportReceiver == null) {
7080 return null;
7081 }
7082
7083 if (!r.crashing && !r.notResponding) {
7084 return null;
7085 }
7086
Dan Egnorb7f03672009-12-09 16:22:32 -08007087 ApplicationErrorReport report = new ApplicationErrorReport();
7088 report.packageName = r.info.packageName;
7089 report.installerPackageName = r.errorReportReceiver.getPackageName();
7090 report.processName = r.processName;
7091 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007092 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007093
Dan Egnorb7f03672009-12-09 16:22:32 -08007094 if (r.crashing) {
7095 report.type = ApplicationErrorReport.TYPE_CRASH;
7096 report.crashInfo = crashInfo;
7097 } else if (r.notResponding) {
7098 report.type = ApplicationErrorReport.TYPE_ANR;
7099 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007100
Dan Egnorb7f03672009-12-09 16:22:32 -08007101 report.anrInfo.activity = r.notRespondingReport.tag;
7102 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7103 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007104 }
7105
Dan Egnorb7f03672009-12-09 16:22:32 -08007106 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007107 }
7108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007109 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7110 // assume our apps are happy - lazy create the list
7111 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7112
7113 synchronized (this) {
7114
7115 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007116 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7117 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007118 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7119 // This one's in trouble, so we'll generate a report for it
7120 // crashes are higher priority (in case there's a crash *and* an anr)
7121 ActivityManager.ProcessErrorStateInfo report = null;
7122 if (app.crashing) {
7123 report = app.crashingReport;
7124 } else if (app.notResponding) {
7125 report = app.notRespondingReport;
7126 }
7127
7128 if (report != null) {
7129 if (errList == null) {
7130 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7131 }
7132 errList.add(report);
7133 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007134 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 " crashing = " + app.crashing +
7136 " notResponding = " + app.notResponding);
7137 }
7138 }
7139 }
7140 }
7141
7142 return errList;
7143 }
7144
7145 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7146 // Lazy instantiation of list
7147 List<ActivityManager.RunningAppProcessInfo> runList = null;
7148 synchronized (this) {
7149 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007150 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7151 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7153 // Generate process state info for running application
7154 ActivityManager.RunningAppProcessInfo currApp =
7155 new ActivityManager.RunningAppProcessInfo(app.processName,
7156 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007157 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007158 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007159 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007160 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007161 if (app.persistent) {
7162 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007165 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007166 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7167 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7168 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007169 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7170 } else if (adj >= HOME_APP_ADJ) {
7171 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7172 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173 } else if (adj >= SECONDARY_SERVER_ADJ) {
7174 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007175 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007176 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007177 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7178 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007179 } else if (adj >= VISIBLE_APP_ADJ) {
7180 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7181 } else {
7182 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7183 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007184 currApp.importanceReasonCode = app.adjTypeCode;
7185 if (app.adjSource instanceof ProcessRecord) {
7186 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007187 } else if (app.adjSource instanceof ActivityRecord) {
7188 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007189 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7190 }
7191 if (app.adjTarget instanceof ComponentName) {
7192 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7193 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007194 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 // + " lru=" + currApp.lru);
7196 if (runList == null) {
7197 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7198 }
7199 runList.add(currApp);
7200 }
7201 }
7202 }
7203 return runList;
7204 }
7205
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007206 public List<ApplicationInfo> getRunningExternalApplications() {
7207 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7208 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7209 if (runningApps != null && runningApps.size() > 0) {
7210 Set<String> extList = new HashSet<String>();
7211 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7212 if (app.pkgList != null) {
7213 for (String pkg : app.pkgList) {
7214 extList.add(pkg);
7215 }
7216 }
7217 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007218 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007219 for (String pkg : extList) {
7220 try {
7221 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7222 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7223 retList.add(info);
7224 }
7225 } catch (RemoteException e) {
7226 }
7227 }
7228 }
7229 return retList;
7230 }
7231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 @Override
7233 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007234 if (checkCallingPermission(android.Manifest.permission.DUMP)
7235 != PackageManager.PERMISSION_GRANTED) {
7236 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7237 + Binder.getCallingPid()
7238 + ", uid=" + Binder.getCallingUid()
7239 + " without permission "
7240 + android.Manifest.permission.DUMP);
7241 return;
7242 }
7243
7244 boolean dumpAll = false;
7245
7246 int opti = 0;
7247 while (opti < args.length) {
7248 String opt = args[opti];
7249 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7250 break;
7251 }
7252 opti++;
7253 if ("-a".equals(opt)) {
7254 dumpAll = true;
7255 } else if ("-h".equals(opt)) {
7256 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007257 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007258 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007259 pw.println(" a[ctivities]: activity stack state");
7260 pw.println(" b[roadcasts]: broadcast state");
7261 pw.println(" i[ntents]: pending intent state");
7262 pw.println(" p[rocesses]: process state");
7263 pw.println(" o[om]: out of memory management");
7264 pw.println(" prov[iders]: content provider state");
7265 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007266 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007268 } else {
7269 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007271 }
7272
7273 // Is the caller requesting to dump a particular piece of data?
7274 if (opti < args.length) {
7275 String cmd = args[opti];
7276 opti++;
7277 if ("activities".equals(cmd) || "a".equals(cmd)) {
7278 synchronized (this) {
7279 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007281 return;
7282 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7283 synchronized (this) {
7284 dumpBroadcastsLocked(fd, pw, args, opti, true);
7285 }
7286 return;
7287 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7288 synchronized (this) {
7289 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7290 }
7291 return;
7292 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7293 synchronized (this) {
7294 dumpProcessesLocked(fd, pw, args, opti, true);
7295 }
7296 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007297 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7298 synchronized (this) {
7299 dumpOomLocked(fd, pw, args, opti, true);
7300 }
7301 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007302 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7303 synchronized (this) {
7304 dumpProvidersLocked(fd, pw, args, opti, true);
7305 }
7306 return;
7307 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007308 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007309 return;
7310 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7311 synchronized (this) {
7312 dumpServicesLocked(fd, pw, args, opti, true);
7313 }
7314 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007315 } else {
7316 // Dumping a single activity?
7317 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7318 return;
7319 }
7320 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007322 }
7323
7324 // No piece of data specified, dump everything.
7325 synchronized (this) {
7326 boolean needSep;
7327 if (dumpAll) {
7328 pw.println("Providers in Current Activity Manager State:");
7329 }
7330 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7331 if (needSep) {
7332 pw.println(" ");
7333 }
7334 if (dumpAll) {
7335 pw.println("-------------------------------------------------------------------------------");
7336 pw.println("Broadcasts in Current Activity Manager State:");
7337 }
7338 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7339 if (needSep) {
7340 pw.println(" ");
7341 }
7342 if (dumpAll) {
7343 pw.println("-------------------------------------------------------------------------------");
7344 pw.println("Services in Current Activity Manager State:");
7345 }
7346 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7347 if (needSep) {
7348 pw.println(" ");
7349 }
7350 if (dumpAll) {
7351 pw.println("-------------------------------------------------------------------------------");
7352 pw.println("PendingIntents in Current Activity Manager State:");
7353 }
7354 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7355 if (needSep) {
7356 pw.println(" ");
7357 }
7358 if (dumpAll) {
7359 pw.println("-------------------------------------------------------------------------------");
7360 pw.println("Activities in Current Activity Manager State:");
7361 }
7362 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7363 if (needSep) {
7364 pw.println(" ");
7365 }
7366 if (dumpAll) {
7367 pw.println("-------------------------------------------------------------------------------");
7368 pw.println("Processes in Current Activity Manager State:");
7369 }
7370 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7371 }
7372 }
7373
7374 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7375 int opti, boolean dumpAll, boolean needHeader) {
7376 if (needHeader) {
7377 pw.println(" Activity stack:");
7378 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007379 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007380 pw.println(" ");
7381 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007382 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7383 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007385 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007386 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007387 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007388 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007391 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007392 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007393 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007394 pw.println(" ");
7395 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007396 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007399 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007400 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7401 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007403 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007405 if (dumpAll && mRecentTasks.size() > 0) {
7406 pw.println(" ");
7407 pw.println("Recent tasks in Current Activity Manager State:");
7408
7409 final int N = mRecentTasks.size();
7410 for (int i=0; i<N; i++) {
7411 TaskRecord tr = mRecentTasks.get(i);
7412 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7413 pw.println(tr);
7414 mRecentTasks.get(i).dump(pw, " ");
7415 }
7416 }
7417
7418 pw.println(" ");
7419 pw.println(" mCurTask: " + mCurTask);
7420
7421 return true;
7422 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007423
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007424 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7425 int opti, boolean dumpAll) {
7426 boolean needSep = false;
7427 int numPers = 0;
7428
7429 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7431 final int NA = procs.size();
7432 for (int ia=0; ia<NA; ia++) {
7433 if (!needSep) {
7434 pw.println(" All known processes:");
7435 needSep = true;
7436 }
7437 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007438 pw.print(r.persistent ? " *PERS*" : " *APP*");
7439 pw.print(" UID "); pw.print(procs.keyAt(ia));
7440 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441 r.dump(pw, " ");
7442 if (r.persistent) {
7443 numPers++;
7444 }
7445 }
7446 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007447 }
7448
7449 if (mLruProcesses.size() > 0) {
7450 if (needSep) pw.println(" ");
7451 needSep = true;
7452 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007453 dumpProcessOomList(pw, this, mLruProcesses, " ",
7454 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007455 needSep = true;
7456 }
7457
7458 synchronized (mPidsSelfLocked) {
7459 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 if (needSep) pw.println(" ");
7461 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007462 pw.println(" PID mappings:");
7463 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7464 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7465 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 }
7467 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007468 }
7469
7470 if (mForegroundProcesses.size() > 0) {
7471 if (needSep) pw.println(" ");
7472 needSep = true;
7473 pw.println(" Foreground Processes:");
7474 for (int i=0; i<mForegroundProcesses.size(); i++) {
7475 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7476 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007478 }
7479
7480 if (mPersistentStartingProcesses.size() > 0) {
7481 if (needSep) pw.println(" ");
7482 needSep = true;
7483 pw.println(" Persisent processes that are starting:");
7484 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007485 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007488 if (mStartingProcesses.size() > 0) {
7489 if (needSep) pw.println(" ");
7490 needSep = true;
7491 pw.println(" Processes that are starting:");
7492 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007493 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007496 if (mRemovedProcesses.size() > 0) {
7497 if (needSep) pw.println(" ");
7498 needSep = true;
7499 pw.println(" Processes that are being removed:");
7500 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007501 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007502 }
7503
7504 if (mProcessesOnHold.size() > 0) {
7505 if (needSep) pw.println(" ");
7506 needSep = true;
7507 pw.println(" Processes that are on old until the system is ready:");
7508 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007509 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007511
Dianne Hackborn287952c2010-09-22 22:34:31 -07007512 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007513
7514 if (mProcessCrashTimes.getMap().size() > 0) {
7515 if (needSep) pw.println(" ");
7516 needSep = true;
7517 pw.println(" Time since processes crashed:");
7518 long now = SystemClock.uptimeMillis();
7519 for (Map.Entry<String, SparseArray<Long>> procs
7520 : mProcessCrashTimes.getMap().entrySet()) {
7521 SparseArray<Long> uids = procs.getValue();
7522 final int N = uids.size();
7523 for (int i=0; i<N; i++) {
7524 pw.print(" Process "); pw.print(procs.getKey());
7525 pw.print(" uid "); pw.print(uids.keyAt(i));
7526 pw.print(": last crashed ");
7527 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007528 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007529 }
7530 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007533 if (mBadProcesses.getMap().size() > 0) {
7534 if (needSep) pw.println(" ");
7535 needSep = true;
7536 pw.println(" Bad processes:");
7537 for (Map.Entry<String, SparseArray<Long>> procs
7538 : mBadProcesses.getMap().entrySet()) {
7539 SparseArray<Long> uids = procs.getValue();
7540 final int N = uids.size();
7541 for (int i=0; i<N; i++) {
7542 pw.print(" Bad process "); pw.print(procs.getKey());
7543 pw.print(" uid "); pw.print(uids.keyAt(i));
7544 pw.print(": crashed at time ");
7545 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 }
7547 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007550 pw.println(" ");
7551 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007552 if (mHeavyWeightProcess != null) {
7553 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7554 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007555 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007556 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007557 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7558 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7559 || mOrigWaitForDebugger) {
7560 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7561 + " mDebugTransient=" + mDebugTransient
7562 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7563 }
7564 if (mAlwaysFinishActivities || mController != null) {
7565 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7566 + " mController=" + mController);
7567 }
7568 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007571 + " mProcessesReady=" + mProcessesReady
7572 + " mSystemReady=" + mSystemReady);
7573 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007574 + " mBooted=" + mBooted
7575 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007576 pw.print(" mLastPowerCheckRealtime=");
7577 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7578 pw.println("");
7579 pw.print(" mLastPowerCheckUptime=");
7580 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7581 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007582 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7583 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007584 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007586
7587 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 }
7589
Dianne Hackborn287952c2010-09-22 22:34:31 -07007590 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7591 int opti, boolean needSep, boolean dumpAll) {
7592 if (mProcessesToGc.size() > 0) {
7593 if (needSep) pw.println(" ");
7594 needSep = true;
7595 pw.println(" Processes that are waiting to GC:");
7596 long now = SystemClock.uptimeMillis();
7597 for (int i=0; i<mProcessesToGc.size(); i++) {
7598 ProcessRecord proc = mProcessesToGc.get(i);
7599 pw.print(" Process "); pw.println(proc);
7600 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7601 pw.print(", last gced=");
7602 pw.print(now-proc.lastRequestedGc);
7603 pw.print(" ms ago, last lowMem=");
7604 pw.print(now-proc.lastLowMemory);
7605 pw.println(" ms ago");
7606
7607 }
7608 }
7609 return needSep;
7610 }
7611
7612 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7613 int opti, boolean dumpAll) {
7614 boolean needSep = false;
7615
7616 if (mLruProcesses.size() > 0) {
7617 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7618
7619 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7620 @Override
7621 public int compare(ProcessRecord object1, ProcessRecord object2) {
7622 if (object1.setAdj != object2.setAdj) {
7623 return object1.setAdj > object2.setAdj ? -1 : 1;
7624 }
7625 if (object1.setSchedGroup != object2.setSchedGroup) {
7626 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7627 }
7628 if (object1.keeping != object2.keeping) {
7629 return object1.keeping ? -1 : 1;
7630 }
7631 if (object1.pid != object2.pid) {
7632 return object1.pid > object2.pid ? -1 : 1;
7633 }
7634 return 0;
7635 }
7636 };
7637
7638 Collections.sort(procs, comparator);
7639
7640 if (needSep) pw.println(" ");
7641 needSep = true;
7642 pw.println(" Process OOM control:");
7643 dumpProcessOomList(pw, this, procs, " ",
7644 "Proc", "PERS", true);
7645 needSep = true;
7646 }
7647
7648 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7649
7650 pw.println(" ");
7651 pw.println(" mHomeProcess: " + mHomeProcess);
7652 if (mHeavyWeightProcess != null) {
7653 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7654 }
7655
7656 return true;
7657 }
7658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659 /**
7660 * There are three ways to call this:
7661 * - no service specified: dump all the services
7662 * - a flattened component name that matched an existing service was specified as the
7663 * first arg: dump that one service
7664 * - the first arg isn't the flattened component name of an existing service:
7665 * dump all services whose component contains the first arg as a substring
7666 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007667 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 String[] newArgs;
7669 String componentNameString;
7670 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007671 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007672 componentNameString = null;
7673 newArgs = EMPTY_STRING_ARRAY;
7674 r = null;
7675 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007676 componentNameString = args[opti];
7677 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007679 synchronized (this) {
7680 r = componentName != null ? mServices.get(componentName) : null;
7681 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007682 newArgs = new String[args.length - opti];
7683 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 }
7685
7686 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007687 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007689 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7690 synchronized (this) {
7691 for (ServiceRecord r1 : mServices.values()) {
7692 if (componentNameString == null
7693 || r1.name.flattenToString().contains(componentNameString)) {
7694 services.add(r1);
7695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007696 }
7697 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007698 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007699 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 }
7702 }
7703
7704 /**
7705 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7706 * there is a thread associated with the service.
7707 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007708 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7709 pw.println("------------------------------------------------------------"
7710 + "-------------------");
7711 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007712 if (r.app != null && r.app.thread != null) {
7713 try {
7714 // flush anything that is already in the PrintWriter since the thread is going
7715 // to write to the file descriptor directly
7716 pw.flush();
7717 r.app.thread.dumpService(fd, r, args);
7718 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007719 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 } catch (RemoteException e) {
7721 pw.println("got a RemoteException while dumping the service");
7722 }
7723 }
7724 }
7725
Dianne Hackborn625ac272010-09-17 18:29:22 -07007726 /**
7727 * There are three things that cmd can be:
7728 * - a flattened component name that matched an existing activity
7729 * - the cmd arg isn't the flattened component name of an existing activity:
7730 * dump all activity whose component contains the cmd as a substring
7731 * - A hex number of the ActivityRecord object instance.
7732 */
7733 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7734 int opti, boolean dumpAll) {
7735 String[] newArgs;
7736 ComponentName componentName = ComponentName.unflattenFromString(name);
7737 int objectId = 0;
7738 try {
7739 objectId = Integer.parseInt(name, 16);
7740 name = null;
7741 componentName = null;
7742 } catch (RuntimeException e) {
7743 }
7744 newArgs = new String[args.length - opti];
7745 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7746
7747 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7748 synchronized (this) {
7749 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7750 if (componentName != null) {
7751 if (r1.intent.getComponent().equals(componentName)) {
7752 activities.add(r1);
7753 }
7754 } else if (name != null) {
7755 if (r1.intent.getComponent().flattenToString().contains(name)) {
7756 activities.add(r1);
7757 }
7758 } else if (System.identityHashCode(this) == objectId) {
7759 activities.add(r1);
7760 }
7761 }
7762 }
7763
7764 if (activities.size() <= 0) {
7765 return false;
7766 }
7767
7768 for (int i=0; i<activities.size(); i++) {
7769 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7770 }
7771 return true;
7772 }
7773
7774 /**
7775 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7776 * there is a thread associated with the activity.
7777 */
7778 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7779 boolean dumpAll) {
7780 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7781 if (dumpAll) {
7782 synchronized (this) {
7783 pw.print(" * "); pw.println(r);
7784 r.dump(pw, " ");
7785 }
7786 pw.println("");
7787 }
7788 if (r.app != null && r.app.thread != null) {
7789 try {
7790 // flush anything that is already in the PrintWriter since the thread is going
7791 // to write to the file descriptor directly
7792 pw.flush();
7793 r.app.thread.dumpActivity(fd, r, args);
7794 pw.print("\n");
7795 pw.flush();
7796 } catch (RemoteException e) {
7797 pw.println("got a RemoteException while dumping the activity");
7798 }
7799 }
7800 }
7801
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007802 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7803 int opti, boolean dumpAll) {
7804 boolean needSep = false;
7805
7806 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 if (mRegisteredReceivers.size() > 0) {
7808 pw.println(" ");
7809 pw.println(" Registered Receivers:");
7810 Iterator it = mRegisteredReceivers.values().iterator();
7811 while (it.hasNext()) {
7812 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007813 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 r.dump(pw, " ");
7815 }
7816 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007818 pw.println(" ");
7819 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007820 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007821 needSep = true;
7822 }
7823
7824 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7825 || mPendingBroadcast != null) {
7826 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007828 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007829 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007830 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7831 pw.println(" Broadcast #" + i + ":");
7832 mParallelBroadcasts.get(i).dump(pw, " ");
7833 }
7834 if (mOrderedBroadcasts.size() > 0) {
7835 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007836 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007837 }
7838 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7839 pw.println(" Serialized Broadcast #" + i + ":");
7840 mOrderedBroadcasts.get(i).dump(pw, " ");
7841 }
7842 pw.println(" ");
7843 pw.println(" Pending broadcast:");
7844 if (mPendingBroadcast != null) {
7845 mPendingBroadcast.dump(pw, " ");
7846 } else {
7847 pw.println(" (null)");
7848 }
7849 needSep = true;
7850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007852 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007854 pw.println(" Historical broadcasts:");
7855 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7856 BroadcastRecord r = mBroadcastHistory[i];
7857 if (r == null) {
7858 break;
7859 }
7860 pw.println(" Historical Broadcast #" + i + ":");
7861 r.dump(pw, " ");
7862 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007863 needSep = true;
7864 }
7865
7866 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007867 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007868 pw.println(" Sticky broadcasts:");
7869 StringBuilder sb = new StringBuilder(128);
7870 for (Map.Entry<String, ArrayList<Intent>> ent
7871 : mStickyBroadcasts.entrySet()) {
7872 pw.print(" * Sticky action "); pw.print(ent.getKey());
7873 pw.println(":");
7874 ArrayList<Intent> intents = ent.getValue();
7875 final int N = intents.size();
7876 for (int i=0; i<N; i++) {
7877 sb.setLength(0);
7878 sb.append(" Intent: ");
7879 intents.get(i).toShortString(sb, true, false);
7880 pw.println(sb.toString());
7881 Bundle bundle = intents.get(i).getExtras();
7882 if (bundle != null) {
7883 pw.print(" ");
7884 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007885 }
7886 }
7887 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007888 needSep = true;
7889 }
7890
7891 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007893 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 pw.println(" mHandler:");
7895 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007896 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007898
7899 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 }
7901
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7903 int opti, boolean dumpAll) {
7904 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007906 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 if (mServices.size() > 0) {
7908 pw.println(" Active services:");
7909 Iterator<ServiceRecord> it = mServices.values().iterator();
7910 while (it.hasNext()) {
7911 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007912 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 r.dump(pw, " ");
7914 }
7915 needSep = true;
7916 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007919 if (mPendingServices.size() > 0) {
7920 if (needSep) pw.println(" ");
7921 pw.println(" Pending services:");
7922 for (int i=0; i<mPendingServices.size(); i++) {
7923 ServiceRecord r = mPendingServices.get(i);
7924 pw.print(" * Pending "); pw.println(r);
7925 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007927 needSep = true;
7928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007930 if (mRestartingServices.size() > 0) {
7931 if (needSep) pw.println(" ");
7932 pw.println(" Restarting services:");
7933 for (int i=0; i<mRestartingServices.size(); i++) {
7934 ServiceRecord r = mRestartingServices.get(i);
7935 pw.print(" * Restarting "); pw.println(r);
7936 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007938 needSep = true;
7939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007941 if (mStoppingServices.size() > 0) {
7942 if (needSep) pw.println(" ");
7943 pw.println(" Stopping services:");
7944 for (int i=0; i<mStoppingServices.size(); i++) {
7945 ServiceRecord r = mStoppingServices.get(i);
7946 pw.print(" * Stopping "); pw.println(r);
7947 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007949 needSep = true;
7950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007952 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 if (mServiceConnections.size() > 0) {
7954 if (needSep) pw.println(" ");
7955 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007956 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 = mServiceConnections.values().iterator();
7958 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007959 ArrayList<ConnectionRecord> r = it.next();
7960 for (int i=0; i<r.size(); i++) {
7961 pw.print(" * "); pw.println(r.get(i));
7962 r.get(i).dump(pw, " ");
7963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007964 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007965 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007966 }
7967 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007968
7969 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 }
7971
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007972 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7973 int opti, boolean dumpAll) {
7974 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007975
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007976 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977 if (mProvidersByClass.size() > 0) {
7978 if (needSep) pw.println(" ");
7979 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007980 Iterator<Map.Entry<String, ContentProviderRecord>> it
7981 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007982 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007983 Map.Entry<String, ContentProviderRecord> e = it.next();
7984 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007985 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 r.dump(pw, " ");
7987 }
7988 needSep = true;
7989 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007990
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007991 if (mProvidersByName.size() > 0) {
7992 pw.println(" ");
7993 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007994 Iterator<Map.Entry<String, ContentProviderRecord>> it
7995 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007996 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007997 Map.Entry<String, ContentProviderRecord> e = it.next();
7998 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007999 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8000 pw.println(r);
8001 }
8002 needSep = true;
8003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008004 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008005
8006 if (mLaunchingProviders.size() > 0) {
8007 if (needSep) pw.println(" ");
8008 pw.println(" Launching content providers:");
8009 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8010 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8011 pw.println(mLaunchingProviders.get(i));
8012 }
8013 needSep = true;
8014 }
8015
8016 if (mGrantedUriPermissions.size() > 0) {
8017 pw.println();
8018 pw.println("Granted Uri Permissions:");
8019 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8020 int uid = mGrantedUriPermissions.keyAt(i);
8021 HashMap<Uri, UriPermission> perms
8022 = mGrantedUriPermissions.valueAt(i);
8023 pw.print(" * UID "); pw.print(uid);
8024 pw.println(" holds:");
8025 for (UriPermission perm : perms.values()) {
8026 pw.print(" "); pw.println(perm);
8027 perm.dump(pw, " ");
8028 }
8029 }
8030 needSep = true;
8031 }
8032
8033 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008034 }
8035
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008036 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8037 int opti, boolean dumpAll) {
8038 boolean needSep = false;
8039
8040 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 if (this.mIntentSenderRecords.size() > 0) {
8042 Iterator<WeakReference<PendingIntentRecord>> it
8043 = mIntentSenderRecords.values().iterator();
8044 while (it.hasNext()) {
8045 WeakReference<PendingIntentRecord> ref = it.next();
8046 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008047 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008049 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 rec.dump(pw, " ");
8051 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008052 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008053 }
8054 }
8055 }
8056 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008057
8058 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059 }
8060
8061 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008062 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 TaskRecord lastTask = null;
8064 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008065 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008066 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067 if (lastTask != r.task) {
8068 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008069 pw.print(prefix);
8070 pw.print(full ? "* " : " ");
8071 pw.println(lastTask);
8072 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008073 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008076 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8077 pw.print(" #"); pw.print(i); pw.print(": ");
8078 pw.println(r);
8079 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008080 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 }
8083 }
8084
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008085 private static String buildOomTag(String prefix, String space, int val, int base) {
8086 if (val == base) {
8087 if (space == null) return prefix;
8088 return prefix + " ";
8089 }
8090 return prefix + "+" + Integer.toString(val-base);
8091 }
8092
8093 private static final int dumpProcessList(PrintWriter pw,
8094 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008095 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008097 final int N = list.size()-1;
8098 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008099 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008100 pw.println(String.format("%s%s #%2d: %s",
8101 prefix, (r.persistent ? persistentLabel : normalLabel),
8102 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 if (r.persistent) {
8104 numPers++;
8105 }
8106 }
8107 return numPers;
8108 }
8109
Dianne Hackborn287952c2010-09-22 22:34:31 -07008110 private static final void dumpProcessOomList(PrintWriter pw,
8111 ActivityManagerService service, List<ProcessRecord> list,
8112 String prefix, String normalLabel, String persistentLabel,
8113 boolean inclDetails) {
8114
8115 final long curRealtime = SystemClock.elapsedRealtime();
8116 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8117 final long curUptime = SystemClock.uptimeMillis();
8118 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8119
8120 final int N = list.size()-1;
8121 for (int i=N; i>=0; i--) {
8122 ProcessRecord r = list.get(i);
8123 String oomAdj;
8124 if (r.setAdj >= EMPTY_APP_ADJ) {
8125 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8126 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8127 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8128 } else if (r.setAdj >= HOME_APP_ADJ) {
8129 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8130 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8131 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8132 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8133 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8134 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8135 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8136 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8137 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8138 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8139 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8140 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8141 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8142 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8143 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8144 } else if (r.setAdj >= SYSTEM_ADJ) {
8145 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8146 } else {
8147 oomAdj = Integer.toString(r.setAdj);
8148 }
8149 String schedGroup;
8150 switch (r.setSchedGroup) {
8151 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8152 schedGroup = "B";
8153 break;
8154 case Process.THREAD_GROUP_DEFAULT:
8155 schedGroup = "F";
8156 break;
8157 default:
8158 schedGroup = Integer.toString(r.setSchedGroup);
8159 break;
8160 }
8161 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8162 prefix, (r.persistent ? persistentLabel : normalLabel),
8163 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8164 if (r.adjSource != null || r.adjTarget != null) {
8165 pw.print(prefix);
8166 pw.print(" ");
8167 if (r.adjTarget instanceof ComponentName) {
8168 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8169 } else if (r.adjTarget != null) {
8170 pw.print(r.adjTarget.toString());
8171 } else {
8172 pw.print("{null}");
8173 }
8174 pw.print("<=");
8175 if (r.adjSource instanceof ProcessRecord) {
8176 pw.print("Proc{");
8177 pw.print(((ProcessRecord)r.adjSource).toShortString());
8178 pw.println("}");
8179 } else if (r.adjSource != null) {
8180 pw.println(r.adjSource.toString());
8181 } else {
8182 pw.println("{null}");
8183 }
8184 }
8185 if (inclDetails) {
8186 pw.print(prefix);
8187 pw.print(" ");
8188 pw.print("oom: max="); pw.print(r.maxAdj);
8189 pw.print(" hidden="); pw.print(r.hiddenAdj);
8190 pw.print(" curRaw="); pw.print(r.curRawAdj);
8191 pw.print(" setRaw="); pw.print(r.setRawAdj);
8192 pw.print(" cur="); pw.print(r.curAdj);
8193 pw.print(" set="); pw.println(r.setAdj);
8194 pw.print(prefix);
8195 pw.print(" ");
8196 pw.print("keeping="); pw.print(r.keeping);
8197 pw.print(" hidden="); pw.print(r.hidden);
8198 pw.print(" empty="); pw.println(r.empty);
8199
8200 if (!r.keeping) {
8201 if (r.lastWakeTime != 0) {
8202 long wtime;
8203 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8204 synchronized (stats) {
8205 wtime = stats.getProcessWakeTime(r.info.uid,
8206 r.pid, curRealtime);
8207 }
8208 long timeUsed = wtime - r.lastWakeTime;
8209 pw.print(prefix);
8210 pw.print(" ");
8211 pw.print("keep awake over ");
8212 TimeUtils.formatDuration(realtimeSince, pw);
8213 pw.print(" used ");
8214 TimeUtils.formatDuration(timeUsed, pw);
8215 pw.print(" (");
8216 pw.print((timeUsed*100)/realtimeSince);
8217 pw.println("%)");
8218 }
8219 if (r.lastCpuTime != 0) {
8220 long timeUsed = r.curCpuTime - r.lastCpuTime;
8221 pw.print(prefix);
8222 pw.print(" ");
8223 pw.print("run cpu over ");
8224 TimeUtils.formatDuration(uptimeSince, pw);
8225 pw.print(" used ");
8226 TimeUtils.formatDuration(timeUsed, pw);
8227 pw.print(" (");
8228 pw.print((timeUsed*100)/uptimeSince);
8229 pw.println("%)");
8230 }
8231 }
8232 }
8233 }
8234 }
8235
Dianne Hackborn472ad872010-04-07 17:31:48 -07008236 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008237 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008238 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008239 long uptime = SystemClock.uptimeMillis();
8240 long realtime = SystemClock.elapsedRealtime();
8241
8242 if (isCheckinRequest) {
8243 // short checkin version
8244 pw.println(uptime + "," + realtime);
8245 pw.flush();
8246 } else {
8247 pw.println("Applications Memory Usage (kB):");
8248 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8249 }
8250 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8251 ProcessRecord r = (ProcessRecord)list.get(i);
8252 if (r.thread != null) {
8253 if (!isCheckinRequest) {
8254 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8255 pw.flush();
8256 }
8257 try {
8258 r.thread.asBinder().dump(fd, args);
8259 } catch (RemoteException e) {
8260 if (!isCheckinRequest) {
8261 pw.println("Got RemoteException!");
8262 pw.flush();
8263 }
8264 }
8265 }
8266 }
8267 }
8268
8269 /**
8270 * Searches array of arguments for the specified string
8271 * @param args array of argument strings
8272 * @param value value to search for
8273 * @return true if the value is contained in the array
8274 */
8275 private static boolean scanArgs(String[] args, String value) {
8276 if (args != null) {
8277 for (String arg : args) {
8278 if (value.equals(arg)) {
8279 return true;
8280 }
8281 }
8282 }
8283 return false;
8284 }
8285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008286 private final void killServicesLocked(ProcessRecord app,
8287 boolean allowRestart) {
8288 // Report disconnected services.
8289 if (false) {
8290 // XXX we are letting the client link to the service for
8291 // death notifications.
8292 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008293 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008295 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008296 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008297 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 = r.connections.values().iterator();
8299 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008300 ArrayList<ConnectionRecord> cl = jt.next();
8301 for (int i=0; i<cl.size(); i++) {
8302 ConnectionRecord c = cl.get(i);
8303 if (c.binding.client != app) {
8304 try {
8305 //c.conn.connected(r.className, null);
8306 } catch (Exception e) {
8307 // todo: this should be asynchronous!
8308 Slog.w(TAG, "Exception thrown disconnected servce "
8309 + r.shortName
8310 + " from app " + app.processName, e);
8311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 }
8313 }
8314 }
8315 }
8316 }
8317 }
8318 }
8319
8320 // Clean up any connections this application has to other services.
8321 if (app.connections.size() > 0) {
8322 Iterator<ConnectionRecord> it = app.connections.iterator();
8323 while (it.hasNext()) {
8324 ConnectionRecord r = it.next();
8325 removeConnectionLocked(r, app, null);
8326 }
8327 }
8328 app.connections.clear();
8329
8330 if (app.services.size() != 0) {
8331 // Any services running in the application need to be placed
8332 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008333 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008335 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 synchronized (sr.stats.getBatteryStats()) {
8337 sr.stats.stopLaunchedLocked();
8338 }
8339 sr.app = null;
8340 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008341 if (mStoppingServices.remove(sr)) {
8342 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8343 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008344
8345 boolean hasClients = sr.bindings.size() > 0;
8346 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 Iterator<IntentBindRecord> bindings
8348 = sr.bindings.values().iterator();
8349 while (bindings.hasNext()) {
8350 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008351 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008352 + ": shouldUnbind=" + b.hasBound);
8353 b.binder = null;
8354 b.requested = b.received = b.hasBound = false;
8355 }
8356 }
8357
8358 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008359 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008361 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 sr.crashCount, sr.shortName, app.pid);
8363 bringDownServiceLocked(sr, true);
8364 } else if (!allowRestart) {
8365 bringDownServiceLocked(sr, true);
8366 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008367 boolean canceled = scheduleServiceRestartLocked(sr, true);
8368
8369 // Should the service remain running? Note that in the
8370 // extreme case of so many attempts to deliver a command
8371 // that it failed, that we also will stop it here.
8372 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8373 if (sr.pendingStarts.size() == 0) {
8374 sr.startRequested = false;
8375 if (!hasClients) {
8376 // Whoops, no reason to restart!
8377 bringDownServiceLocked(sr, true);
8378 }
8379 }
8380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008381 }
8382 }
8383
8384 if (!allowRestart) {
8385 app.services.clear();
8386 }
8387 }
8388
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008389 // Make sure we have no more records on the stopping list.
8390 int i = mStoppingServices.size();
8391 while (i > 0) {
8392 i--;
8393 ServiceRecord sr = mStoppingServices.get(i);
8394 if (sr.app == app) {
8395 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008396 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008397 }
8398 }
8399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008400 app.executingServices.clear();
8401 }
8402
8403 private final void removeDyingProviderLocked(ProcessRecord proc,
8404 ContentProviderRecord cpr) {
8405 synchronized (cpr) {
8406 cpr.launchingApp = null;
8407 cpr.notifyAll();
8408 }
8409
8410 mProvidersByClass.remove(cpr.info.name);
8411 String names[] = cpr.info.authority.split(";");
8412 for (int j = 0; j < names.length; j++) {
8413 mProvidersByName.remove(names[j]);
8414 }
8415
8416 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8417 while (cit.hasNext()) {
8418 ProcessRecord capp = cit.next();
8419 if (!capp.persistent && capp.thread != null
8420 && capp.pid != 0
8421 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008422 Slog.i(TAG, "Kill " + capp.processName
8423 + " (pid " + capp.pid + "): provider " + cpr.info.name
8424 + " in dying process " + proc.processName);
8425 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8426 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427 Process.killProcess(capp.pid);
8428 }
8429 }
8430
8431 mLaunchingProviders.remove(cpr);
8432 }
8433
8434 /**
8435 * Main code for cleaning up a process when it has gone away. This is
8436 * called both as a result of the process dying, or directly when stopping
8437 * a process when running in single process mode.
8438 */
8439 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8440 boolean restarting, int index) {
8441 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008442 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 }
8444
Dianne Hackborn36124872009-10-08 16:22:03 -07008445 mProcessesToGc.remove(app);
8446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 // Dismiss any open dialogs.
8448 if (app.crashDialog != null) {
8449 app.crashDialog.dismiss();
8450 app.crashDialog = null;
8451 }
8452 if (app.anrDialog != null) {
8453 app.anrDialog.dismiss();
8454 app.anrDialog = null;
8455 }
8456 if (app.waitDialog != null) {
8457 app.waitDialog.dismiss();
8458 app.waitDialog = null;
8459 }
8460
8461 app.crashing = false;
8462 app.notResponding = false;
8463
8464 app.resetPackageList();
8465 app.thread = null;
8466 app.forcingToForeground = null;
8467 app.foregroundServices = false;
8468
8469 killServicesLocked(app, true);
8470
8471 boolean restart = false;
8472
8473 int NL = mLaunchingProviders.size();
8474
8475 // Remove published content providers.
8476 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008477 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008479 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 cpr.provider = null;
8481 cpr.app = null;
8482
8483 // See if someone is waiting for this provider... in which
8484 // case we don't remove it, but just let it restart.
8485 int i = 0;
8486 if (!app.bad) {
8487 for (; i<NL; i++) {
8488 if (mLaunchingProviders.get(i) == cpr) {
8489 restart = true;
8490 break;
8491 }
8492 }
8493 } else {
8494 i = NL;
8495 }
8496
8497 if (i >= NL) {
8498 removeDyingProviderLocked(app, cpr);
8499 NL = mLaunchingProviders.size();
8500 }
8501 }
8502 app.pubProviders.clear();
8503 }
8504
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008505 // Take care of any launching providers waiting for this process.
8506 if (checkAppInLaunchingProvidersLocked(app, false)) {
8507 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 // Unregister from connected content providers.
8511 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008512 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 while (it.hasNext()) {
8514 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8515 cpr.clients.remove(app);
8516 }
8517 app.conProviders.clear();
8518 }
8519
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008520 // At this point there may be remaining entries in mLaunchingProviders
8521 // where we were the only one waiting, so they are no longer of use.
8522 // Look for these and clean up if found.
8523 // XXX Commented out for now. Trying to figure out a way to reproduce
8524 // the actual situation to identify what is actually going on.
8525 if (false) {
8526 for (int i=0; i<NL; i++) {
8527 ContentProviderRecord cpr = (ContentProviderRecord)
8528 mLaunchingProviders.get(i);
8529 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8530 synchronized (cpr) {
8531 cpr.launchingApp = null;
8532 cpr.notifyAll();
8533 }
8534 }
8535 }
8536 }
8537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 skipCurrentReceiverLocked(app);
8539
8540 // Unregister any receivers.
8541 if (app.receivers.size() > 0) {
8542 Iterator<ReceiverList> it = app.receivers.iterator();
8543 while (it.hasNext()) {
8544 removeReceiverLocked(it.next());
8545 }
8546 app.receivers.clear();
8547 }
8548
Christopher Tate181fafa2009-05-14 11:12:14 -07008549 // If the app is undergoing backup, tell the backup manager about it
8550 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008551 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008552 try {
8553 IBackupManager bm = IBackupManager.Stub.asInterface(
8554 ServiceManager.getService(Context.BACKUP_SERVICE));
8555 bm.agentDisconnected(app.info.packageName);
8556 } catch (RemoteException e) {
8557 // can't happen; backup manager is local
8558 }
8559 }
8560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 // If the caller is restarting this app, then leave it in its
8562 // current lists and let the caller take care of it.
8563 if (restarting) {
8564 return;
8565 }
8566
8567 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008568 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 "Removing non-persistent process during cleanup: " + app);
8570 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008571 if (mHeavyWeightProcess == app) {
8572 mHeavyWeightProcess = null;
8573 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 } else if (!app.removed) {
8576 // This app is persistent, so we need to keep its record around.
8577 // If it is not already on the pending app list, add it there
8578 // and start a new process for it.
8579 app.thread = null;
8580 app.forcingToForeground = null;
8581 app.foregroundServices = false;
8582 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8583 mPersistentStartingProcesses.add(app);
8584 restart = true;
8585 }
8586 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008587 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8588 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 mProcessesOnHold.remove(app);
8590
The Android Open Source Project4df24232009-03-05 14:34:35 -08008591 if (app == mHomeProcess) {
8592 mHomeProcess = null;
8593 }
8594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 if (restart) {
8596 // We have components that still need to be running in the
8597 // process, so re-launch it.
8598 mProcessNames.put(app.processName, app.info.uid, app);
8599 startProcessLocked(app, "restart", app.processName);
8600 } else if (app.pid > 0 && app.pid != MY_PID) {
8601 // Goodbye!
8602 synchronized (mPidsSelfLocked) {
8603 mPidsSelfLocked.remove(app.pid);
8604 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8605 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008606 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 }
8608 }
8609
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008610 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8611 // Look through the content providers we are waiting to have launched,
8612 // and if any run in this process then either schedule a restart of
8613 // the process or kill the client waiting for it if this process has
8614 // gone bad.
8615 int NL = mLaunchingProviders.size();
8616 boolean restart = false;
8617 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008618 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008619 if (cpr.launchingApp == app) {
8620 if (!alwaysBad && !app.bad) {
8621 restart = true;
8622 } else {
8623 removeDyingProviderLocked(app, cpr);
8624 NL = mLaunchingProviders.size();
8625 }
8626 }
8627 }
8628 return restart;
8629 }
8630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 // =========================================================
8632 // SERVICES
8633 // =========================================================
8634
8635 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8636 ActivityManager.RunningServiceInfo info =
8637 new ActivityManager.RunningServiceInfo();
8638 info.service = r.name;
8639 if (r.app != null) {
8640 info.pid = r.app.pid;
8641 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008642 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 info.process = r.processName;
8644 info.foreground = r.isForeground;
8645 info.activeSince = r.createTime;
8646 info.started = r.startRequested;
8647 info.clientCount = r.connections.size();
8648 info.crashCount = r.crashCount;
8649 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008650 if (r.isForeground) {
8651 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8652 }
8653 if (r.startRequested) {
8654 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8655 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008656 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008657 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8658 }
8659 if (r.app != null && r.app.persistent) {
8660 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8661 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008662
8663 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8664 for (int i=0; i<connl.size(); i++) {
8665 ConnectionRecord conn = connl.get(i);
8666 if (conn.clientLabel != 0) {
8667 info.clientPackage = conn.binding.client.info.packageName;
8668 info.clientLabel = conn.clientLabel;
8669 return info;
8670 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008671 }
8672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 return info;
8674 }
8675
8676 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8677 int flags) {
8678 synchronized (this) {
8679 ArrayList<ActivityManager.RunningServiceInfo> res
8680 = new ArrayList<ActivityManager.RunningServiceInfo>();
8681
8682 if (mServices.size() > 0) {
8683 Iterator<ServiceRecord> it = mServices.values().iterator();
8684 while (it.hasNext() && res.size() < maxNum) {
8685 res.add(makeRunningServiceInfoLocked(it.next()));
8686 }
8687 }
8688
8689 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8690 ServiceRecord r = mRestartingServices.get(i);
8691 ActivityManager.RunningServiceInfo info =
8692 makeRunningServiceInfoLocked(r);
8693 info.restarting = r.nextRestartTime;
8694 res.add(info);
8695 }
8696
8697 return res;
8698 }
8699 }
8700
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008701 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8702 synchronized (this) {
8703 ServiceRecord r = mServices.get(name);
8704 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008705 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8706 for (int i=0; i<conn.size(); i++) {
8707 if (conn.get(i).clientIntent != null) {
8708 return conn.get(i).clientIntent;
8709 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008710 }
8711 }
8712 }
8713 }
8714 return null;
8715 }
8716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 private final ServiceRecord findServiceLocked(ComponentName name,
8718 IBinder token) {
8719 ServiceRecord r = mServices.get(name);
8720 return r == token ? r : null;
8721 }
8722
8723 private final class ServiceLookupResult {
8724 final ServiceRecord record;
8725 final String permission;
8726
8727 ServiceLookupResult(ServiceRecord _record, String _permission) {
8728 record = _record;
8729 permission = _permission;
8730 }
8731 };
8732
8733 private ServiceLookupResult findServiceLocked(Intent service,
8734 String resolvedType) {
8735 ServiceRecord r = null;
8736 if (service.getComponent() != null) {
8737 r = mServices.get(service.getComponent());
8738 }
8739 if (r == null) {
8740 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8741 r = mServicesByIntent.get(filter);
8742 }
8743
8744 if (r == null) {
8745 try {
8746 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008747 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748 service, resolvedType, 0);
8749 ServiceInfo sInfo =
8750 rInfo != null ? rInfo.serviceInfo : null;
8751 if (sInfo == null) {
8752 return null;
8753 }
8754
8755 ComponentName name = new ComponentName(
8756 sInfo.applicationInfo.packageName, sInfo.name);
8757 r = mServices.get(name);
8758 } catch (RemoteException ex) {
8759 // pm is in same process, this will never happen.
8760 }
8761 }
8762 if (r != null) {
8763 int callingPid = Binder.getCallingPid();
8764 int callingUid = Binder.getCallingUid();
8765 if (checkComponentPermission(r.permission,
8766 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8767 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008768 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769 + " from pid=" + callingPid
8770 + ", uid=" + callingUid
8771 + " requires " + r.permission);
8772 return new ServiceLookupResult(null, r.permission);
8773 }
8774 return new ServiceLookupResult(r, null);
8775 }
8776 return null;
8777 }
8778
8779 private class ServiceRestarter implements Runnable {
8780 private ServiceRecord mService;
8781
8782 void setService(ServiceRecord service) {
8783 mService = service;
8784 }
8785
8786 public void run() {
8787 synchronized(ActivityManagerService.this) {
8788 performServiceRestartLocked(mService);
8789 }
8790 }
8791 }
8792
8793 private ServiceLookupResult retrieveServiceLocked(Intent service,
8794 String resolvedType, int callingPid, int callingUid) {
8795 ServiceRecord r = null;
8796 if (service.getComponent() != null) {
8797 r = mServices.get(service.getComponent());
8798 }
8799 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8800 r = mServicesByIntent.get(filter);
8801 if (r == null) {
8802 try {
8803 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008804 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008805 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 ServiceInfo sInfo =
8807 rInfo != null ? rInfo.serviceInfo : null;
8808 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008809 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008810 ": not found");
8811 return null;
8812 }
8813
8814 ComponentName name = new ComponentName(
8815 sInfo.applicationInfo.packageName, sInfo.name);
8816 r = mServices.get(name);
8817 if (r == null) {
8818 filter = new Intent.FilterComparison(service.cloneFilter());
8819 ServiceRestarter res = new ServiceRestarter();
8820 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8821 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8822 synchronized (stats) {
8823 ss = stats.getServiceStatsLocked(
8824 sInfo.applicationInfo.uid, sInfo.packageName,
8825 sInfo.name);
8826 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008827 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008828 res.setService(r);
8829 mServices.put(name, r);
8830 mServicesByIntent.put(filter, r);
8831
8832 // Make sure this component isn't in the pending list.
8833 int N = mPendingServices.size();
8834 for (int i=0; i<N; i++) {
8835 ServiceRecord pr = mPendingServices.get(i);
8836 if (pr.name.equals(name)) {
8837 mPendingServices.remove(i);
8838 i--;
8839 N--;
8840 }
8841 }
8842 }
8843 } catch (RemoteException ex) {
8844 // pm is in same process, this will never happen.
8845 }
8846 }
8847 if (r != null) {
8848 if (checkComponentPermission(r.permission,
8849 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8850 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008851 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008852 + " from pid=" + Binder.getCallingPid()
8853 + ", uid=" + Binder.getCallingUid()
8854 + " requires " + r.permission);
8855 return new ServiceLookupResult(null, r.permission);
8856 }
8857 return new ServiceLookupResult(r, null);
8858 }
8859 return null;
8860 }
8861
Dianne Hackborn287952c2010-09-22 22:34:31 -07008862 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8863 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8864 + why + " of " + r + " in app " + r.app);
8865 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8866 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008867 long now = SystemClock.uptimeMillis();
8868 if (r.executeNesting == 0 && r.app != null) {
8869 if (r.app.executingServices.size() == 0) {
8870 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8871 msg.obj = r.app;
8872 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8873 }
8874 r.app.executingServices.add(r);
8875 }
8876 r.executeNesting++;
8877 r.executingStart = now;
8878 }
8879
8880 private final void sendServiceArgsLocked(ServiceRecord r,
8881 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008882 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008883 if (N == 0) {
8884 return;
8885 }
8886
Dianne Hackborn39792d22010-08-19 18:01:52 -07008887 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008888 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008889 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008890 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8891 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008892 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008893 // If somehow we got a dummy start at the front, then
8894 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008895 continue;
8896 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008897 si.deliveredTime = SystemClock.uptimeMillis();
8898 r.deliveredStarts.add(si);
8899 si.deliveryCount++;
8900 if (si.targetPermissionUid >= 0) {
8901 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008902 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008903 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008904 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 if (!oomAdjusted) {
8906 oomAdjusted = true;
8907 updateOomAdjLocked(r.app);
8908 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008909 int flags = 0;
8910 if (si.deliveryCount > 0) {
8911 flags |= Service.START_FLAG_RETRY;
8912 }
8913 if (si.doneExecutingCount > 0) {
8914 flags |= Service.START_FLAG_REDELIVERY;
8915 }
8916 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008917 } catch (RemoteException e) {
8918 // Remote process gone... we'll let the normal cleanup take
8919 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008920 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008921 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008922 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008923 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 break;
8925 }
8926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008927 }
8928
8929 private final boolean requestServiceBindingLocked(ServiceRecord r,
8930 IntentBindRecord i, boolean rebind) {
8931 if (r.app == null || r.app.thread == null) {
8932 // If service is not currently running, can't yet bind.
8933 return false;
8934 }
8935 if ((!i.requested || rebind) && i.apps.size() > 0) {
8936 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008937 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8939 if (!rebind) {
8940 i.requested = true;
8941 }
8942 i.hasBound = true;
8943 i.doRebind = false;
8944 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008945 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 return false;
8947 }
8948 }
8949 return true;
8950 }
8951
8952 private final void requestServiceBindingsLocked(ServiceRecord r) {
8953 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8954 while (bindings.hasNext()) {
8955 IntentBindRecord i = bindings.next();
8956 if (!requestServiceBindingLocked(r, i, false)) {
8957 break;
8958 }
8959 }
8960 }
8961
8962 private final void realStartServiceLocked(ServiceRecord r,
8963 ProcessRecord app) throws RemoteException {
8964 if (app.thread == null) {
8965 throw new RemoteException();
8966 }
8967
8968 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008969 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970
8971 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008972 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008973 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008974
8975 boolean created = false;
8976 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008977 mStringBuilder.setLength(0);
8978 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008979 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008980 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008981 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 synchronized (r.stats.getBatteryStats()) {
8983 r.stats.startLaunchedLocked();
8984 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008985 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008987 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008988 created = true;
8989 } finally {
8990 if (!created) {
8991 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008992 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 }
8994 }
8995
8996 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008997
8998 // If the service is in the started state, and there are no
8999 // pending arguments, then fake up one so its onStartCommand() will
9000 // be called.
9001 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9002 r.lastStartId++;
9003 if (r.lastStartId < 1) {
9004 r.lastStartId = 1;
9005 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009006 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009007 }
9008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009009 sendServiceArgsLocked(r, true);
9010 }
9011
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009012 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9013 boolean allowCancel) {
9014 boolean canceled = false;
9015
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009016 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009017 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009018 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009019
9020 // Any delivered but not yet finished starts should be put back
9021 // on the pending list.
9022 final int N = r.deliveredStarts.size();
9023 if (N > 0) {
9024 for (int i=N-1; i>=0; i--) {
9025 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009026 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009027 if (si.intent == null) {
9028 // We'll generate this again if needed.
9029 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9030 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9031 r.pendingStarts.add(0, si);
9032 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9033 dur *= 2;
9034 if (minDuration < dur) minDuration = dur;
9035 if (resetTime < dur) resetTime = dur;
9036 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009037 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009038 + r.name);
9039 canceled = true;
9040 }
9041 }
9042 r.deliveredStarts.clear();
9043 }
9044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 r.totalRestartCount++;
9046 if (r.restartDelay == 0) {
9047 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009048 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 } else {
9050 // If it has been a "reasonably long time" since the service
9051 // was started, then reset our restart duration back to
9052 // the beginning, so we don't infinitely increase the duration
9053 // on a service that just occasionally gets killed (which is
9054 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009055 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009056 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009057 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009059 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009060 if (r.restartDelay < minDuration) {
9061 r.restartDelay = minDuration;
9062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 }
9064 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009065
9066 r.nextRestartTime = now + r.restartDelay;
9067
9068 // Make sure that we don't end up restarting a bunch of services
9069 // all at the same time.
9070 boolean repeat;
9071 do {
9072 repeat = false;
9073 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9074 ServiceRecord r2 = mRestartingServices.get(i);
9075 if (r2 != r && r.nextRestartTime
9076 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9077 && r.nextRestartTime
9078 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9079 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9080 r.restartDelay = r.nextRestartTime - now;
9081 repeat = true;
9082 break;
9083 }
9084 }
9085 } while (repeat);
9086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 if (!mRestartingServices.contains(r)) {
9088 mRestartingServices.add(r);
9089 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009090
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009091 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009094 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009095 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009096 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009098 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 r.shortName, r.restartDelay);
9100
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009101 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 }
9103
9104 final void performServiceRestartLocked(ServiceRecord r) {
9105 if (!mRestartingServices.contains(r)) {
9106 return;
9107 }
9108 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9109 }
9110
9111 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9112 if (r.restartDelay == 0) {
9113 return false;
9114 }
9115 r.resetRestartCounter();
9116 mRestartingServices.remove(r);
9117 mHandler.removeCallbacks(r.restarter);
9118 return true;
9119 }
9120
9121 private final boolean bringUpServiceLocked(ServiceRecord r,
9122 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009123 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 //r.dump(" ");
9125
Dianne Hackborn36124872009-10-08 16:22:03 -07009126 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009127 sendServiceArgsLocked(r, false);
9128 return true;
9129 }
9130
9131 if (!whileRestarting && r.restartDelay > 0) {
9132 // If waiting for a restart, then do nothing.
9133 return true;
9134 }
9135
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009136 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009138 // We are now bringing the service up, so no longer in the
9139 // restarting state.
9140 mRestartingServices.remove(r);
9141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009142 final String appName = r.processName;
9143 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9144 if (app != null && app.thread != null) {
9145 try {
9146 realStartServiceLocked(r, app);
9147 return true;
9148 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009149 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009150 }
9151
9152 // If a dead object exception was thrown -- fall through to
9153 // restart the application.
9154 }
9155
Dianne Hackborn36124872009-10-08 16:22:03 -07009156 // Not running -- get it started, and enqueue this service record
9157 // to be executed when the app comes up.
9158 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9159 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009160 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009161 + r.appInfo.packageName + "/"
9162 + r.appInfo.uid + " for service "
9163 + r.intent.getIntent() + ": process is bad");
9164 bringDownServiceLocked(r, true);
9165 return false;
9166 }
9167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009169 mPendingServices.add(r);
9170 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 return true;
9173 }
9174
9175 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009176 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 //r.dump(" ");
9178
9179 // Does it still need to run?
9180 if (!force && r.startRequested) {
9181 return;
9182 }
9183 if (r.connections.size() > 0) {
9184 if (!force) {
9185 // XXX should probably keep a count of the number of auto-create
9186 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009187 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009189 ArrayList<ConnectionRecord> cr = it.next();
9190 for (int i=0; i<cr.size(); i++) {
9191 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9192 return;
9193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 }
9195 }
9196 }
9197
9198 // Report to all of the connections that the service is no longer
9199 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009200 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009202 ArrayList<ConnectionRecord> c = it.next();
9203 for (int i=0; i<c.size(); i++) {
9204 try {
9205 c.get(i).conn.connected(r.name, null);
9206 } catch (Exception e) {
9207 Slog.w(TAG, "Failure disconnecting service " + r.name +
9208 " to connection " + c.get(i).conn.asBinder() +
9209 " (in " + c.get(i).binding.client.processName + ")", e);
9210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 }
9212 }
9213 }
9214
9215 // Tell the service that it has been unbound.
9216 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9217 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9218 while (it.hasNext()) {
9219 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009220 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 + ": hasBound=" + ibr.hasBound);
9222 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9223 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009224 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 updateOomAdjLocked(r.app);
9226 ibr.hasBound = false;
9227 r.app.thread.scheduleUnbindService(r,
9228 ibr.intent.getIntent());
9229 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009230 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 + r.shortName, e);
9232 serviceDoneExecutingLocked(r, true);
9233 }
9234 }
9235 }
9236 }
9237
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009238 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009239 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 System.identityHashCode(r), r.shortName,
9241 (r.app != null) ? r.app.pid : -1);
9242
9243 mServices.remove(r.name);
9244 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 r.totalRestartCount = 0;
9246 unscheduleServiceRestartLocked(r);
9247
9248 // Also make sure it is not on the pending list.
9249 int N = mPendingServices.size();
9250 for (int i=0; i<N; i++) {
9251 if (mPendingServices.get(i) == r) {
9252 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009253 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009254 i--;
9255 N--;
9256 }
9257 }
9258
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009259 r.cancelNotification();
9260 r.isForeground = false;
9261 r.foregroundId = 0;
9262 r.foregroundNoti = null;
9263
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009264 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009265 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009266 r.pendingStarts.clear();
9267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268 if (r.app != null) {
9269 synchronized (r.stats.getBatteryStats()) {
9270 r.stats.stopLaunchedLocked();
9271 }
9272 r.app.services.remove(r);
9273 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009275 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009276 mStoppingServices.add(r);
9277 updateOomAdjLocked(r.app);
9278 r.app.thread.scheduleStopService(r);
9279 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009280 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 + r.shortName, e);
9282 serviceDoneExecutingLocked(r, true);
9283 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009284 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009286 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009287 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 }
9289 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009290 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009291 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009292 }
9293 }
9294
9295 ComponentName startServiceLocked(IApplicationThread caller,
9296 Intent service, String resolvedType,
9297 int callingPid, int callingUid) {
9298 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009299 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 + " type=" + resolvedType + " args=" + service.getExtras());
9301
9302 if (caller != null) {
9303 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9304 if (callerApp == null) {
9305 throw new SecurityException(
9306 "Unable to find app for caller " + caller
9307 + " (pid=" + Binder.getCallingPid()
9308 + ") when starting service " + service);
9309 }
9310 }
9311
9312 ServiceLookupResult res =
9313 retrieveServiceLocked(service, resolvedType,
9314 callingPid, callingUid);
9315 if (res == null) {
9316 return null;
9317 }
9318 if (res.record == null) {
9319 return new ComponentName("!", res.permission != null
9320 ? res.permission : "private to package");
9321 }
9322 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009323 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9324 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009326 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009327 }
9328 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009329 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 r.lastStartId++;
9331 if (r.lastStartId < 1) {
9332 r.lastStartId = 1;
9333 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009334 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9335 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009336 r.lastActivity = SystemClock.uptimeMillis();
9337 synchronized (r.stats.getBatteryStats()) {
9338 r.stats.startRunningLocked();
9339 }
9340 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9341 return new ComponentName("!", "Service process is bad");
9342 }
9343 return r.name;
9344 }
9345 }
9346
9347 public ComponentName startService(IApplicationThread caller, Intent service,
9348 String resolvedType) {
9349 // Refuse possible leaked file descriptors
9350 if (service != null && service.hasFileDescriptors() == true) {
9351 throw new IllegalArgumentException("File descriptors passed in Intent");
9352 }
9353
9354 synchronized(this) {
9355 final int callingPid = Binder.getCallingPid();
9356 final int callingUid = Binder.getCallingUid();
9357 final long origId = Binder.clearCallingIdentity();
9358 ComponentName res = startServiceLocked(caller, service,
9359 resolvedType, callingPid, callingUid);
9360 Binder.restoreCallingIdentity(origId);
9361 return res;
9362 }
9363 }
9364
9365 ComponentName startServiceInPackage(int uid,
9366 Intent service, String resolvedType) {
9367 synchronized(this) {
9368 final long origId = Binder.clearCallingIdentity();
9369 ComponentName res = startServiceLocked(null, service,
9370 resolvedType, -1, uid);
9371 Binder.restoreCallingIdentity(origId);
9372 return res;
9373 }
9374 }
9375
9376 public int stopService(IApplicationThread caller, Intent service,
9377 String resolvedType) {
9378 // Refuse possible leaked file descriptors
9379 if (service != null && service.hasFileDescriptors() == true) {
9380 throw new IllegalArgumentException("File descriptors passed in Intent");
9381 }
9382
9383 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009384 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 + " type=" + resolvedType);
9386
9387 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9388 if (caller != null && callerApp == null) {
9389 throw new SecurityException(
9390 "Unable to find app for caller " + caller
9391 + " (pid=" + Binder.getCallingPid()
9392 + ") when stopping service " + service);
9393 }
9394
9395 // If this service is active, make sure it is stopped.
9396 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9397 if (r != null) {
9398 if (r.record != null) {
9399 synchronized (r.record.stats.getBatteryStats()) {
9400 r.record.stats.stopRunningLocked();
9401 }
9402 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009403 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404 final long origId = Binder.clearCallingIdentity();
9405 bringDownServiceLocked(r.record, false);
9406 Binder.restoreCallingIdentity(origId);
9407 return 1;
9408 }
9409 return -1;
9410 }
9411 }
9412
9413 return 0;
9414 }
9415
9416 public IBinder peekService(Intent service, String resolvedType) {
9417 // Refuse possible leaked file descriptors
9418 if (service != null && service.hasFileDescriptors() == true) {
9419 throw new IllegalArgumentException("File descriptors passed in Intent");
9420 }
9421
9422 IBinder ret = null;
9423
9424 synchronized(this) {
9425 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9426
9427 if (r != null) {
9428 // r.record is null if findServiceLocked() failed the caller permission check
9429 if (r.record == null) {
9430 throw new SecurityException(
9431 "Permission Denial: Accessing service " + r.record.name
9432 + " from pid=" + Binder.getCallingPid()
9433 + ", uid=" + Binder.getCallingUid()
9434 + " requires " + r.permission);
9435 }
9436 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9437 if (ib != null) {
9438 ret = ib.binder;
9439 }
9440 }
9441 }
9442
9443 return ret;
9444 }
9445
9446 public boolean stopServiceToken(ComponentName className, IBinder token,
9447 int startId) {
9448 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009449 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009450 + " " + token + " startId=" + startId);
9451 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009452 if (r != null) {
9453 if (startId >= 0) {
9454 // Asked to only stop if done with all work. Note that
9455 // to avoid leaks, we will take this as dropping all
9456 // start items up to and including this one.
9457 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9458 if (si != null) {
9459 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009460 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9461 cur.removeUriPermissionsLocked();
9462 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009463 break;
9464 }
9465 }
9466 }
9467
9468 if (r.lastStartId != startId) {
9469 return false;
9470 }
9471
9472 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009473 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009474 + " is last, but have " + r.deliveredStarts.size()
9475 + " remaining args");
9476 }
9477 }
9478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 synchronized (r.stats.getBatteryStats()) {
9480 r.stats.stopRunningLocked();
9481 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009482 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483 }
9484 final long origId = Binder.clearCallingIdentity();
9485 bringDownServiceLocked(r, false);
9486 Binder.restoreCallingIdentity(origId);
9487 return true;
9488 }
9489 }
9490 return false;
9491 }
9492
9493 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009494 int id, Notification notification, boolean removeNotification) {
9495 final long origId = Binder.clearCallingIdentity();
9496 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497 synchronized(this) {
9498 ServiceRecord r = findServiceLocked(className, token);
9499 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009500 if (id != 0) {
9501 if (notification == null) {
9502 throw new IllegalArgumentException("null notification");
9503 }
9504 if (r.foregroundId != id) {
9505 r.cancelNotification();
9506 r.foregroundId = id;
9507 }
9508 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9509 r.foregroundNoti = notification;
9510 r.isForeground = true;
9511 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 if (r.app != null) {
9513 updateServiceForegroundLocked(r.app, true);
9514 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009515 } else {
9516 if (r.isForeground) {
9517 r.isForeground = false;
9518 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009519 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009520 updateServiceForegroundLocked(r.app, true);
9521 }
9522 }
9523 if (removeNotification) {
9524 r.cancelNotification();
9525 r.foregroundId = 0;
9526 r.foregroundNoti = null;
9527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 }
9529 }
9530 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009531 } finally {
9532 Binder.restoreCallingIdentity(origId);
9533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009534 }
9535
9536 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9537 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009538 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 if (sr.isForeground) {
9540 anyForeground = true;
9541 break;
9542 }
9543 }
9544 if (anyForeground != proc.foregroundServices) {
9545 proc.foregroundServices = anyForeground;
9546 if (oomAdj) {
9547 updateOomAdjLocked();
9548 }
9549 }
9550 }
9551
9552 public int bindService(IApplicationThread caller, IBinder token,
9553 Intent service, String resolvedType,
9554 IServiceConnection connection, int flags) {
9555 // Refuse possible leaked file descriptors
9556 if (service != null && service.hasFileDescriptors() == true) {
9557 throw new IllegalArgumentException("File descriptors passed in Intent");
9558 }
9559
9560 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009561 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 + " type=" + resolvedType + " conn=" + connection.asBinder()
9563 + " flags=0x" + Integer.toHexString(flags));
9564 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9565 if (callerApp == null) {
9566 throw new SecurityException(
9567 "Unable to find app for caller " + caller
9568 + " (pid=" + Binder.getCallingPid()
9569 + ") when binding service " + service);
9570 }
9571
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009572 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009574 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009575 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009576 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 return 0;
9578 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009579 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 }
9581
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009582 int clientLabel = 0;
9583 PendingIntent clientIntent = null;
9584
9585 if (callerApp.info.uid == Process.SYSTEM_UID) {
9586 // Hacky kind of thing -- allow system stuff to tell us
9587 // what they are, so we can report this elsewhere for
9588 // others to know why certain services are running.
9589 try {
9590 clientIntent = (PendingIntent)service.getParcelableExtra(
9591 Intent.EXTRA_CLIENT_INTENT);
9592 } catch (RuntimeException e) {
9593 }
9594 if (clientIntent != null) {
9595 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9596 if (clientLabel != 0) {
9597 // There are no useful extras in the intent, trash them.
9598 // System code calling with this stuff just needs to know
9599 // this will happen.
9600 service = service.cloneFilter();
9601 }
9602 }
9603 }
9604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009605 ServiceLookupResult res =
9606 retrieveServiceLocked(service, resolvedType,
9607 Binder.getCallingPid(), Binder.getCallingUid());
9608 if (res == null) {
9609 return 0;
9610 }
9611 if (res.record == null) {
9612 return -1;
9613 }
9614 ServiceRecord s = res.record;
9615
9616 final long origId = Binder.clearCallingIdentity();
9617
9618 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009619 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009620 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 }
9622
9623 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9624 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009625 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626
9627 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009628 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9629 if (clist == null) {
9630 clist = new ArrayList<ConnectionRecord>();
9631 s.connections.put(binder, clist);
9632 }
9633 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 b.connections.add(c);
9635 if (activity != null) {
9636 if (activity.connections == null) {
9637 activity.connections = new HashSet<ConnectionRecord>();
9638 }
9639 activity.connections.add(c);
9640 }
9641 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009642 clist = mServiceConnections.get(binder);
9643 if (clist == null) {
9644 clist = new ArrayList<ConnectionRecord>();
9645 mServiceConnections.put(binder, clist);
9646 }
9647 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009648
9649 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9650 s.lastActivity = SystemClock.uptimeMillis();
9651 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9652 return 0;
9653 }
9654 }
9655
9656 if (s.app != null) {
9657 // This could have made the service more important.
9658 updateOomAdjLocked(s.app);
9659 }
9660
Joe Onorato8a9b2202010-02-26 18:56:32 -08009661 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009662 + ": received=" + b.intent.received
9663 + " apps=" + b.intent.apps.size()
9664 + " doRebind=" + b.intent.doRebind);
9665
9666 if (s.app != null && b.intent.received) {
9667 // Service is already running, so we can immediately
9668 // publish the connection.
9669 try {
9670 c.conn.connected(s.name, b.intent.binder);
9671 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009672 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 + " to connection " + c.conn.asBinder()
9674 + " (in " + c.binding.client.processName + ")", e);
9675 }
9676
9677 // If this is the first app connected back to this binding,
9678 // and the service had previously asked to be told when
9679 // rebound, then do so.
9680 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9681 requestServiceBindingLocked(s, b.intent, true);
9682 }
9683 } else if (!b.intent.requested) {
9684 requestServiceBindingLocked(s, b.intent, false);
9685 }
9686
9687 Binder.restoreCallingIdentity(origId);
9688 }
9689
9690 return 1;
9691 }
9692
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009693 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009694 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 IBinder binder = c.conn.asBinder();
9696 AppBindRecord b = c.binding;
9697 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009698 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9699 if (clist != null) {
9700 clist.remove(c);
9701 if (clist.size() == 0) {
9702 s.connections.remove(binder);
9703 }
9704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 b.connections.remove(c);
9706 if (c.activity != null && c.activity != skipAct) {
9707 if (c.activity.connections != null) {
9708 c.activity.connections.remove(c);
9709 }
9710 }
9711 if (b.client != skipApp) {
9712 b.client.connections.remove(c);
9713 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009714 clist = mServiceConnections.get(binder);
9715 if (clist != null) {
9716 clist.remove(c);
9717 if (clist.size() == 0) {
9718 mServiceConnections.remove(binder);
9719 }
9720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721
9722 if (b.connections.size() == 0) {
9723 b.intent.apps.remove(b.client);
9724 }
9725
Joe Onorato8a9b2202010-02-26 18:56:32 -08009726 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 + ": shouldUnbind=" + b.intent.hasBound);
9728 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9729 && b.intent.hasBound) {
9730 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009731 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009732 updateOomAdjLocked(s.app);
9733 b.intent.hasBound = false;
9734 // Assume the client doesn't want to know about a rebind;
9735 // we will deal with that later if it asks for one.
9736 b.intent.doRebind = false;
9737 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9738 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009739 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 serviceDoneExecutingLocked(s, true);
9741 }
9742 }
9743
9744 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9745 bringDownServiceLocked(s, false);
9746 }
9747 }
9748
9749 public boolean unbindService(IServiceConnection connection) {
9750 synchronized (this) {
9751 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009752 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009753 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9754 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009755 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756 + connection.asBinder());
9757 return false;
9758 }
9759
9760 final long origId = Binder.clearCallingIdentity();
9761
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009762 while (clist.size() > 0) {
9763 ConnectionRecord r = clist.get(0);
9764 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009766 if (r.binding.service.app != null) {
9767 // This could have made the service less important.
9768 updateOomAdjLocked(r.binding.service.app);
9769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009770 }
9771
9772 Binder.restoreCallingIdentity(origId);
9773 }
9774
9775 return true;
9776 }
9777
9778 public void publishService(IBinder token, Intent intent, IBinder service) {
9779 // Refuse possible leaked file descriptors
9780 if (intent != null && intent.hasFileDescriptors() == true) {
9781 throw new IllegalArgumentException("File descriptors passed in Intent");
9782 }
9783
9784 synchronized(this) {
9785 if (!(token instanceof ServiceRecord)) {
9786 throw new IllegalArgumentException("Invalid service token");
9787 }
9788 ServiceRecord r = (ServiceRecord)token;
9789
9790 final long origId = Binder.clearCallingIdentity();
9791
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009792 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 + " " + intent + ": " + service);
9794 if (r != null) {
9795 Intent.FilterComparison filter
9796 = new Intent.FilterComparison(intent);
9797 IntentBindRecord b = r.bindings.get(filter);
9798 if (b != null && !b.received) {
9799 b.binder = service;
9800 b.requested = true;
9801 b.received = true;
9802 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009803 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009804 = r.connections.values().iterator();
9805 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009806 ArrayList<ConnectionRecord> clist = it.next();
9807 for (int i=0; i<clist.size(); i++) {
9808 ConnectionRecord c = clist.get(i);
9809 if (!filter.equals(c.binding.intent.intent)) {
9810 if (DEBUG_SERVICE) Slog.v(
9811 TAG, "Not publishing to: " + c);
9812 if (DEBUG_SERVICE) Slog.v(
9813 TAG, "Bound intent: " + c.binding.intent.intent);
9814 if (DEBUG_SERVICE) Slog.v(
9815 TAG, "Published intent: " + intent);
9816 continue;
9817 }
9818 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9819 try {
9820 c.conn.connected(r.name, service);
9821 } catch (Exception e) {
9822 Slog.w(TAG, "Failure sending service " + r.name +
9823 " to connection " + c.conn.asBinder() +
9824 " (in " + c.binding.client.processName + ")", e);
9825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 }
9827 }
9828 }
9829 }
9830
9831 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9832
9833 Binder.restoreCallingIdentity(origId);
9834 }
9835 }
9836 }
9837
9838 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9839 // Refuse possible leaked file descriptors
9840 if (intent != null && intent.hasFileDescriptors() == true) {
9841 throw new IllegalArgumentException("File descriptors passed in Intent");
9842 }
9843
9844 synchronized(this) {
9845 if (!(token instanceof ServiceRecord)) {
9846 throw new IllegalArgumentException("Invalid service token");
9847 }
9848 ServiceRecord r = (ServiceRecord)token;
9849
9850 final long origId = Binder.clearCallingIdentity();
9851
9852 if (r != null) {
9853 Intent.FilterComparison filter
9854 = new Intent.FilterComparison(intent);
9855 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009856 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 + " at " + b + ": apps="
9858 + (b != null ? b.apps.size() : 0));
9859 if (b != null) {
9860 if (b.apps.size() > 0) {
9861 // Applications have already bound since the last
9862 // unbind, so just rebind right here.
9863 requestServiceBindingLocked(r, b, true);
9864 } else {
9865 // Note to tell the service the next time there is
9866 // a new client.
9867 b.doRebind = true;
9868 }
9869 }
9870
9871 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9872
9873 Binder.restoreCallingIdentity(origId);
9874 }
9875 }
9876 }
9877
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009878 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879 synchronized(this) {
9880 if (!(token instanceof ServiceRecord)) {
9881 throw new IllegalArgumentException("Invalid service token");
9882 }
9883 ServiceRecord r = (ServiceRecord)token;
9884 boolean inStopping = mStoppingServices.contains(token);
9885 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009887 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888 + " with incorrect token: given " + token
9889 + ", expected " + r);
9890 return;
9891 }
9892
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009893 if (type == 1) {
9894 // This is a call from a service start... take care of
9895 // book-keeping.
9896 r.callStart = true;
9897 switch (res) {
9898 case Service.START_STICKY_COMPATIBILITY:
9899 case Service.START_STICKY: {
9900 // We are done with the associated start arguments.
9901 r.findDeliveredStart(startId, true);
9902 // Don't stop if killed.
9903 r.stopIfKilled = false;
9904 break;
9905 }
9906 case Service.START_NOT_STICKY: {
9907 // We are done with the associated start arguments.
9908 r.findDeliveredStart(startId, true);
9909 if (r.lastStartId == startId) {
9910 // There is no more work, and this service
9911 // doesn't want to hang around if killed.
9912 r.stopIfKilled = true;
9913 }
9914 break;
9915 }
9916 case Service.START_REDELIVER_INTENT: {
9917 // We'll keep this item until they explicitly
9918 // call stop for it, but keep track of the fact
9919 // that it was delivered.
9920 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9921 if (si != null) {
9922 si.deliveryCount = 0;
9923 si.doneExecutingCount++;
9924 // Don't stop if killed.
9925 r.stopIfKilled = true;
9926 }
9927 break;
9928 }
9929 default:
9930 throw new IllegalArgumentException(
9931 "Unknown service start result: " + res);
9932 }
9933 if (res == Service.START_STICKY_COMPATIBILITY) {
9934 r.callStart = false;
9935 }
9936 }
9937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938 final long origId = Binder.clearCallingIdentity();
9939 serviceDoneExecutingLocked(r, inStopping);
9940 Binder.restoreCallingIdentity(origId);
9941 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009942 Slog.w(TAG, "Done executing unknown service from pid "
9943 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009944 }
9945 }
9946 }
9947
9948 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009949 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9950 + ": nesting=" + r.executeNesting
9951 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009952 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 r.executeNesting--;
9954 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009955 if (DEBUG_SERVICE) Slog.v(TAG,
9956 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 r.app.executingServices.remove(r);
9958 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009959 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9960 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9962 }
9963 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009964 if (DEBUG_SERVICE) Slog.v(TAG,
9965 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 mStoppingServices.remove(r);
9967 }
9968 updateOomAdjLocked(r.app);
9969 }
9970 }
9971
9972 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009973 String anrMessage = null;
9974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 synchronized(this) {
9976 if (proc.executingServices.size() == 0 || proc.thread == null) {
9977 return;
9978 }
9979 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9980 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9981 ServiceRecord timeout = null;
9982 long nextTime = 0;
9983 while (it.hasNext()) {
9984 ServiceRecord sr = it.next();
9985 if (sr.executingStart < maxTime) {
9986 timeout = sr;
9987 break;
9988 }
9989 if (sr.executingStart > nextTime) {
9990 nextTime = sr.executingStart;
9991 }
9992 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009993 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009994 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009995 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 } else {
9997 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9998 msg.obj = proc;
9999 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10000 }
10001 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010002
10003 if (anrMessage != null) {
10004 appNotResponding(proc, null, null, anrMessage);
10005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 }
10007
10008 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010009 // BACKUP AND RESTORE
10010 // =========================================================
10011
10012 // Cause the target app to be launched if necessary and its backup agent
10013 // instantiated. The backup agent will invoke backupAgentCreated() on the
10014 // activity manager to announce its creation.
10015 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010016 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010017 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10018
10019 synchronized(this) {
10020 // !!! TODO: currently no check here that we're already bound
10021 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10022 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10023 synchronized (stats) {
10024 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10025 }
10026
10027 BackupRecord r = new BackupRecord(ss, app, backupMode);
10028 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10029 // startProcessLocked() returns existing proc's record if it's already running
10030 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010031 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010032 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010033 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010034 return false;
10035 }
10036
10037 r.app = proc;
10038 mBackupTarget = r;
10039 mBackupAppName = app.packageName;
10040
Christopher Tate6fa95972009-06-05 18:43:55 -070010041 // Try not to kill the process during backup
10042 updateOomAdjLocked(proc);
10043
Christopher Tate181fafa2009-05-14 11:12:14 -070010044 // If the process is already attached, schedule the creation of the backup agent now.
10045 // If it is not yet live, this will be done when it attaches to the framework.
10046 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010047 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010048 try {
10049 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10050 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010051 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010052 }
10053 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010054 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010055 }
10056 // Invariants: at this point, the target app process exists and the application
10057 // is either already running or in the process of coming up. mBackupTarget and
10058 // mBackupAppName describe the app, so that when it binds back to the AM we
10059 // know that it's scheduled for a backup-agent operation.
10060 }
10061
10062 return true;
10063 }
10064
10065 // A backup agent has just come up
10066 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010067 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010068 + " = " + agent);
10069
10070 synchronized(this) {
10071 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010072 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010073 return;
10074 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010075 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010076
Dianne Hackborn06740692010-09-22 22:46:21 -070010077 long oldIdent = Binder.clearCallingIdentity();
10078 try {
10079 IBackupManager bm = IBackupManager.Stub.asInterface(
10080 ServiceManager.getService(Context.BACKUP_SERVICE));
10081 bm.agentConnected(agentPackageName, agent);
10082 } catch (RemoteException e) {
10083 // can't happen; the backup manager service is local
10084 } catch (Exception e) {
10085 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10086 e.printStackTrace();
10087 } finally {
10088 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010089 }
10090 }
10091
10092 // done with this agent
10093 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010094 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010095 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010096 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010097 return;
10098 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010099
10100 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010101 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010102 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010103 return;
10104 }
10105
Christopher Tate181fafa2009-05-14 11:12:14 -070010106 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010107 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010108 return;
10109 }
10110
Christopher Tate6fa95972009-06-05 18:43:55 -070010111 ProcessRecord proc = mBackupTarget.app;
10112 mBackupTarget = null;
10113 mBackupAppName = null;
10114
10115 // Not backing this app up any more; reset its OOM adjustment
10116 updateOomAdjLocked(proc);
10117
Christopher Tatec7b31e32009-06-10 15:49:30 -070010118 // If the app crashed during backup, 'thread' will be null here
10119 if (proc.thread != null) {
10120 try {
10121 proc.thread.scheduleDestroyBackupAgent(appInfo);
10122 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010123 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010124 e.printStackTrace();
10125 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010126 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010127 }
10128 }
10129 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 // BROADCASTS
10131 // =========================================================
10132
Josh Bartel7f208742010-02-25 11:01:44 -060010133 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010134 List cur) {
10135 final ContentResolver resolver = mContext.getContentResolver();
10136 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10137 if (list == null) {
10138 return cur;
10139 }
10140 int N = list.size();
10141 for (int i=0; i<N; i++) {
10142 Intent intent = list.get(i);
10143 if (filter.match(resolver, intent, true, TAG) >= 0) {
10144 if (cur == null) {
10145 cur = new ArrayList<Intent>();
10146 }
10147 cur.add(intent);
10148 }
10149 }
10150 return cur;
10151 }
10152
10153 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010154 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 + mBroadcastsScheduled);
10156
10157 if (mBroadcastsScheduled) {
10158 return;
10159 }
10160 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10161 mBroadcastsScheduled = true;
10162 }
10163
10164 public Intent registerReceiver(IApplicationThread caller,
10165 IIntentReceiver receiver, IntentFilter filter, String permission) {
10166 synchronized(this) {
10167 ProcessRecord callerApp = null;
10168 if (caller != null) {
10169 callerApp = getRecordForAppLocked(caller);
10170 if (callerApp == null) {
10171 throw new SecurityException(
10172 "Unable to find app for caller " + caller
10173 + " (pid=" + Binder.getCallingPid()
10174 + ") when registering receiver " + receiver);
10175 }
10176 }
10177
10178 List allSticky = null;
10179
10180 // Look for any matching sticky broadcasts...
10181 Iterator actions = filter.actionsIterator();
10182 if (actions != null) {
10183 while (actions.hasNext()) {
10184 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010185 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186 }
10187 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010188 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 }
10190
10191 // The first sticky in the list is returned directly back to
10192 // the client.
10193 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10194
Joe Onorato8a9b2202010-02-26 18:56:32 -080010195 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 + ": " + sticky);
10197
10198 if (receiver == null) {
10199 return sticky;
10200 }
10201
10202 ReceiverList rl
10203 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10204 if (rl == null) {
10205 rl = new ReceiverList(this, callerApp,
10206 Binder.getCallingPid(),
10207 Binder.getCallingUid(), receiver);
10208 if (rl.app != null) {
10209 rl.app.receivers.add(rl);
10210 } else {
10211 try {
10212 receiver.asBinder().linkToDeath(rl, 0);
10213 } catch (RemoteException e) {
10214 return sticky;
10215 }
10216 rl.linkedToDeath = true;
10217 }
10218 mRegisteredReceivers.put(receiver.asBinder(), rl);
10219 }
10220 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10221 rl.add(bf);
10222 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010223 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010224 }
10225 mReceiverResolver.addFilter(bf);
10226
10227 // Enqueue broadcasts for all existing stickies that match
10228 // this filter.
10229 if (allSticky != null) {
10230 ArrayList receivers = new ArrayList();
10231 receivers.add(bf);
10232
10233 int N = allSticky.size();
10234 for (int i=0; i<N; i++) {
10235 Intent intent = (Intent)allSticky.get(i);
10236 BroadcastRecord r = new BroadcastRecord(intent, null,
10237 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010238 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010239 if (mParallelBroadcasts.size() == 0) {
10240 scheduleBroadcastsLocked();
10241 }
10242 mParallelBroadcasts.add(r);
10243 }
10244 }
10245
10246 return sticky;
10247 }
10248 }
10249
10250 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010251 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010252
10253 boolean doNext = false;
10254
10255 synchronized(this) {
10256 ReceiverList rl
10257 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10258 if (rl != null) {
10259 if (rl.curBroadcast != null) {
10260 BroadcastRecord r = rl.curBroadcast;
10261 doNext = finishReceiverLocked(
10262 receiver.asBinder(), r.resultCode, r.resultData,
10263 r.resultExtras, r.resultAbort, true);
10264 }
10265
10266 if (rl.app != null) {
10267 rl.app.receivers.remove(rl);
10268 }
10269 removeReceiverLocked(rl);
10270 if (rl.linkedToDeath) {
10271 rl.linkedToDeath = false;
10272 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10273 }
10274 }
10275 }
10276
10277 if (!doNext) {
10278 return;
10279 }
10280
10281 final long origId = Binder.clearCallingIdentity();
10282 processNextBroadcast(false);
10283 trimApplications();
10284 Binder.restoreCallingIdentity(origId);
10285 }
10286
10287 void removeReceiverLocked(ReceiverList rl) {
10288 mRegisteredReceivers.remove(rl.receiver.asBinder());
10289 int N = rl.size();
10290 for (int i=0; i<N; i++) {
10291 mReceiverResolver.removeFilter(rl.get(i));
10292 }
10293 }
10294
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010295 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10296 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10297 ProcessRecord r = mLruProcesses.get(i);
10298 if (r.thread != null) {
10299 try {
10300 r.thread.dispatchPackageBroadcast(cmd, packages);
10301 } catch (RemoteException ex) {
10302 }
10303 }
10304 }
10305 }
10306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 private final int broadcastIntentLocked(ProcessRecord callerApp,
10308 String callerPackage, Intent intent, String resolvedType,
10309 IIntentReceiver resultTo, int resultCode, String resultData,
10310 Bundle map, String requiredPermission,
10311 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10312 intent = new Intent(intent);
10313
Joe Onorato8a9b2202010-02-26 18:56:32 -080010314 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10316 + " ordered=" + ordered);
10317 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010318 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 }
10320
10321 // Handle special intents: if this broadcast is from the package
10322 // manager about a package being removed, we need to remove all of
10323 // its activities from the history stack.
10324 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10325 intent.getAction());
10326 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10327 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010328 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 || uidRemoved) {
10330 if (checkComponentPermission(
10331 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10332 callingPid, callingUid, -1)
10333 == PackageManager.PERMISSION_GRANTED) {
10334 if (uidRemoved) {
10335 final Bundle intentExtras = intent.getExtras();
10336 final int uid = intentExtras != null
10337 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10338 if (uid >= 0) {
10339 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10340 synchronized (bs) {
10341 bs.removeUidStatsLocked(uid);
10342 }
10343 }
10344 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010345 // If resources are unvailble just force stop all
10346 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010347 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010348 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10349 if (list != null && (list.length > 0)) {
10350 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010351 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010352 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010353 sendPackageBroadcastLocked(
10354 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010355 }
10356 } else {
10357 Uri data = intent.getData();
10358 String ssp;
10359 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10360 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10361 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010362 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010363 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010364 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10365 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10366 new String[] {ssp});
10367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 }
10369 }
10370 }
10371 } else {
10372 String msg = "Permission Denial: " + intent.getAction()
10373 + " broadcast from " + callerPackage + " (pid=" + callingPid
10374 + ", uid=" + callingUid + ")"
10375 + " requires "
10376 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010377 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 throw new SecurityException(msg);
10379 }
10380 }
10381
10382 /*
10383 * If this is the time zone changed action, queue up a message that will reset the timezone
10384 * of all currently running processes. This message will get queued up before the broadcast
10385 * happens.
10386 */
10387 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10388 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10389 }
10390
Robert Greenwalt03595d02010-11-02 14:08:23 -070010391 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10392 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10393 }
10394
Dianne Hackborn854060af2009-07-09 18:14:31 -070010395 /*
10396 * Prevent non-system code (defined here to be non-persistent
10397 * processes) from sending protected broadcasts.
10398 */
10399 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10400 || callingUid == Process.SHELL_UID || callingUid == 0) {
10401 // Always okay.
10402 } else if (callerApp == null || !callerApp.persistent) {
10403 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010404 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010405 intent.getAction())) {
10406 String msg = "Permission Denial: not allowed to send broadcast "
10407 + intent.getAction() + " from pid="
10408 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010409 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010410 throw new SecurityException(msg);
10411 }
10412 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010413 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010414 return BROADCAST_SUCCESS;
10415 }
10416 }
10417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418 // Add to the sticky list if requested.
10419 if (sticky) {
10420 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10421 callingPid, callingUid)
10422 != PackageManager.PERMISSION_GRANTED) {
10423 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10424 + callingPid + ", uid=" + callingUid
10425 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010426 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 throw new SecurityException(msg);
10428 }
10429 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010430 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010431 + " and enforce permission " + requiredPermission);
10432 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10433 }
10434 if (intent.getComponent() != null) {
10435 throw new SecurityException(
10436 "Sticky broadcasts can't target a specific component");
10437 }
10438 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10439 if (list == null) {
10440 list = new ArrayList<Intent>();
10441 mStickyBroadcasts.put(intent.getAction(), list);
10442 }
10443 int N = list.size();
10444 int i;
10445 for (i=0; i<N; i++) {
10446 if (intent.filterEquals(list.get(i))) {
10447 // This sticky already exists, replace it.
10448 list.set(i, new Intent(intent));
10449 break;
10450 }
10451 }
10452 if (i >= N) {
10453 list.add(new Intent(intent));
10454 }
10455 }
10456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 // Figure out who all will receive this broadcast.
10458 List receivers = null;
10459 List<BroadcastFilter> registeredReceivers = null;
10460 try {
10461 if (intent.getComponent() != null) {
10462 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010463 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010464 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010465 if (ai != null) {
10466 receivers = new ArrayList();
10467 ResolveInfo ri = new ResolveInfo();
10468 ri.activityInfo = ai;
10469 receivers.add(ri);
10470 }
10471 } else {
10472 // Need to resolve the intent to interested receivers...
10473 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10474 == 0) {
10475 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010476 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010477 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 }
Mihai Preda074edef2009-05-18 17:13:31 +020010479 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010480 }
10481 } catch (RemoteException ex) {
10482 // pm is in same process, this will never happen.
10483 }
10484
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010485 final boolean replacePending =
10486 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10487
Joe Onorato8a9b2202010-02-26 18:56:32 -080010488 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010489 + " replacePending=" + replacePending);
10490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010491 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10492 if (!ordered && NR > 0) {
10493 // If we are not serializing this broadcast, then send the
10494 // registered receivers separately so they don't wait for the
10495 // components to be launched.
10496 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10497 callerPackage, callingPid, callingUid, requiredPermission,
10498 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010499 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010500 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 TAG, "Enqueueing parallel broadcast " + r
10502 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010503 boolean replaced = false;
10504 if (replacePending) {
10505 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10506 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010507 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010508 "***** DROPPING PARALLEL: " + intent);
10509 mParallelBroadcasts.set(i, r);
10510 replaced = true;
10511 break;
10512 }
10513 }
10514 }
10515 if (!replaced) {
10516 mParallelBroadcasts.add(r);
10517 scheduleBroadcastsLocked();
10518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010519 registeredReceivers = null;
10520 NR = 0;
10521 }
10522
10523 // Merge into one list.
10524 int ir = 0;
10525 if (receivers != null) {
10526 // A special case for PACKAGE_ADDED: do not allow the package
10527 // being added to see this broadcast. This prevents them from
10528 // using this as a back door to get run as soon as they are
10529 // installed. Maybe in the future we want to have a special install
10530 // broadcast or such for apps, but we'd like to deliberately make
10531 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010532 String skipPackages[] = null;
10533 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10534 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10535 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10536 Uri data = intent.getData();
10537 if (data != null) {
10538 String pkgName = data.getSchemeSpecificPart();
10539 if (pkgName != null) {
10540 skipPackages = new String[] { pkgName };
10541 }
10542 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010543 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010544 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010545 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010546 if (skipPackages != null && (skipPackages.length > 0)) {
10547 for (String skipPackage : skipPackages) {
10548 if (skipPackage != null) {
10549 int NT = receivers.size();
10550 for (int it=0; it<NT; it++) {
10551 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10552 if (curt.activityInfo.packageName.equals(skipPackage)) {
10553 receivers.remove(it);
10554 it--;
10555 NT--;
10556 }
10557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010558 }
10559 }
10560 }
10561
10562 int NT = receivers != null ? receivers.size() : 0;
10563 int it = 0;
10564 ResolveInfo curt = null;
10565 BroadcastFilter curr = null;
10566 while (it < NT && ir < NR) {
10567 if (curt == null) {
10568 curt = (ResolveInfo)receivers.get(it);
10569 }
10570 if (curr == null) {
10571 curr = registeredReceivers.get(ir);
10572 }
10573 if (curr.getPriority() >= curt.priority) {
10574 // Insert this broadcast record into the final list.
10575 receivers.add(it, curr);
10576 ir++;
10577 curr = null;
10578 it++;
10579 NT++;
10580 } else {
10581 // Skip to the next ResolveInfo in the final list.
10582 it++;
10583 curt = null;
10584 }
10585 }
10586 }
10587 while (ir < NR) {
10588 if (receivers == null) {
10589 receivers = new ArrayList();
10590 }
10591 receivers.add(registeredReceivers.get(ir));
10592 ir++;
10593 }
10594
10595 if ((receivers != null && receivers.size() > 0)
10596 || resultTo != null) {
10597 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10598 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010599 receivers, resultTo, resultCode, resultData, map, ordered,
10600 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 TAG, "Enqueueing ordered broadcast " + r
10603 + ": prev had " + mOrderedBroadcasts.size());
10604 if (DEBUG_BROADCAST) {
10605 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010606 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010608 boolean replaced = false;
10609 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010610 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010611 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010612 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010613 "***** DROPPING ORDERED: " + intent);
10614 mOrderedBroadcasts.set(i, r);
10615 replaced = true;
10616 break;
10617 }
10618 }
10619 }
10620 if (!replaced) {
10621 mOrderedBroadcasts.add(r);
10622 scheduleBroadcastsLocked();
10623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010624 }
10625
10626 return BROADCAST_SUCCESS;
10627 }
10628
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010629 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010630 // Refuse possible leaked file descriptors
10631 if (intent != null && intent.hasFileDescriptors() == true) {
10632 throw new IllegalArgumentException("File descriptors passed in Intent");
10633 }
10634
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010635 int flags = intent.getFlags();
10636
10637 if (!mProcessesReady) {
10638 // if the caller really truly claims to know what they're doing, go
10639 // ahead and allow the broadcast without launching any receivers
10640 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10641 intent = new Intent(intent);
10642 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10643 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10644 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10645 + " before boot completion");
10646 throw new IllegalStateException("Cannot broadcast before boot completed");
10647 }
10648 }
10649
10650 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10651 throw new IllegalArgumentException(
10652 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10653 }
10654
10655 return intent;
10656 }
10657
10658 public final int broadcastIntent(IApplicationThread caller,
10659 Intent intent, String resolvedType, IIntentReceiver resultTo,
10660 int resultCode, String resultData, Bundle map,
10661 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010662 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010663 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010665 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10666 final int callingPid = Binder.getCallingPid();
10667 final int callingUid = Binder.getCallingUid();
10668 final long origId = Binder.clearCallingIdentity();
10669 int res = broadcastIntentLocked(callerApp,
10670 callerApp != null ? callerApp.info.packageName : null,
10671 intent, resolvedType, resultTo,
10672 resultCode, resultData, map, requiredPermission, serialized,
10673 sticky, callingPid, callingUid);
10674 Binder.restoreCallingIdentity(origId);
10675 return res;
10676 }
10677 }
10678
10679 int broadcastIntentInPackage(String packageName, int uid,
10680 Intent intent, String resolvedType, IIntentReceiver resultTo,
10681 int resultCode, String resultData, Bundle map,
10682 String requiredPermission, boolean serialized, boolean sticky) {
10683 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010684 intent = verifyBroadcastLocked(intent);
10685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010686 final long origId = Binder.clearCallingIdentity();
10687 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10688 resultTo, resultCode, resultData, map, requiredPermission,
10689 serialized, sticky, -1, uid);
10690 Binder.restoreCallingIdentity(origId);
10691 return res;
10692 }
10693 }
10694
10695 public final void unbroadcastIntent(IApplicationThread caller,
10696 Intent intent) {
10697 // Refuse possible leaked file descriptors
10698 if (intent != null && intent.hasFileDescriptors() == true) {
10699 throw new IllegalArgumentException("File descriptors passed in Intent");
10700 }
10701
10702 synchronized(this) {
10703 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10704 != PackageManager.PERMISSION_GRANTED) {
10705 String msg = "Permission Denial: unbroadcastIntent() from pid="
10706 + Binder.getCallingPid()
10707 + ", uid=" + Binder.getCallingUid()
10708 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010709 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 throw new SecurityException(msg);
10711 }
10712 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10713 if (list != null) {
10714 int N = list.size();
10715 int i;
10716 for (i=0; i<N; i++) {
10717 if (intent.filterEquals(list.get(i))) {
10718 list.remove(i);
10719 break;
10720 }
10721 }
10722 }
10723 }
10724 }
10725
10726 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10727 String resultData, Bundle resultExtras, boolean resultAbort,
10728 boolean explicit) {
10729 if (mOrderedBroadcasts.size() == 0) {
10730 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010731 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 }
10733 return false;
10734 }
10735 BroadcastRecord r = mOrderedBroadcasts.get(0);
10736 if (r.receiver == null) {
10737 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010738 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 }
10740 return false;
10741 }
10742 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010743 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010744 return false;
10745 }
10746 int state = r.state;
10747 r.state = r.IDLE;
10748 if (state == r.IDLE) {
10749 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010750 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751 }
10752 }
10753 r.receiver = null;
10754 r.intent.setComponent(null);
10755 if (r.curApp != null) {
10756 r.curApp.curReceiver = null;
10757 }
10758 if (r.curFilter != null) {
10759 r.curFilter.receiverList.curBroadcast = null;
10760 }
10761 r.curFilter = null;
10762 r.curApp = null;
10763 r.curComponent = null;
10764 r.curReceiver = null;
10765 mPendingBroadcast = null;
10766
10767 r.resultCode = resultCode;
10768 r.resultData = resultData;
10769 r.resultExtras = resultExtras;
10770 r.resultAbort = resultAbort;
10771
10772 // We will process the next receiver right now if this is finishing
10773 // an app receiver (which is always asynchronous) or after we have
10774 // come back from calling a receiver.
10775 return state == BroadcastRecord.APP_RECEIVE
10776 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10777 }
10778
10779 public void finishReceiver(IBinder who, int resultCode, String resultData,
10780 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010781 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782
10783 // Refuse possible leaked file descriptors
10784 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10785 throw new IllegalArgumentException("File descriptors passed in Bundle");
10786 }
10787
10788 boolean doNext;
10789
10790 final long origId = Binder.clearCallingIdentity();
10791
10792 synchronized(this) {
10793 doNext = finishReceiverLocked(
10794 who, resultCode, resultData, resultExtras, resultAbort, true);
10795 }
10796
10797 if (doNext) {
10798 processNextBroadcast(false);
10799 }
10800 trimApplications();
10801
10802 Binder.restoreCallingIdentity(origId);
10803 }
10804
Jeff Brown4d94a762010-09-23 11:33:28 -070010805 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 if (r.nextReceiver > 0) {
10807 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10808 if (curReceiver instanceof BroadcastFilter) {
10809 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010810 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010811 System.identityHashCode(r),
10812 r.intent.getAction(),
10813 r.nextReceiver - 1,
10814 System.identityHashCode(bf));
10815 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010816 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 System.identityHashCode(r),
10818 r.intent.getAction(),
10819 r.nextReceiver - 1,
10820 ((ResolveInfo)curReceiver).toString());
10821 }
10822 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010823 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010825 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010826 System.identityHashCode(r),
10827 r.intent.getAction(),
10828 r.nextReceiver,
10829 "NONE");
10830 }
10831 }
10832
Jeff Brown4d94a762010-09-23 11:33:28 -070010833 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10834 if (! mPendingBroadcastTimeoutMessage) {
10835 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10836 mHandler.sendMessageAtTime(msg, timeoutTime);
10837 mPendingBroadcastTimeoutMessage = true;
10838 }
10839 }
10840
10841 private final void cancelBroadcastTimeoutLocked() {
10842 if (mPendingBroadcastTimeoutMessage) {
10843 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10844 mPendingBroadcastTimeoutMessage = false;
10845 }
10846 }
10847
10848 private final void broadcastTimeoutLocked(boolean fromMsg) {
10849 if (fromMsg) {
10850 mPendingBroadcastTimeoutMessage = false;
10851 }
10852
10853 if (mOrderedBroadcasts.size() == 0) {
10854 return;
10855 }
10856
10857 long now = SystemClock.uptimeMillis();
10858 BroadcastRecord r = mOrderedBroadcasts.get(0);
10859 if (fromMsg) {
10860 if (mDidDexOpt) {
10861 // Delay timeouts until dexopt finishes.
10862 mDidDexOpt = false;
10863 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10864 setBroadcastTimeoutLocked(timeoutTime);
10865 return;
10866 }
10867 if (! mProcessesReady) {
10868 // Only process broadcast timeouts if the system is ready. That way
10869 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10870 // to do heavy lifting for system up.
10871 return;
10872 }
10873
10874 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10875 if (timeoutTime > now) {
10876 // We can observe premature timeouts because we do not cancel and reset the
10877 // broadcast timeout message after each receiver finishes. Instead, we set up
10878 // an initial timeout then kick it down the road a little further as needed
10879 // when it expires.
10880 if (DEBUG_BROADCAST) Slog.v(TAG,
10881 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10882 + timeoutTime);
10883 setBroadcastTimeoutLocked(timeoutTime);
10884 return;
10885 }
10886 }
10887
10888 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10889 + ", started " + (now - r.receiverTime) + "ms ago");
10890 r.receiverTime = now;
10891 r.anrCount++;
10892
10893 // Current receiver has passed its expiration date.
10894 if (r.nextReceiver <= 0) {
10895 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10896 return;
10897 }
10898
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010899 ProcessRecord app = null;
10900 String anrMessage = null;
10901
Jeff Brown4d94a762010-09-23 11:33:28 -070010902 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10903 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10904 logBroadcastReceiverDiscardLocked(r);
10905 if (curReceiver instanceof BroadcastFilter) {
10906 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10907 if (bf.receiverList.pid != 0
10908 && bf.receiverList.pid != MY_PID) {
10909 synchronized (this.mPidsSelfLocked) {
10910 app = this.mPidsSelfLocked.get(
10911 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010914 } else {
10915 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010917
Jeff Brown4d94a762010-09-23 11:33:28 -070010918 if (app != null) {
10919 anrMessage = "Broadcast of " + r.intent.toString();
10920 }
10921
10922 if (mPendingBroadcast == r) {
10923 mPendingBroadcast = null;
10924 }
10925
10926 // Move on to the next receiver.
10927 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10928 r.resultExtras, r.resultAbort, true);
10929 scheduleBroadcastsLocked();
10930
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010931 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010932 // Post the ANR to the handler since we do not want to process ANRs while
10933 // potentially holding our lock.
10934 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 }
10937
10938 private final void processCurBroadcastLocked(BroadcastRecord r,
10939 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010940 if (DEBUG_BROADCAST) Slog.v(TAG,
10941 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 if (app.thread == null) {
10943 throw new RemoteException();
10944 }
10945 r.receiver = app.thread.asBinder();
10946 r.curApp = app;
10947 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010948 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949
10950 // Tell the application to launch this receiver.
10951 r.intent.setComponent(r.curComponent);
10952
10953 boolean started = false;
10954 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010955 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 "Delivering to component " + r.curComponent
10957 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010958 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10960 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010961 if (DEBUG_BROADCAST) Slog.v(TAG,
10962 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 started = true;
10964 } finally {
10965 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010966 if (DEBUG_BROADCAST) Slog.v(TAG,
10967 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 r.receiver = null;
10969 r.curApp = null;
10970 app.curReceiver = null;
10971 }
10972 }
10973
10974 }
10975
Jeff Brown4d94a762010-09-23 11:33:28 -070010976 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010977 Intent intent, int resultCode, String data, Bundle extras,
10978 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010979 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 if (app != null && app.thread != null) {
10981 // If we have an app thread, do the call through that so it is
10982 // correctly ordered with other one-way calls.
10983 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010984 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010986 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 }
10988 }
10989
Jeff Brown4d94a762010-09-23 11:33:28 -070010990 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010991 BroadcastFilter filter, boolean ordered) {
10992 boolean skip = false;
10993 if (filter.requiredPermission != null) {
10994 int perm = checkComponentPermission(filter.requiredPermission,
10995 r.callingPid, r.callingUid, -1);
10996 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010997 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 + r.intent.toString()
10999 + " from " + r.callerPackage + " (pid="
11000 + r.callingPid + ", uid=" + r.callingUid + ")"
11001 + " requires " + filter.requiredPermission
11002 + " due to registered receiver " + filter);
11003 skip = true;
11004 }
11005 }
11006 if (r.requiredPermission != null) {
11007 int perm = checkComponentPermission(r.requiredPermission,
11008 filter.receiverList.pid, filter.receiverList.uid, -1);
11009 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011010 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 + r.intent.toString()
11012 + " to " + filter.receiverList.app
11013 + " (pid=" + filter.receiverList.pid
11014 + ", uid=" + filter.receiverList.uid + ")"
11015 + " requires " + r.requiredPermission
11016 + " due to sender " + r.callerPackage
11017 + " (uid " + r.callingUid + ")");
11018 skip = true;
11019 }
11020 }
11021
11022 if (!skip) {
11023 // If this is not being sent as an ordered broadcast, then we
11024 // don't want to touch the fields that keep track of the current
11025 // state of ordered broadcasts.
11026 if (ordered) {
11027 r.receiver = filter.receiverList.receiver.asBinder();
11028 r.curFilter = filter;
11029 filter.receiverList.curBroadcast = r;
11030 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011031 if (filter.receiverList.app != null) {
11032 // Bump hosting application to no longer be in background
11033 // scheduling class. Note that we can't do that if there
11034 // isn't an app... but we can only be in that case for
11035 // things that directly call the IActivityManager API, which
11036 // are already core system stuff so don't matter for this.
11037 r.curApp = filter.receiverList.app;
11038 filter.receiverList.app.curReceiver = r;
11039 updateOomAdjLocked();
11040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 }
11042 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011043 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011045 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011046 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011048 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011050 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 if (ordered) {
11052 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11053 }
11054 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011055 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 if (ordered) {
11057 r.receiver = null;
11058 r.curFilter = null;
11059 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011060 if (filter.receiverList.app != null) {
11061 filter.receiverList.app.curReceiver = null;
11062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 }
11064 }
11065 }
11066 }
11067
Dianne Hackborn12527f92009-11-11 17:39:50 -080011068 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11069 if (r.callingUid < 0) {
11070 // This was from a registerReceiver() call; ignore it.
11071 return;
11072 }
11073 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11074 MAX_BROADCAST_HISTORY-1);
11075 r.finishTime = SystemClock.uptimeMillis();
11076 mBroadcastHistory[0] = r;
11077 }
11078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 private final void processNextBroadcast(boolean fromMsg) {
11080 synchronized(this) {
11081 BroadcastRecord r;
11082
Joe Onorato8a9b2202010-02-26 18:56:32 -080011083 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011085 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086
11087 updateCpuStats();
11088
11089 if (fromMsg) {
11090 mBroadcastsScheduled = false;
11091 }
11092
11093 // First, deliver any non-serialized broadcasts right away.
11094 while (mParallelBroadcasts.size() > 0) {
11095 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011096 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011098 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011099 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 for (int i=0; i<N; i++) {
11101 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011102 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011103 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011105 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011107 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011108 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011109 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 }
11111
11112 // Now take care of the next serialized one...
11113
11114 // If we are waiting for a process to come up to handle the next
11115 // broadcast, then do nothing at this point. Just in case, we
11116 // check that the process we're waiting for still exists.
11117 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011118 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011119 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011120 + mPendingBroadcast.curApp);
11121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122
11123 boolean isDead;
11124 synchronized (mPidsSelfLocked) {
11125 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11126 }
11127 if (!isDead) {
11128 // It's still alive, so keep waiting
11129 return;
11130 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011131 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011133 mPendingBroadcast.state = BroadcastRecord.IDLE;
11134 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 mPendingBroadcast = null;
11136 }
11137 }
11138
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011139 boolean looped = false;
11140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 do {
11142 if (mOrderedBroadcasts.size() == 0) {
11143 // No more broadcasts pending, so all done!
11144 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011145 if (looped) {
11146 // If we had finished the last ordered broadcast, then
11147 // make sure all processes have correct oom and sched
11148 // adjustments.
11149 updateOomAdjLocked();
11150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 return;
11152 }
11153 r = mOrderedBroadcasts.get(0);
11154 boolean forceReceive = false;
11155
11156 // Ensure that even if something goes awry with the timeout
11157 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011158 // and continue to make progress.
11159 //
11160 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011161 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011162 // one time heavy lifting after system upgrades and can take
11163 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011165 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011166 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 if ((numReceivers > 0) &&
11168 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011169 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 + " now=" + now
11171 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011172 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 + " intent=" + r.intent
11174 + " numReceivers=" + numReceivers
11175 + " nextReceiver=" + r.nextReceiver
11176 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011177 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178 forceReceive = true;
11179 r.state = BroadcastRecord.IDLE;
11180 }
11181 }
11182
11183 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011184 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 "processNextBroadcast() called when not idle (state="
11186 + r.state + ")");
11187 return;
11188 }
11189
11190 if (r.receivers == null || r.nextReceiver >= numReceivers
11191 || r.resultAbort || forceReceive) {
11192 // No more receivers for this broadcast! Send the final
11193 // result if requested...
11194 if (r.resultTo != null) {
11195 try {
11196 if (DEBUG_BROADCAST) {
11197 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011198 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 + " seq=" + seq + " app=" + r.callerApp);
11200 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011201 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011203 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011205 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 }
11207 }
11208
Joe Onorato8a9b2202010-02-26 18:56:32 -080011209 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011210 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211
Joe Onorato8a9b2202010-02-26 18:56:32 -080011212 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011213 + r);
11214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011216 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011217 mOrderedBroadcasts.remove(0);
11218 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011219 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 continue;
11221 }
11222 } while (r == null);
11223
11224 // Get the next receiver...
11225 int recIdx = r.nextReceiver++;
11226
11227 // Keep track of when this receiver started, and make sure there
11228 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011229 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011231 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232
Joe Onorato8a9b2202010-02-26 18:56:32 -080011233 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011234 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011235 }
11236 if (! mPendingBroadcastTimeoutMessage) {
11237 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011238 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011239 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11240 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011241 }
11242
11243 Object nextReceiver = r.receivers.get(recIdx);
11244 if (nextReceiver instanceof BroadcastFilter) {
11245 // Simple case: this is a registered receiver who gets
11246 // a direct call.
11247 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011248 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011249 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011251 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 if (r.receiver == null || !r.ordered) {
11253 // The receiver has already finished, so schedule to
11254 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011255 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11256 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 r.state = BroadcastRecord.IDLE;
11258 scheduleBroadcastsLocked();
11259 }
11260 return;
11261 }
11262
11263 // Hard case: need to instantiate the receiver, possibly
11264 // starting its application process to host it.
11265
11266 ResolveInfo info =
11267 (ResolveInfo)nextReceiver;
11268
11269 boolean skip = false;
11270 int perm = checkComponentPermission(info.activityInfo.permission,
11271 r.callingPid, r.callingUid,
11272 info.activityInfo.exported
11273 ? -1 : info.activityInfo.applicationInfo.uid);
11274 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011275 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 + r.intent.toString()
11277 + " from " + r.callerPackage + " (pid=" + r.callingPid
11278 + ", uid=" + r.callingUid + ")"
11279 + " requires " + info.activityInfo.permission
11280 + " due to receiver " + info.activityInfo.packageName
11281 + "/" + info.activityInfo.name);
11282 skip = true;
11283 }
11284 if (r.callingUid != Process.SYSTEM_UID &&
11285 r.requiredPermission != null) {
11286 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011287 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 checkPermission(r.requiredPermission,
11289 info.activityInfo.applicationInfo.packageName);
11290 } catch (RemoteException e) {
11291 perm = PackageManager.PERMISSION_DENIED;
11292 }
11293 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011294 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 + r.intent + " to "
11296 + info.activityInfo.applicationInfo.packageName
11297 + " requires " + r.requiredPermission
11298 + " due to sender " + r.callerPackage
11299 + " (uid " + r.callingUid + ")");
11300 skip = true;
11301 }
11302 }
11303 if (r.curApp != null && r.curApp.crashing) {
11304 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011305 if (DEBUG_BROADCAST) Slog.v(TAG,
11306 "Skipping deliver ordered " + r + " to " + r.curApp
11307 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308 skip = true;
11309 }
11310
11311 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011312 if (DEBUG_BROADCAST) Slog.v(TAG,
11313 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011314 r.receiver = null;
11315 r.curFilter = null;
11316 r.state = BroadcastRecord.IDLE;
11317 scheduleBroadcastsLocked();
11318 return;
11319 }
11320
11321 r.state = BroadcastRecord.APP_RECEIVE;
11322 String targetProcess = info.activityInfo.processName;
11323 r.curComponent = new ComponentName(
11324 info.activityInfo.applicationInfo.packageName,
11325 info.activityInfo.name);
11326 r.curReceiver = info.activityInfo;
11327
11328 // Is this receiver's application already running?
11329 ProcessRecord app = getProcessRecordLocked(targetProcess,
11330 info.activityInfo.applicationInfo.uid);
11331 if (app != null && app.thread != null) {
11332 try {
11333 processCurBroadcastLocked(r, app);
11334 return;
11335 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011336 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 + r.curComponent, e);
11338 }
11339
11340 // If a dead object exception was thrown -- fall through to
11341 // restart the application.
11342 }
11343
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011344 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011345 if (DEBUG_BROADCAST) Slog.v(TAG,
11346 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 if ((r.curApp=startProcessLocked(targetProcess,
11348 info.activityInfo.applicationInfo, true,
11349 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011350 "broadcast", r.curComponent,
11351 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11352 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 // Ah, this recipient is unavailable. Finish it if necessary,
11354 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011355 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356 + info.activityInfo.applicationInfo.packageName + "/"
11357 + info.activityInfo.applicationInfo.uid + " for broadcast "
11358 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011359 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11361 r.resultExtras, r.resultAbort, true);
11362 scheduleBroadcastsLocked();
11363 r.state = BroadcastRecord.IDLE;
11364 return;
11365 }
11366
11367 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011368 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 }
11370 }
11371
11372 // =========================================================
11373 // INSTRUMENTATION
11374 // =========================================================
11375
11376 public boolean startInstrumentation(ComponentName className,
11377 String profileFile, int flags, Bundle arguments,
11378 IInstrumentationWatcher watcher) {
11379 // Refuse possible leaked file descriptors
11380 if (arguments != null && arguments.hasFileDescriptors()) {
11381 throw new IllegalArgumentException("File descriptors passed in Bundle");
11382 }
11383
11384 synchronized(this) {
11385 InstrumentationInfo ii = null;
11386 ApplicationInfo ai = null;
11387 try {
11388 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011389 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011391 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011392 } catch (PackageManager.NameNotFoundException e) {
11393 }
11394 if (ii == null) {
11395 reportStartInstrumentationFailure(watcher, className,
11396 "Unable to find instrumentation info for: " + className);
11397 return false;
11398 }
11399 if (ai == null) {
11400 reportStartInstrumentationFailure(watcher, className,
11401 "Unable to find instrumentation target package: " + ii.targetPackage);
11402 return false;
11403 }
11404
11405 int match = mContext.getPackageManager().checkSignatures(
11406 ii.targetPackage, ii.packageName);
11407 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11408 String msg = "Permission Denial: starting instrumentation "
11409 + className + " from pid="
11410 + Binder.getCallingPid()
11411 + ", uid=" + Binder.getCallingPid()
11412 + " not allowed because package " + ii.packageName
11413 + " does not have a signature matching the target "
11414 + ii.targetPackage;
11415 reportStartInstrumentationFailure(watcher, className, msg);
11416 throw new SecurityException(msg);
11417 }
11418
11419 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011420 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 ProcessRecord app = addAppLocked(ai);
11422 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011423 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 app.instrumentationProfileFile = profileFile;
11425 app.instrumentationArguments = arguments;
11426 app.instrumentationWatcher = watcher;
11427 app.instrumentationResultClass = className;
11428 Binder.restoreCallingIdentity(origId);
11429 }
11430
11431 return true;
11432 }
11433
11434 /**
11435 * Report errors that occur while attempting to start Instrumentation. Always writes the
11436 * error to the logs, but if somebody is watching, send the report there too. This enables
11437 * the "am" command to report errors with more information.
11438 *
11439 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11440 * @param cn The component name of the instrumentation.
11441 * @param report The error report.
11442 */
11443 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11444 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011445 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 try {
11447 if (watcher != null) {
11448 Bundle results = new Bundle();
11449 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11450 results.putString("Error", report);
11451 watcher.instrumentationStatus(cn, -1, results);
11452 }
11453 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011454 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 }
11456 }
11457
11458 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11459 if (app.instrumentationWatcher != null) {
11460 try {
11461 // NOTE: IInstrumentationWatcher *must* be oneway here
11462 app.instrumentationWatcher.instrumentationFinished(
11463 app.instrumentationClass,
11464 resultCode,
11465 results);
11466 } catch (RemoteException e) {
11467 }
11468 }
11469 app.instrumentationWatcher = null;
11470 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011471 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 app.instrumentationProfileFile = null;
11473 app.instrumentationArguments = null;
11474
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011475 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 }
11477
11478 public void finishInstrumentation(IApplicationThread target,
11479 int resultCode, Bundle results) {
11480 // Refuse possible leaked file descriptors
11481 if (results != null && results.hasFileDescriptors()) {
11482 throw new IllegalArgumentException("File descriptors passed in Intent");
11483 }
11484
11485 synchronized(this) {
11486 ProcessRecord app = getRecordForAppLocked(target);
11487 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011488 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011489 return;
11490 }
11491 final long origId = Binder.clearCallingIdentity();
11492 finishInstrumentationLocked(app, resultCode, results);
11493 Binder.restoreCallingIdentity(origId);
11494 }
11495 }
11496
11497 // =========================================================
11498 // CONFIGURATION
11499 // =========================================================
11500
11501 public ConfigurationInfo getDeviceConfigurationInfo() {
11502 ConfigurationInfo config = new ConfigurationInfo();
11503 synchronized (this) {
11504 config.reqTouchScreen = mConfiguration.touchscreen;
11505 config.reqKeyboardType = mConfiguration.keyboard;
11506 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011507 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11508 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11510 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011511 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11512 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11514 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011515 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 }
11517 return config;
11518 }
11519
11520 public Configuration getConfiguration() {
11521 Configuration ci;
11522 synchronized(this) {
11523 ci = new Configuration(mConfiguration);
11524 }
11525 return ci;
11526 }
11527
11528 public void updateConfiguration(Configuration values) {
11529 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11530 "updateConfiguration()");
11531
11532 synchronized(this) {
11533 if (values == null && mWindowManager != null) {
11534 // sentinel: fetch the current configuration from the window manager
11535 values = mWindowManager.computeNewConfiguration();
11536 }
11537
11538 final long origId = Binder.clearCallingIdentity();
11539 updateConfigurationLocked(values, null);
11540 Binder.restoreCallingIdentity(origId);
11541 }
11542 }
11543
11544 /**
11545 * Do either or both things: (1) change the current configuration, and (2)
11546 * make sure the given activity is running with the (now) current
11547 * configuration. Returns true if the activity has been left running, or
11548 * false if <var>starting</var> is being destroyed to match the new
11549 * configuration.
11550 */
11551 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011552 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 int changes = 0;
11554
11555 boolean kept = true;
11556
11557 if (values != null) {
11558 Configuration newConfig = new Configuration(mConfiguration);
11559 changes = newConfig.updateFrom(values);
11560 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011561 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 }
11564
Doug Zongker2bec3d42009-12-04 12:52:44 -080011565 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566
11567 if (values.locale != null) {
11568 saveLocaleLocked(values.locale,
11569 !values.locale.equals(mConfiguration.locale),
11570 values.userSetLocale);
11571 }
11572
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011573 mConfigurationSeq++;
11574 if (mConfigurationSeq <= 0) {
11575 mConfigurationSeq = 1;
11576 }
11577 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011579 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011580
11581 AttributeCache ac = AttributeCache.instance();
11582 if (ac != null) {
11583 ac.updateConfiguration(mConfiguration);
11584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011586 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11587 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11588 msg.obj = new Configuration(mConfiguration);
11589 mHandler.sendMessage(msg);
11590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011591
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011592 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11593 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 try {
11595 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011596 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011597 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 app.thread.scheduleConfigurationChanged(mConfiguration);
11599 }
11600 } catch (Exception e) {
11601 }
11602 }
11603 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011604 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11605 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011606 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11607 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011608 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11609 broadcastIntentLocked(null, null,
11610 new Intent(Intent.ACTION_LOCALE_CHANGED),
11611 null, null, 0, null, null,
11612 null, false, false, MY_PID, Process.SYSTEM_UID);
11613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 }
11615 }
11616
11617 if (changes != 0 && starting == null) {
11618 // If the configuration changed, and the caller is not already
11619 // in the process of starting an activity, then find the top
11620 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011621 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 }
11623
11624 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011625 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011626 if (kept) {
11627 // If this didn't result in the starting activity being
11628 // destroyed, then we need to make sure at this point that all
11629 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011630 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011632 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 }
11634 }
11635
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011636 if (values != null && mWindowManager != null) {
11637 mWindowManager.setNewConfiguration(mConfiguration);
11638 }
11639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011640 return kept;
11641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642
11643 /**
11644 * Save the locale. You must be inside a synchronized (this) block.
11645 */
11646 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11647 if(isDiff) {
11648 SystemProperties.set("user.language", l.getLanguage());
11649 SystemProperties.set("user.region", l.getCountry());
11650 }
11651
11652 if(isPersist) {
11653 SystemProperties.set("persist.sys.language", l.getLanguage());
11654 SystemProperties.set("persist.sys.country", l.getCountry());
11655 SystemProperties.set("persist.sys.localevar", l.getVariant());
11656 }
11657 }
11658
11659 // =========================================================
11660 // LIFETIME MANAGEMENT
11661 // =========================================================
11662
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011663 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11664 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011666 // This adjustment has already been computed. If we are calling
11667 // from the top, we may have already computed our adjustment with
11668 // an earlier hidden adjustment that isn't really for us... if
11669 // so, use the new hidden adjustment.
11670 if (!recursed && app.hidden) {
11671 app.curAdj = hiddenAdj;
11672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 return app.curAdj;
11674 }
11675
11676 if (app.thread == null) {
11677 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011678 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 return (app.curAdj=EMPTY_APP_ADJ);
11680 }
11681
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011682 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11683 // The max adjustment doesn't allow this app to be anything
11684 // below foreground, so it is not worth doing work for it.
11685 app.adjType = "fixed";
11686 app.adjSeq = mAdjSeq;
11687 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011688 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011689 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11690 return (app.curAdj=app.maxAdj);
11691 }
11692
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011693 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011694 app.adjSource = null;
11695 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011696 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011697 app.empty = false;
11698 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699
The Android Open Source Project4df24232009-03-05 14:34:35 -080011700 // Determine the importance of the process, starting with most
11701 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011703 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011704 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011705 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 // The last app on the list is the foreground app.
11707 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011708 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011709 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011710 } else if (app.instrumentationClass != null) {
11711 // Don't want to kill running instrumentation.
11712 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011713 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011714 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 } else if (app.curReceiver != null ||
11716 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11717 // An app that is currently receiving a broadcast also
11718 // counts as being in the foreground.
11719 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011720 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011721 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 } else if (app.executingServices.size() > 0) {
11723 // An app that is currently executing a service callback also
11724 // counts as being in the foreground.
11725 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011726 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011727 app.adjType = "exec-service";
11728 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011730 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011731 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011732 app.adjType = "foreground-service";
11733 } else if (app.forcingToForeground != null) {
11734 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011735 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011736 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011737 app.adjType = "force-foreground";
11738 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011739 } else if (app == mHeavyWeightProcess) {
11740 // We don't want to kill the current heavy-weight process.
11741 adj = HEAVY_WEIGHT_APP_ADJ;
11742 schedGroup = Process.THREAD_GROUP_DEFAULT;
11743 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011744 } else if (app == mHomeProcess) {
11745 // This process is hosting what we currently consider to be the
11746 // home app, so we don't want to let it go into the background.
11747 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011748 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011749 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 } else if ((N=app.activities.size()) != 0) {
11751 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011752 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011754 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011755 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011756 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011758 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011760 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011762 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011763 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764 break;
11765 }
11766 }
11767 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011768 // A very not-needed process. If this is lower in the lru list,
11769 // we will push it in to the empty bucket.
11770 app.hidden = true;
11771 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011772 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011773 adj = hiddenAdj;
11774 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 }
11776
Joe Onorato8a9b2202010-02-26 18:56:32 -080011777 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011778
The Android Open Source Project4df24232009-03-05 14:34:35 -080011779 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 // there are applications dependent on our services or providers, but
11781 // this gives us a baseline and makes sure we don't get into an
11782 // infinite recursion.
11783 app.adjSeq = mAdjSeq;
11784 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785
Christopher Tate6fa95972009-06-05 18:43:55 -070011786 if (mBackupTarget != null && app == mBackupTarget.app) {
11787 // If possible we want to avoid killing apps while they're being backed up
11788 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011789 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011790 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011791 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011792 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011793 }
11794 }
11795
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011796 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11797 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 final long now = SystemClock.uptimeMillis();
11799 // This process is more important if the top activity is
11800 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011801 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011803 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 if (s.startRequested) {
11805 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11806 // This service has seen some activity within
11807 // recent memory, so we will keep its process ahead
11808 // of the background processes.
11809 if (adj > SECONDARY_SERVER_ADJ) {
11810 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011811 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011812 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 }
11814 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011815 // If we have let the service slide into the background
11816 // state, still have some text describing what it is doing
11817 // even though the service no longer has an impact.
11818 if (adj > SECONDARY_SERVER_ADJ) {
11819 app.adjType = "started-bg-services";
11820 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011821 // Don't kill this process because it is doing work; it
11822 // has said it is doing work.
11823 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011825 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11826 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011827 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011828 = s.connections.values().iterator();
11829 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011830 ArrayList<ConnectionRecord> clist = kt.next();
11831 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11832 // XXX should compute this based on the max of
11833 // all connected clients.
11834 ConnectionRecord cr = clist.get(i);
11835 if (cr.binding.client == app) {
11836 // Binding to ourself is not interesting.
11837 continue;
11838 }
11839 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11840 ProcessRecord client = cr.binding.client;
11841 int myHiddenAdj = hiddenAdj;
11842 if (myHiddenAdj > client.hiddenAdj) {
11843 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11844 myHiddenAdj = client.hiddenAdj;
11845 } else {
11846 myHiddenAdj = VISIBLE_APP_ADJ;
11847 }
11848 }
11849 int clientAdj = computeOomAdjLocked(
11850 client, myHiddenAdj, TOP_APP, true);
11851 if (adj > clientAdj) {
11852 adj = clientAdj >= VISIBLE_APP_ADJ
11853 ? clientAdj : VISIBLE_APP_ADJ;
11854 if (!client.hidden) {
11855 app.hidden = false;
11856 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011857 if (client.keeping) {
11858 app.keeping = true;
11859 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011860 app.adjType = "service";
11861 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11862 .REASON_SERVICE_IN_USE;
11863 app.adjSource = cr.binding.client;
11864 app.adjTarget = s.name;
11865 }
11866 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11867 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11868 schedGroup = Process.THREAD_GROUP_DEFAULT;
11869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 }
11871 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011872 ActivityRecord a = cr.activity;
11873 //if (a != null) {
11874 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11875 //}
11876 if (a != null && adj > FOREGROUND_APP_ADJ &&
11877 (a.state == ActivityState.RESUMED
11878 || a.state == ActivityState.PAUSING)) {
11879 adj = FOREGROUND_APP_ADJ;
11880 schedGroup = Process.THREAD_GROUP_DEFAULT;
11881 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011882 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011883 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11884 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011885 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011886 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011888 }
11889 }
11890 }
11891 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011892
Dianne Hackborn287952c2010-09-22 22:34:31 -070011893 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011894 // would like to avoid killing it unless it would prevent the current
11895 // application from running. By default we put the process in
11896 // with the rest of the background processes; as we scan through
11897 // its services we may bump it up from there.
11898 if (adj > hiddenAdj) {
11899 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011900 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011901 app.adjType = "bg-services";
11902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 }
11904
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011905 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11906 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011907 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011908 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11909 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011910 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911 if (cpr.clients.size() != 0) {
11912 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11913 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11914 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011915 if (client == app) {
11916 // Being our own client is not interesting.
11917 continue;
11918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 int myHiddenAdj = hiddenAdj;
11920 if (myHiddenAdj > client.hiddenAdj) {
11921 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11922 myHiddenAdj = client.hiddenAdj;
11923 } else {
11924 myHiddenAdj = FOREGROUND_APP_ADJ;
11925 }
11926 }
11927 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011928 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 if (adj > clientAdj) {
11930 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011931 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011932 if (!client.hidden) {
11933 app.hidden = false;
11934 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011935 if (client.keeping) {
11936 app.keeping = true;
11937 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011938 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011939 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11940 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011941 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011942 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011944 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11945 schedGroup = Process.THREAD_GROUP_DEFAULT;
11946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 }
11948 }
11949 // If the provider has external (non-framework) process
11950 // dependencies, ensure that its adjustment is at least
11951 // FOREGROUND_APP_ADJ.
11952 if (cpr.externals != 0) {
11953 if (adj > FOREGROUND_APP_ADJ) {
11954 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011955 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011956 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011957 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011958 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011959 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 }
11961 }
11962 }
11963 }
11964
11965 app.curRawAdj = adj;
11966
Joe Onorato8a9b2202010-02-26 18:56:32 -080011967 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011968 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11969 if (adj > app.maxAdj) {
11970 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011971 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011972 schedGroup = Process.THREAD_GROUP_DEFAULT;
11973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011974 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011975 if (adj < HIDDEN_APP_MIN_ADJ) {
11976 app.keeping = true;
11977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978
11979 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011980 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 return adj;
11983 }
11984
11985 /**
11986 * Ask a given process to GC right now.
11987 */
11988 final void performAppGcLocked(ProcessRecord app) {
11989 try {
11990 app.lastRequestedGc = SystemClock.uptimeMillis();
11991 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011992 if (app.reportLowMemory) {
11993 app.reportLowMemory = false;
11994 app.thread.scheduleLowMemory();
11995 } else {
11996 app.thread.processInBackground();
11997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011998 }
11999 } catch (Exception e) {
12000 // whatever.
12001 }
12002 }
12003
12004 /**
12005 * Returns true if things are idle enough to perform GCs.
12006 */
Josh Bartel7f208742010-02-25 11:01:44 -060012007 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008 return mParallelBroadcasts.size() == 0
12009 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012010 && (mSleeping || (mMainStack.mResumedActivity != null &&
12011 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 }
12013
12014 /**
12015 * Perform GCs on all processes that are waiting for it, but only
12016 * if things are idle.
12017 */
12018 final void performAppGcsLocked() {
12019 final int N = mProcessesToGc.size();
12020 if (N <= 0) {
12021 return;
12022 }
Josh Bartel7f208742010-02-25 11:01:44 -060012023 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012024 while (mProcessesToGc.size() > 0) {
12025 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012026 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012027 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12028 <= SystemClock.uptimeMillis()) {
12029 // To avoid spamming the system, we will GC processes one
12030 // at a time, waiting a few seconds between each.
12031 performAppGcLocked(proc);
12032 scheduleAppGcsLocked();
12033 return;
12034 } else {
12035 // It hasn't been long enough since we last GCed this
12036 // process... put it in the list to wait for its time.
12037 addProcessToGcListLocked(proc);
12038 break;
12039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012040 }
12041 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012042
12043 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012044 }
12045 }
12046
12047 /**
12048 * If all looks good, perform GCs on all processes waiting for them.
12049 */
12050 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012051 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 performAppGcsLocked();
12053 return;
12054 }
12055 // Still not idle, wait some more.
12056 scheduleAppGcsLocked();
12057 }
12058
12059 /**
12060 * Schedule the execution of all pending app GCs.
12061 */
12062 final void scheduleAppGcsLocked() {
12063 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012064
12065 if (mProcessesToGc.size() > 0) {
12066 // Schedule a GC for the time to the next process.
12067 ProcessRecord proc = mProcessesToGc.get(0);
12068 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12069
12070 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12071 long now = SystemClock.uptimeMillis();
12072 if (when < (now+GC_TIMEOUT)) {
12073 when = now + GC_TIMEOUT;
12074 }
12075 mHandler.sendMessageAtTime(msg, when);
12076 }
12077 }
12078
12079 /**
12080 * Add a process to the array of processes waiting to be GCed. Keeps the
12081 * list in sorted order by the last GC time. The process can't already be
12082 * on the list.
12083 */
12084 final void addProcessToGcListLocked(ProcessRecord proc) {
12085 boolean added = false;
12086 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12087 if (mProcessesToGc.get(i).lastRequestedGc <
12088 proc.lastRequestedGc) {
12089 added = true;
12090 mProcessesToGc.add(i+1, proc);
12091 break;
12092 }
12093 }
12094 if (!added) {
12095 mProcessesToGc.add(0, proc);
12096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012097 }
12098
12099 /**
12100 * Set up to ask a process to GC itself. This will either do it
12101 * immediately, or put it on the list of processes to gc the next
12102 * time things are idle.
12103 */
12104 final void scheduleAppGcLocked(ProcessRecord app) {
12105 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012106 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107 return;
12108 }
12109 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012110 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 scheduleAppGcsLocked();
12112 }
12113 }
12114
Dianne Hackborn287952c2010-09-22 22:34:31 -070012115 final void checkExcessivePowerUsageLocked(boolean doKills) {
12116 updateCpuStatsNow();
12117
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012118 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012119 boolean doWakeKills = doKills;
12120 boolean doCpuKills = doKills;
12121 if (mLastPowerCheckRealtime == 0) {
12122 doWakeKills = false;
12123 }
12124 if (mLastPowerCheckUptime == 0) {
12125 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012126 }
12127 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012128 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012129 }
12130 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012131 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12132 final long curUptime = SystemClock.uptimeMillis();
12133 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12134 mLastPowerCheckRealtime = curRealtime;
12135 mLastPowerCheckUptime = curUptime;
12136 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12137 doWakeKills = false;
12138 }
12139 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12140 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012141 }
12142 int i = mLruProcesses.size();
12143 while (i > 0) {
12144 i--;
12145 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012146 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012147 long wtime;
12148 synchronized (stats) {
12149 wtime = stats.getProcessWakeTime(app.info.uid,
12150 app.pid, curRealtime);
12151 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012152 long wtimeUsed = wtime - app.lastWakeTime;
12153 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12154 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012155 StringBuilder sb = new StringBuilder(128);
12156 sb.append("Wake for ");
12157 app.toShortString(sb);
12158 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012159 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012160 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012161 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012162 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012163 sb.append((wtimeUsed*100)/realtimeSince);
12164 sb.append("%)");
12165 Slog.i(TAG, sb.toString());
12166 sb.setLength(0);
12167 sb.append("CPU for ");
12168 app.toShortString(sb);
12169 sb.append(": over ");
12170 TimeUtils.formatDuration(uptimeSince, sb);
12171 sb.append(" used ");
12172 TimeUtils.formatDuration(cputimeUsed, sb);
12173 sb.append(" (");
12174 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012175 sb.append("%)");
12176 Slog.i(TAG, sb.toString());
12177 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012178 // If a process has held a wake lock for more
12179 // than 50% of the time during this period,
12180 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012181 if (doWakeKills && realtimeSince > 0
12182 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12183 synchronized (stats) {
12184 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12185 realtimeSince, wtimeUsed);
12186 }
12187 Slog.w(TAG, "Excessive wake lock in " + app.processName
12188 + " (pid " + app.pid + "): held " + wtimeUsed
12189 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012190 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12191 app.processName, app.setAdj, "excessive wake lock");
12192 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012193 } else if (doCpuKills && uptimeSince > 0
12194 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12195 synchronized (stats) {
12196 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12197 uptimeSince, cputimeUsed);
12198 }
12199 Slog.w(TAG, "Excessive CPU in " + app.processName
12200 + " (pid " + app.pid + "): used " + cputimeUsed
12201 + " during " + uptimeSince);
12202 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12203 app.processName, app.setAdj, "excessive cpu");
12204 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012205 } else {
12206 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012207 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012208 }
12209 }
12210 }
12211 }
12212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012213 private final boolean updateOomAdjLocked(
12214 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12215 app.hiddenAdj = hiddenAdj;
12216
12217 if (app.thread == null) {
12218 return true;
12219 }
12220
Dianne Hackborn287952c2010-09-22 22:34:31 -070012221 final boolean wasKeeping = app.keeping;
12222
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012223 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012224
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012225 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 if (app.curRawAdj != app.setRawAdj) {
12227 if (app.curRawAdj > FOREGROUND_APP_ADJ
12228 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12229 // If this app is transitioning from foreground to
12230 // non-foreground, have it do a gc.
12231 scheduleAppGcLocked(app);
12232 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12233 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12234 // Likewise do a gc when an app is moving in to the
12235 // background (such as a service stopping).
12236 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012237 }
12238
12239 if (wasKeeping && !app.keeping) {
12240 // This app is no longer something we want to keep. Note
12241 // its current wake lock time to later know to kill it if
12242 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012243 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12244 synchronized (stats) {
12245 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12246 app.pid, SystemClock.elapsedRealtime());
12247 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012248 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012249 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012251 app.setRawAdj = app.curRawAdj;
12252 }
12253 if (adj != app.setAdj) {
12254 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012255 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012256 TAG, "Set app " + app.processName +
12257 " oom adj to " + adj);
12258 app.setAdj = adj;
12259 } else {
12260 return false;
12261 }
12262 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012263 if (app.setSchedGroup != app.curSchedGroup) {
12264 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012265 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012266 "Setting process group of " + app.processName
12267 + " to " + app.curSchedGroup);
12268 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012269 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012270 try {
12271 Process.setProcessGroup(app.pid, app.curSchedGroup);
12272 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012273 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012274 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012275 e.printStackTrace();
12276 } finally {
12277 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012278 }
12279 }
12280 if (false) {
12281 if (app.thread != null) {
12282 try {
12283 app.thread.setSchedulingGroup(app.curSchedGroup);
12284 } catch (RemoteException e) {
12285 }
12286 }
12287 }
12288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012289 }
12290
12291 return true;
12292 }
12293
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012294 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012295 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012296 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012297 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012298 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012299 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012300 }
12301 }
12302 return resumedActivity;
12303 }
12304
12305 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012306 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012307 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12308 int curAdj = app.curAdj;
12309 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12310 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12311
12312 mAdjSeq++;
12313
12314 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12315 if (res) {
12316 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12317 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12318 if (nowHidden != wasHidden) {
12319 // Changed to/from hidden state, so apps after it in the LRU
12320 // list may also be changed.
12321 updateOomAdjLocked();
12322 }
12323 }
12324 return res;
12325 }
12326
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012327 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012328 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012329 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12331
12332 if (false) {
12333 RuntimeException e = new RuntimeException();
12334 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012335 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 }
12337
12338 mAdjSeq++;
12339
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012340 // Let's determine how many processes we have running vs.
12341 // how many slots we have for background processes; we may want
12342 // to put multiple processes in a slot of there are enough of
12343 // them.
12344 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12345 int factor = (mLruProcesses.size()-4)/numSlots;
12346 if (factor < 1) factor = 1;
12347 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012348 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012350 // First try updating the OOM adjustment for each of the
12351 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012352 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12354 while (i > 0) {
12355 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012356 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012357 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012359 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012361 step++;
12362 if (step >= factor) {
12363 step = 0;
12364 curHiddenAdj++;
12365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012367 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012368 if (!app.killedBackground) {
12369 numHidden++;
12370 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012371 Slog.i(TAG, "No longer want " + app.processName
12372 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012373 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12374 app.processName, app.setAdj, "too many background");
12375 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012376 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012377 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012378 }
12379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012380 } else {
12381 didOomAdj = false;
12382 }
12383 }
12384
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012385 // If we return false, we will fall back on killing processes to
12386 // have a fixed limit. Do this if a limit has been requested; else
12387 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012388 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12389 }
12390
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012391 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 synchronized (this) {
12393 int i;
12394
12395 // First remove any unused application processes whose package
12396 // has been removed.
12397 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12398 final ProcessRecord app = mRemovedProcesses.get(i);
12399 if (app.activities.size() == 0
12400 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012401 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402 TAG, "Exiting empty application process "
12403 + app.processName + " ("
12404 + (app.thread != null ? app.thread.asBinder() : null)
12405 + ")\n");
12406 if (app.pid > 0 && app.pid != MY_PID) {
12407 Process.killProcess(app.pid);
12408 } else {
12409 try {
12410 app.thread.scheduleExit();
12411 } catch (Exception e) {
12412 // Ignore exceptions.
12413 }
12414 }
12415 cleanUpApplicationRecordLocked(app, false, -1);
12416 mRemovedProcesses.remove(i);
12417
12418 if (app.persistent) {
12419 if (app.persistent) {
12420 addAppLocked(app.info);
12421 }
12422 }
12423 }
12424 }
12425
12426 // Now try updating the OOM adjustment for each of the
12427 // application processes based on their current state.
12428 // If the setOomAdj() API is not supported, then go with our
12429 // back-up plan...
12430 if (!updateOomAdjLocked()) {
12431
12432 // Count how many processes are running services.
12433 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012434 for (i=mLruProcesses.size()-1; i>=0; i--) {
12435 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436
12437 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012438 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012439 // Don't count processes holding services against our
12440 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012441 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012442 TAG, "Not trimming app " + app + " with services: "
12443 + app.services);
12444 numServiceProcs++;
12445 }
12446 }
12447
12448 int curMaxProcs = mProcessLimit;
12449 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12450 if (mAlwaysFinishActivities) {
12451 curMaxProcs = 1;
12452 }
12453 curMaxProcs += numServiceProcs;
12454
12455 // Quit as many processes as we can to get down to the desired
12456 // process count. First remove any processes that no longer
12457 // have activites running in them.
12458 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012459 i<mLruProcesses.size()
12460 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012461 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012462 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012463 // Quit an application only if it is not currently
12464 // running any activities.
12465 if (!app.persistent && app.activities.size() == 0
12466 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012467 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012468 TAG, "Exiting empty application process "
12469 + app.processName + " ("
12470 + (app.thread != null ? app.thread.asBinder() : null)
12471 + ")\n");
12472 if (app.pid > 0 && app.pid != MY_PID) {
12473 Process.killProcess(app.pid);
12474 } else {
12475 try {
12476 app.thread.scheduleExit();
12477 } catch (Exception e) {
12478 // Ignore exceptions.
12479 }
12480 }
12481 // todo: For now we assume the application is not buggy
12482 // or evil, and will quit as a result of our request.
12483 // Eventually we need to drive this off of the death
12484 // notification, and kill the process if it takes too long.
12485 cleanUpApplicationRecordLocked(app, false, i);
12486 i--;
12487 }
12488 }
12489
12490 // If we still have too many processes, now from the least
12491 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012492 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012493 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 " of " + curMaxProcs + " processes");
12495 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012496 i<mLruProcesses.size()
12497 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012499 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012500 // Quit the application only if we have a state saved for
12501 // all of its activities.
12502 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012503 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 int NUMA = app.activities.size();
12505 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012506 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012507 TAG, "Looking to quit " + app.processName);
12508 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012509 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012510 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012511 TAG, " " + r.intent.getComponent().flattenToShortString()
12512 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12513 canQuit = (r.haveState || !r.stateNotNeeded)
12514 && !r.visible && r.stopped;
12515 }
12516 if (canQuit) {
12517 // Finish all of the activities, and then the app itself.
12518 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012519 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012520 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012521 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 }
12523 r.resultTo = null;
12524 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012525 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012526 + app.processName + " ("
12527 + (app.thread != null ? app.thread.asBinder() : null)
12528 + ")\n");
12529 if (app.pid > 0 && app.pid != MY_PID) {
12530 Process.killProcess(app.pid);
12531 } else {
12532 try {
12533 app.thread.scheduleExit();
12534 } catch (Exception e) {
12535 // Ignore exceptions.
12536 }
12537 }
12538 // todo: For now we assume the application is not buggy
12539 // or evil, and will quit as a result of our request.
12540 // Eventually we need to drive this off of the death
12541 // notification, and kill the process if it takes too long.
12542 cleanUpApplicationRecordLocked(app, false, i);
12543 i--;
12544 //dump();
12545 }
12546 }
12547
12548 }
12549
12550 int curMaxActivities = MAX_ACTIVITIES;
12551 if (mAlwaysFinishActivities) {
12552 curMaxActivities = 1;
12553 }
12554
12555 // Finally, if there are too many activities now running, try to
12556 // finish as many as we can to get back down to the limit.
12557 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012558 i<mMainStack.mLRUActivities.size()
12559 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012561 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012562 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012563
12564 // We can finish this one if we have its icicle saved and
12565 // it is not persistent.
12566 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012567 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012568 final int origSize = mMainStack.mLRUActivities.size();
12569 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570
12571 // This will remove it from the LRU list, so keep
12572 // our index at the same value. Note that this check to
12573 // see if the size changes is just paranoia -- if
12574 // something unexpected happens, we don't want to end up
12575 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012576 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 i--;
12578 }
12579 }
12580 }
12581 }
12582 }
12583
12584 /** This method sends the specified signal to each of the persistent apps */
12585 public void signalPersistentProcesses(int sig) throws RemoteException {
12586 if (sig != Process.SIGNAL_USR1) {
12587 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12588 }
12589
12590 synchronized (this) {
12591 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12592 != PackageManager.PERMISSION_GRANTED) {
12593 throw new SecurityException("Requires permission "
12594 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12595 }
12596
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012597 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12598 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 if (r.thread != null && r.persistent) {
12600 Process.sendSignal(r.pid, sig);
12601 }
12602 }
12603 }
12604 }
12605
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012606 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012607 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012608
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012609 try {
12610 synchronized (this) {
12611 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12612 // its own permission.
12613 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12614 != PackageManager.PERMISSION_GRANTED) {
12615 throw new SecurityException("Requires permission "
12616 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012617 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012618
12619 if (start && fd == null) {
12620 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012621 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012622
12623 ProcessRecord proc = null;
12624 try {
12625 int pid = Integer.parseInt(process);
12626 synchronized (mPidsSelfLocked) {
12627 proc = mPidsSelfLocked.get(pid);
12628 }
12629 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012630 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012631
12632 if (proc == null) {
12633 HashMap<String, SparseArray<ProcessRecord>> all
12634 = mProcessNames.getMap();
12635 SparseArray<ProcessRecord> procs = all.get(process);
12636 if (procs != null && procs.size() > 0) {
12637 proc = procs.valueAt(0);
12638 }
12639 }
12640
12641 if (proc == null || proc.thread == null) {
12642 throw new IllegalArgumentException("Unknown process: " + process);
12643 }
12644
12645 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12646 if (isSecure) {
12647 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12648 throw new SecurityException("Process not debuggable: " + proc);
12649 }
12650 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012651
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012652 proc.thread.profilerControl(start, path, fd);
12653 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012654 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012655 }
12656 } catch (RemoteException e) {
12657 throw new IllegalStateException("Process disappeared");
12658 } finally {
12659 if (fd != null) {
12660 try {
12661 fd.close();
12662 } catch (IOException e) {
12663 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012664 }
12665 }
12666 }
Andy McFadden824c5102010-07-09 16:26:57 -070012667
12668 public boolean dumpHeap(String process, boolean managed,
12669 String path, ParcelFileDescriptor fd) throws RemoteException {
12670
12671 try {
12672 synchronized (this) {
12673 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12674 // its own permission (same as profileControl).
12675 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12676 != PackageManager.PERMISSION_GRANTED) {
12677 throw new SecurityException("Requires permission "
12678 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12679 }
12680
12681 if (fd == null) {
12682 throw new IllegalArgumentException("null fd");
12683 }
12684
12685 ProcessRecord proc = null;
12686 try {
12687 int pid = Integer.parseInt(process);
12688 synchronized (mPidsSelfLocked) {
12689 proc = mPidsSelfLocked.get(pid);
12690 }
12691 } catch (NumberFormatException e) {
12692 }
12693
12694 if (proc == null) {
12695 HashMap<String, SparseArray<ProcessRecord>> all
12696 = mProcessNames.getMap();
12697 SparseArray<ProcessRecord> procs = all.get(process);
12698 if (procs != null && procs.size() > 0) {
12699 proc = procs.valueAt(0);
12700 }
12701 }
12702
12703 if (proc == null || proc.thread == null) {
12704 throw new IllegalArgumentException("Unknown process: " + process);
12705 }
12706
12707 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12708 if (isSecure) {
12709 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12710 throw new SecurityException("Process not debuggable: " + proc);
12711 }
12712 }
12713
12714 proc.thread.dumpHeap(managed, path, fd);
12715 fd = null;
12716 return true;
12717 }
12718 } catch (RemoteException e) {
12719 throw new IllegalStateException("Process disappeared");
12720 } finally {
12721 if (fd != null) {
12722 try {
12723 fd.close();
12724 } catch (IOException e) {
12725 }
12726 }
12727 }
12728 }
12729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012730 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12731 public void monitor() {
12732 synchronized (this) { }
12733 }
12734}