blob: 254a19b534ff1c8bde879f8fe7428d35478184b4 [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;
Robert Greenwalt434203a2010-10-11 16:00:27 -070079import android.net.Proxy;
80import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700111import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700118import java.io.BufferedInputStream;
119import java.io.BufferedOutputStream;
120import java.io.DataInputStream;
121import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.File;
123import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200127import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800128import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.PrintWriter;
130import java.lang.IllegalStateException;
131import java.lang.ref.WeakReference;
132import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700133import java.util.Collections;
134import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.util.HashMap;
136import java.util.HashSet;
137import java.util.Iterator;
138import java.util.List;
139import java.util.Locale;
140import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700141import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700142import java.util.concurrent.atomic.AtomicBoolean;
143import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700145public final class ActivityManagerService extends ActivityManagerNative
146 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final String TAG = "ActivityManager";
148 static final boolean DEBUG = false;
149 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
150 static final boolean DEBUG_SWITCH = localLOGV || false;
151 static final boolean DEBUG_TASKS = localLOGV || false;
152 static final boolean DEBUG_PAUSE = localLOGV || false;
153 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
154 static final boolean DEBUG_TRANSITION = localLOGV || false;
155 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700156 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700158 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_VISBILITY = localLOGV || false;
160 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700161 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800162 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700164 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700165 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700166 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700167 static final boolean DEBUG_POWER = localLOGV || false;
168 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean VALIDATE_TOKENS = false;
170 static final boolean SHOW_ACTIVITY_START_TIME = true;
171
172 // Control over CPU and battery monitoring.
173 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
174 static final boolean MONITOR_CPU_USAGE = true;
175 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
176 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
177 static final boolean MONITOR_THREAD_CPU_USAGE = false;
178
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700180 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 private static final String SYSTEM_SECURE = "ro.secure";
183
184 // This is the maximum number of application processes we would like
185 // to have running. Due to the asynchronous nature of things, we can
186 // temporarily go beyond this limit.
187 static final int MAX_PROCESSES = 2;
188
189 // Set to false to leave processes running indefinitely, relying on
190 // the kernel killing them as resources are required.
191 static final boolean ENFORCE_PROCESS_LIMIT = false;
192
193 // This is the maximum number of activities that we would like to have
194 // running at a given time.
195 static final int MAX_ACTIVITIES = 20;
196
197 // Maximum number of recent tasks that we can remember.
198 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700199
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700200 // Amount of time after a call to stopAppSwitches() during which we will
201 // prevent further untrusted switches from happening.
202 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203
204 // How long we wait for a launched process to attach to the activity manager
205 // before we decide it's never going to come up for real.
206 static final int PROC_START_TIMEOUT = 10*1000;
207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 // How long to wait after going idle before forcing apps to GC.
209 static final int GC_TIMEOUT = 5*1000;
210
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700211 // The minimum amount of time between successive GC requests for a process.
212 static final int GC_MIN_INTERVAL = 60*1000;
213
Dianne Hackborn287952c2010-09-22 22:34:31 -0700214 // The rate at which we check for apps using excessive power -- 15 mins.
215 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
216
217 // The minimum sample duration we will allow before deciding we have
218 // enough data on wake locks to start killing things.
219 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
220
221 // The minimum sample duration we will allow before deciding we have
222 // enough data on CPU usage to start killing things.
223 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // How long we allow a receiver to run before giving up on it.
226 static final int BROADCAST_TIMEOUT = 10*1000;
227
228 // How long we wait for a service to finish executing.
229 static final int SERVICE_TIMEOUT = 20*1000;
230
231 // How long a service needs to be running until restarting its process
232 // is no longer considered to be a relaunch of the service.
233 static final int SERVICE_RESTART_DURATION = 5*1000;
234
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700235 // How long a service needs to be running until it will start back at
236 // SERVICE_RESTART_DURATION after being killed.
237 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
238
239 // Multiplying factor to increase restart duration time by, for each time
240 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
241 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
242
243 // The minimum amount of time between restarting services that we allow.
244 // That is, when multiple services are restarting, we won't allow each
245 // to restart less than this amount of time from the last one.
246 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 // Maximum amount of time for there to be no activity on a service before
249 // we consider it non-essential and allow its process to go on the
250 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700251 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // How long we wait until we timeout on key dispatching.
254 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
255
256 // The minimum time we allow between crashes, for us to consider this
257 // application to be bad and stop and its services and reject broadcasts.
258 static final int MIN_CRASH_INTERVAL = 60*1000;
259
260 // How long we wait until we timeout on key dispatching during instrumentation.
261 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
262
263 // OOM adjustments for processes in various states:
264
265 // This is a process without anything currently running in it. Definitely
266 // the first to go! Value set in system/rootdir/init.rc on startup.
267 // This value is initalized in the constructor, careful when refering to
268 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 // This is a process only hosting activities that are not visible,
272 // so it can be killed without any disruption. Value set in
273 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 static int HIDDEN_APP_MIN_ADJ;
276
The Android Open Source Project4df24232009-03-05 14:34:35 -0800277 // This is a process holding the home application -- we want to try
278 // avoiding killing it, even if it would normally be in the background,
279 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800281
Christopher Tate6fa95972009-06-05 18:43:55 -0700282 // This is a process currently hosting a backup operation. Killing it
283 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 // This is a process holding a secondary server -- killing it will not
287 // have much of an impact as far as the user is concerned. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700291 // This is a process with a heavy-weight application. It is in the
292 // background, but we want to try to avoid killing it. Value set in
293 // system/rootdir/init.rc on startup.
294 static final int HEAVY_WEIGHT_APP_ADJ;
295
296 // This is a process only hosting components that are perceptible to the
297 // user, and we really want to avoid killing them, but they are not
298 // immediately visible. An example is background music playback. Value set in
299 // system/rootdir/init.rc on startup.
300 static final int PERCEPTIBLE_APP_ADJ;
301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 // This is a process only hosting activities that are visible to the
303 // user, so we'd prefer they don't disappear. Value set in
304 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800305 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
307 // This is the process running the current foreground app. We'd really
308 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800309 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 // This is a process running a core server, such as telephony. Definitely
312 // don't want to kill it, but doing so is not completely fatal.
313 static final int CORE_SERVER_ADJ = -12;
314
315 // The system process runs at the default adjustment.
316 static final int SYSTEM_ADJ = -16;
317
318 // Memory pages are 4K.
319 static final int PAGE_SIZE = 4*1024;
320
321 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322 static final int EMPTY_APP_MEM;
323 static final int HIDDEN_APP_MEM;
324 static final int HOME_APP_MEM;
325 static final int BACKUP_APP_MEM;
326 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static final int HEAVY_WEIGHT_APP_MEM;
328 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800329 static final int VISIBLE_APP_MEM;
330 static final int FOREGROUND_APP_MEM;
331
332 // The minimum number of hidden apps we want to be able to keep around,
333 // without empty apps being able to push them out of memory.
334 static final int MIN_HIDDEN_APPS = 2;
335
Dianne Hackborn8633e682010-04-22 16:03:41 -0700336 // The maximum number of hidden processes we will keep around before
337 // killing them; this is just a control to not let us go too crazy with
338 // keeping around processes on devices with large amounts of RAM.
339 static final int MAX_HIDDEN_APPS = 15;
340
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700342 // been idle for less than 15 seconds.
343 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800344
345 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700346 // been idle for less than 120 seconds.
347 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800348
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700349 static int getIntProp(String name, boolean allowZero) {
350 String str = SystemProperties.get(name);
351 if (str == null) {
352 throw new IllegalArgumentException("Property not defined: " + name);
353 }
354 int val = Integer.valueOf(str);
355 if (val == 0 && !allowZero) {
356 throw new IllegalArgumentException("Property must not be zero: " + name);
357 }
358 return val;
359 }
360
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 static {
362 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700363 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
364 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
365 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
366 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
367 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
368 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
369 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
370 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
371 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
372 // These days we use the last empty slot for hidden apps as well.
373 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
374 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
375 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
376 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
377 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
378 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
379 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
380 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
381 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
382 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
Dan Egnor42471dd2010-01-07 17:25:22 -0800385 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386
387 static final String[] EMPTY_STRING_ARRAY = new String[0];
388
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700389 public ActivityStack mMainStack;
390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700392 * Description of a request to start a new activity, which has been held
393 * due to app switches being disabled.
394 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700395 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700396 ActivityRecord r;
397 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700398 Uri[] grantedUriPermissions;
399 int grantedMode;
400 boolean onlyIfNeeded;
401 }
402
403 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
404 = new ArrayList<PendingActivityLaunch>();
405
406 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 * List of all active broadcasts that are to be executed immediately
408 * (without waiting for another broadcast to finish). Currently this only
409 * contains broadcasts to registered receivers, to avoid spinning up
410 * a bunch of processes to execute IntentReceiver components.
411 */
412 final ArrayList<BroadcastRecord> mParallelBroadcasts
413 = new ArrayList<BroadcastRecord>();
414
415 /**
416 * List of all active broadcasts that are to be executed one at a time.
417 * The object at the top of the list is the currently activity broadcasts;
418 * those after it are waiting for the top to finish..
419 */
420 final ArrayList<BroadcastRecord> mOrderedBroadcasts
421 = new ArrayList<BroadcastRecord>();
422
423 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800424 * Historical data of past broadcasts, for debugging.
425 */
426 static final int MAX_BROADCAST_HISTORY = 100;
427 final BroadcastRecord[] mBroadcastHistory
428 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
429
430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * Set when we current have a BROADCAST_INTENT_MSG in flight.
432 */
433 boolean mBroadcastsScheduled = false;
434
435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * Activity we have told the window manager to have key focus.
437 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700438 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * List of intents that were used to start the most recent tasks.
441 */
442 final ArrayList<TaskRecord> mRecentTasks
443 = new ArrayList<TaskRecord>();
444
445 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 * All of the applications we currently have running organized by name.
447 * The keys are strings of the application package name (as
448 * returned by the package manager), and the keys are ApplicationRecord
449 * objects.
450 */
451 final ProcessMap<ProcessRecord> mProcessNames
452 = new ProcessMap<ProcessRecord>();
453
454 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700455 * The currently running heavy-weight process, if any.
456 */
457 ProcessRecord mHeavyWeightProcess = null;
458
459 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 * The last time that various processes have crashed.
461 */
462 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
463
464 /**
465 * Set of applications that we consider to be bad, and will reject
466 * incoming broadcasts from (which the user has no control over).
467 * Processes are added to this set when they have crashed twice within
468 * a minimum amount of time; they are removed from it when they are
469 * later restarted (hopefully due to some user action). The value is the
470 * time it was added to the list.
471 */
472 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
473
474 /**
475 * All of the processes we currently have running organized by pid.
476 * The keys are the pid running the application.
477 *
478 * <p>NOTE: This object is protected by its own lock, NOT the global
479 * activity manager lock!
480 */
481 final SparseArray<ProcessRecord> mPidsSelfLocked
482 = new SparseArray<ProcessRecord>();
483
484 /**
485 * All of the processes that have been forced to be foreground. The key
486 * is the pid of the caller who requested it (we hold a death
487 * link on it).
488 */
489 abstract class ForegroundToken implements IBinder.DeathRecipient {
490 int pid;
491 IBinder token;
492 }
493 final SparseArray<ForegroundToken> mForegroundProcesses
494 = new SparseArray<ForegroundToken>();
495
496 /**
497 * List of records for processes that someone had tried to start before the
498 * system was ready. We don't start them at that point, but ensure they
499 * are started by the time booting is complete.
500 */
501 final ArrayList<ProcessRecord> mProcessesOnHold
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of records for processes that we have started and are waiting
506 * for them to call back. This is really only needed when running in
507 * single processes mode, in which case we do not have a unique pid for
508 * each process.
509 */
510 final ArrayList<ProcessRecord> mStartingProcesses
511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of persistent applications that are in the process
515 * of being started.
516 */
517 final ArrayList<ProcessRecord> mPersistentStartingProcesses
518 = new ArrayList<ProcessRecord>();
519
520 /**
521 * Processes that are being forcibly torn down.
522 */
523 final ArrayList<ProcessRecord> mRemovedProcesses
524 = new ArrayList<ProcessRecord>();
525
526 /**
527 * List of running applications, sorted by recent usage.
528 * The first entry in the list is the least recently used.
529 * It contains ApplicationRecord objects. This list does NOT include
530 * any persistent application records (since we never want to exit them).
531 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800532 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 = new ArrayList<ProcessRecord>();
534
535 /**
536 * List of processes that should gc as soon as things are idle.
537 */
538 final ArrayList<ProcessRecord> mProcessesToGc
539 = new ArrayList<ProcessRecord>();
540
541 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800542 * This is the process holding what we currently consider to be
543 * the "home" activity.
544 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700545 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800546
547 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 * Set of PendingResultRecord objects that are currently active.
549 */
550 final HashSet mPendingResultRecords = new HashSet();
551
552 /**
553 * Set of IntentSenderRecord objects that are currently active.
554 */
555 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
556 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
557
558 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800559 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700560 * already logged DropBox entries for. Guarded by itself. If
561 * something (rogue user app) forces this over
562 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
563 */
564 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
565 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
566
567 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700568 * Strict Mode background batched logging state.
569 *
570 * The string buffer is guarded by itself, and its lock is also
571 * used to determine if another batched write is already
572 * in-flight.
573 */
574 private final StringBuilder mStrictModeBuffer = new StringBuilder();
575
576 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700577 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
578 */
579 private boolean mPendingBroadcastTimeoutMessage;
580
581 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 * Intent broadcast that we have tried to start, but are
583 * waiting for its application's process to be created. We only
584 * need one (instead of a list) because we always process broadcasts
585 * one at a time, so no others can be started while waiting for this
586 * one.
587 */
588 BroadcastRecord mPendingBroadcast = null;
589
590 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700591 * The receiver index that is pending, to restart the broadcast if needed.
592 */
593 int mPendingBroadcastRecvIndex;
594
595 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 * Keeps track of all IIntentReceivers that have been registered for
597 * broadcasts. Hash keys are the receiver IBinder, hash value is
598 * a ReceiverList.
599 */
600 final HashMap mRegisteredReceivers = new HashMap();
601
602 /**
603 * Resolver for broadcast intents to registered receivers.
604 * Holds BroadcastFilter (subclass of IntentFilter).
605 */
606 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
607 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
608 @Override
609 protected boolean allowFilterResult(
610 BroadcastFilter filter, List<BroadcastFilter> dest) {
611 IBinder target = filter.receiverList.receiver.asBinder();
612 for (int i=dest.size()-1; i>=0; i--) {
613 if (dest.get(i).receiverList.receiver.asBinder() == target) {
614 return false;
615 }
616 }
617 return true;
618 }
619 };
620
621 /**
622 * State of all active sticky broadcasts. Keys are the action of the
623 * sticky Intent, values are an ArrayList of all broadcasted intents with
624 * that action (which should usually be one).
625 */
626 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
627 new HashMap<String, ArrayList<Intent>>();
628
629 /**
630 * All currently running services.
631 */
632 final HashMap<ComponentName, ServiceRecord> mServices =
633 new HashMap<ComponentName, ServiceRecord>();
634
635 /**
636 * All currently running services indexed by the Intent used to start them.
637 */
638 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
639 new HashMap<Intent.FilterComparison, ServiceRecord>();
640
641 /**
642 * All currently bound service connections. Keys are the IBinder of
643 * the client's IServiceConnection.
644 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700645 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
646 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647
648 /**
649 * List of services that we have been asked to start,
650 * but haven't yet been able to. It is used to hold start requests
651 * while waiting for their corresponding application thread to get
652 * going.
653 */
654 final ArrayList<ServiceRecord> mPendingServices
655 = new ArrayList<ServiceRecord>();
656
657 /**
658 * List of services that are scheduled to restart following a crash.
659 */
660 final ArrayList<ServiceRecord> mRestartingServices
661 = new ArrayList<ServiceRecord>();
662
663 /**
664 * List of services that are in the process of being stopped.
665 */
666 final ArrayList<ServiceRecord> mStoppingServices
667 = new ArrayList<ServiceRecord>();
668
669 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700670 * Backup/restore process management
671 */
672 String mBackupAppName = null;
673 BackupRecord mBackupTarget = null;
674
675 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 * List of PendingThumbnailsRecord objects of clients who are still
677 * waiting to receive all of the thumbnails for a task.
678 */
679 final ArrayList mPendingThumbnails = new ArrayList();
680
681 /**
682 * List of HistoryRecord objects that have been finished and must
683 * still report back to a pending thumbnail receiver.
684 */
685 final ArrayList mCancelledThumbnails = new ArrayList();
686
687 /**
688 * All of the currently running global content providers. Keys are a
689 * string containing the provider name and values are a
690 * ContentProviderRecord object containing the data about it. Note
691 * that a single provider may be published under multiple names, so
692 * there may be multiple entries here for a single one in mProvidersByClass.
693 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700694 final HashMap<String, ContentProviderRecord> mProvidersByName
695 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696
697 /**
698 * All of the currently running global content providers. Keys are a
699 * string containing the provider's implementation class and values are a
700 * ContentProviderRecord object containing the data about it.
701 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700702 final HashMap<String, ContentProviderRecord> mProvidersByClass
703 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 /**
706 * List of content providers who have clients waiting for them. The
707 * application is currently being launched and the provider will be
708 * removed from this list once it is published.
709 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700710 final ArrayList<ContentProviderRecord> mLaunchingProviders
711 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
713 /**
714 * Global set of specific Uri permissions that have been granted.
715 */
716 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
717 = new SparseArray<HashMap<Uri, UriPermission>>();
718
719 /**
720 * Thread-local storage used to carry caller permissions over through
721 * indirect content-provider access.
722 * @see #ActivityManagerService.openContentUri()
723 */
724 private class Identity {
725 public int pid;
726 public int uid;
727
728 Identity(int _pid, int _uid) {
729 pid = _pid;
730 uid = _uid;
731 }
732 }
733 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
734
735 /**
736 * All information we have collected about the runtime performance of
737 * any user id that can impact battery performance.
738 */
739 final BatteryStatsService mBatteryStatsService;
740
741 /**
742 * information about component usage
743 */
744 final UsageStatsService mUsageStatsService;
745
746 /**
747 * Current configuration information. HistoryRecord objects are given
748 * a reference to this object to indicate which configuration they are
749 * currently running in, so this object must be kept immutable.
750 */
751 Configuration mConfiguration = new Configuration();
752
753 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800754 * Current sequencing integer of the configuration, for skipping old
755 * configurations.
756 */
757 int mConfigurationSeq = 0;
758
759 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700760 * Hardware-reported OpenGLES version.
761 */
762 final int GL_ES_VERSION;
763
764 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 * List of initialization arguments to pass to all processes when binding applications to them.
766 * For example, references to the commonly used services.
767 */
768 HashMap<String, IBinder> mAppBindArgs;
769
770 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700771 * Temporary to avoid allocations. Protected by main lock.
772 */
773 final StringBuilder mStringBuilder = new StringBuilder(256);
774
775 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 * Used to control how we initialize the service.
777 */
778 boolean mStartRunning = false;
779 ComponentName mTopComponent;
780 String mTopAction;
781 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700782 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 boolean mSystemReady = false;
784 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700785 boolean mWaitingUpdate = false;
786 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700787 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700788 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789
790 Context mContext;
791
792 int mFactoryTest;
793
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700794 boolean mCheckedForSetup;
795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700797 * The time at which we will allow normal application switches again,
798 * after a call to {@link #stopAppSwitches()}.
799 */
800 long mAppSwitchesAllowedTime;
801
802 /**
803 * This is set to true after the first switch after mAppSwitchesAllowedTime
804 * is set; any switches after that will clear the time.
805 */
806 boolean mDidAppSwitch;
807
808 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700810 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700811 long mLastPowerCheckRealtime;
812
813 /**
814 * Last time (in uptime) at which we checked for power usage.
815 */
816 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700817
818 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 * Set while we are wanting to sleep, to prevent any
820 * activities from being started/resumed.
821 */
822 boolean mSleeping = false;
823
824 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700825 * Set if we are shutting down the system, similar to sleeping.
826 */
827 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828
829 /**
830 * Task identifier that activities are currently being started
831 * in. Incremented each time a new task is created.
832 * todo: Replace this with a TokenSpace class that generates non-repeating
833 * integers that won't wrap.
834 */
835 int mCurTask = 1;
836
837 /**
838 * Current sequence id for oom_adj computation traversal.
839 */
840 int mAdjSeq = 0;
841
842 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700843 * Current sequence id for process LRU updating.
844 */
845 int mLruSeq = 0;
846
847 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
849 * is set, indicating the user wants processes started in such a way
850 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
851 * running in each process (thus no pre-initialized process, etc).
852 */
853 boolean mSimpleProcessManagement = false;
854
855 /**
856 * System monitoring: number of processes that died since the last
857 * N procs were started.
858 */
859 int[] mProcDeaths = new int[20];
860
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700861 /**
862 * This is set if we had to do a delayed dexopt of an app before launching
863 * it, to increasing the ANR timeouts in that case.
864 */
865 boolean mDidDexOpt;
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 String mDebugApp = null;
868 boolean mWaitForDebugger = false;
869 boolean mDebugTransient = false;
870 String mOrigDebugApp = null;
871 boolean mOrigWaitForDebugger = false;
872 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700875 final RemoteCallbackList<IActivityWatcher> mWatchers
876 = new RemoteCallbackList<IActivityWatcher>();
877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 /**
879 * Callback of last caller to {@link #requestPss}.
880 */
881 Runnable mRequestPssCallback;
882
883 /**
884 * Remaining processes for which we are waiting results from the last
885 * call to {@link #requestPss}.
886 */
887 final ArrayList<ProcessRecord> mRequestPssList
888 = new ArrayList<ProcessRecord>();
889
890 /**
891 * Runtime statistics collection thread. This object's lock is used to
892 * protect all related state.
893 */
894 final Thread mProcessStatsThread;
895
896 /**
897 * Used to collect process stats when showing not responding dialog.
898 * Protected by mProcessStatsThread.
899 */
900 final ProcessStats mProcessStats = new ProcessStats(
901 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700902 final AtomicLong mLastCpuTime = new AtomicLong(0);
903 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 long mLastWriteTime = 0;
906
907 /**
908 * Set to true after the system has finished booting.
909 */
910 boolean mBooted = false;
911
912 int mProcessLimit = 0;
913
914 WindowManagerService mWindowManager;
915
916 static ActivityManagerService mSelf;
917 static ActivityThread mSystemThread;
918
919 private final class AppDeathRecipient implements IBinder.DeathRecipient {
920 final ProcessRecord mApp;
921 final int mPid;
922 final IApplicationThread mAppThread;
923
924 AppDeathRecipient(ProcessRecord app, int pid,
925 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800926 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 TAG, "New death recipient " + this
928 + " for thread " + thread.asBinder());
929 mApp = app;
930 mPid = pid;
931 mAppThread = thread;
932 }
933
934 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800935 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 TAG, "Death received in " + this
937 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 synchronized(ActivityManagerService.this) {
939 appDiedLocked(mApp, mPid, mAppThread);
940 }
941 }
942 }
943
944 static final int SHOW_ERROR_MSG = 1;
945 static final int SHOW_NOT_RESPONDING_MSG = 2;
946 static final int SHOW_FACTORY_ERROR_MSG = 3;
947 static final int UPDATE_CONFIGURATION_MSG = 4;
948 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
949 static final int WAIT_FOR_DEBUGGER_MSG = 6;
950 static final int BROADCAST_INTENT_MSG = 7;
951 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 static final int SERVICE_TIMEOUT_MSG = 12;
953 static final int UPDATE_TIME_ZONE = 13;
954 static final int SHOW_UID_ERROR_MSG = 14;
955 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700957 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700958 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800959 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700960 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
961 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700962 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700963 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700964 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700965 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966
967 AlertDialog mUidAlert;
968
969 final Handler mHandler = new Handler() {
970 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800971 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 //}
973
974 public void handleMessage(Message msg) {
975 switch (msg.what) {
976 case SHOW_ERROR_MSG: {
977 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 synchronized (ActivityManagerService.this) {
979 ProcessRecord proc = (ProcessRecord)data.get("app");
980 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800981 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 return;
983 }
984 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700985 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800986 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 d.show();
988 proc.crashDialog = d;
989 } else {
990 // The device is asleep, so just pretend that the user
991 // saw a crash dialog and hit "force quit".
992 res.set(0);
993 }
994 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700995
996 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 } break;
998 case SHOW_NOT_RESPONDING_MSG: {
999 synchronized (ActivityManagerService.this) {
1000 HashMap data = (HashMap) msg.obj;
1001 ProcessRecord proc = (ProcessRecord)data.get("app");
1002 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001003 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 return;
1005 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001006
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001007 Intent intent = new Intent("android.intent.action.ANR");
1008 if (!mProcessesReady) {
1009 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1010 }
1011 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001012 null, null, 0, null, null, null,
1013 false, false, MY_PID, Process.SYSTEM_UID);
1014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001016 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 d.show();
1018 proc.anrDialog = d;
1019 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001020
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001021 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001023 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1024 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1025 synchronized (ActivityManagerService.this) {
1026 ProcessRecord proc = (ProcessRecord) data.get("app");
1027 if (proc == null) {
1028 Slog.e(TAG, "App not found when showing strict mode dialog.");
1029 break;
1030 }
1031 if (proc.crashDialog != null) {
1032 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1033 return;
1034 }
1035 AppErrorResult res = (AppErrorResult) data.get("result");
1036 if (!mSleeping && !mShuttingDown) {
1037 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1038 d.show();
1039 proc.crashDialog = d;
1040 } else {
1041 // The device is asleep, so just pretend that the user
1042 // saw a crash dialog and hit "force quit".
1043 res.set(0);
1044 }
1045 }
1046 ensureBootCompleted();
1047 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 case SHOW_FACTORY_ERROR_MSG: {
1049 Dialog d = new FactoryErrorDialog(
1050 mContext, msg.getData().getCharSequence("msg"));
1051 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001052 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 } break;
1054 case UPDATE_CONFIGURATION_MSG: {
1055 final ContentResolver resolver = mContext.getContentResolver();
1056 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1057 } break;
1058 case GC_BACKGROUND_PROCESSES_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 performAppGcsIfAppropriateLocked();
1061 }
1062 } break;
1063 case WAIT_FOR_DEBUGGER_MSG: {
1064 synchronized (ActivityManagerService.this) {
1065 ProcessRecord app = (ProcessRecord)msg.obj;
1066 if (msg.arg1 != 0) {
1067 if (!app.waitedForDebugger) {
1068 Dialog d = new AppWaitingForDebuggerDialog(
1069 ActivityManagerService.this,
1070 mContext, app);
1071 app.waitDialog = d;
1072 app.waitedForDebugger = true;
1073 d.show();
1074 }
1075 } else {
1076 if (app.waitDialog != null) {
1077 app.waitDialog.dismiss();
1078 app.waitDialog = null;
1079 }
1080 }
1081 }
1082 } break;
1083 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001084 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 TAG, "Received BROADCAST_INTENT_MSG");
1086 processNextBroadcast(true);
1087 } break;
1088 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001089 synchronized (ActivityManagerService.this) {
1090 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001094 if (mDidDexOpt) {
1095 mDidDexOpt = false;
1096 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1097 nmsg.obj = msg.obj;
1098 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1099 return;
1100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 serviceTimeout((ProcessRecord)msg.obj);
1102 } break;
1103 case UPDATE_TIME_ZONE: {
1104 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001105 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1106 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 if (r.thread != null) {
1108 try {
1109 r.thread.updateTimeZone();
1110 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001111 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 }
1113 }
1114 }
1115 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001116 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001117 case CLEAR_DNS_CACHE: {
1118 synchronized (ActivityManagerService.this) {
1119 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1120 ProcessRecord r = mLruProcesses.get(i);
1121 if (r.thread != null) {
1122 try {
1123 r.thread.clearDnsCache();
1124 } catch (RemoteException ex) {
1125 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1126 }
1127 }
1128 }
1129 }
1130 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001131 case UPDATE_HTTP_PROXY: {
1132 ProxyProperties proxy = (ProxyProperties)msg.obj;
1133 String host = "";
1134 String port = "";
1135 String exclList = "";
1136 if (proxy != null) {
1137 host = proxy.getHost();
1138 port = Integer.toString(proxy.getPort());
1139 exclList = proxy.getExclusionList();
1140 }
1141 synchronized (ActivityManagerService.this) {
1142 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1143 ProcessRecord r = mLruProcesses.get(i);
1144 if (r.thread != null) {
1145 try {
1146 r.thread.setHttpProxy(host, port, exclList);
1147 } catch (RemoteException ex) {
1148 Slog.w(TAG, "Failed to update http proxy for: " +
1149 r.info.processName);
1150 }
1151 }
1152 }
1153 }
1154 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 case SHOW_UID_ERROR_MSG: {
1156 // XXX This is a temporary dialog, no need to localize.
1157 AlertDialog d = new BaseErrorDialog(mContext);
1158 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1159 d.setCancelable(false);
1160 d.setTitle("System UIDs Inconsistent");
1161 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 +02001162 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1164 mUidAlert = d;
1165 d.show();
1166 } break;
1167 case IM_FEELING_LUCKY_MSG: {
1168 if (mUidAlert != null) {
1169 mUidAlert.dismiss();
1170 mUidAlert = null;
1171 }
1172 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001174 if (mDidDexOpt) {
1175 mDidDexOpt = false;
1176 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1177 nmsg.obj = msg.obj;
1178 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1179 return;
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 ProcessRecord app = (ProcessRecord)msg.obj;
1182 synchronized (ActivityManagerService.this) {
1183 processStartTimedOutLocked(app);
1184 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001185 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001186 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1187 synchronized (ActivityManagerService.this) {
1188 doPendingActivityLaunchesLocked(true);
1189 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001190 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001191 case KILL_APPLICATION_MSG: {
1192 synchronized (ActivityManagerService.this) {
1193 int uid = msg.arg1;
1194 boolean restart = (msg.arg2 == 1);
1195 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001196 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001197 }
1198 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001199 case FINALIZE_PENDING_INTENT_MSG: {
1200 ((PendingIntentRecord)msg.obj).completeFinalize();
1201 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001202 case POST_HEAVY_NOTIFICATION_MSG: {
1203 INotificationManager inm = NotificationManager.getService();
1204 if (inm == null) {
1205 return;
1206 }
1207
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001208 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001209 ProcessRecord process = root.app;
1210 if (process == null) {
1211 return;
1212 }
1213
1214 try {
1215 Context context = mContext.createPackageContext(process.info.packageName, 0);
1216 String text = mContext.getString(R.string.heavy_weight_notification,
1217 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1218 Notification notification = new Notification();
1219 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1220 notification.when = 0;
1221 notification.flags = Notification.FLAG_ONGOING_EVENT;
1222 notification.tickerText = text;
1223 notification.defaults = 0; // please be quiet
1224 notification.sound = null;
1225 notification.vibrate = null;
1226 notification.setLatestEventInfo(context, text,
1227 mContext.getText(R.string.heavy_weight_notification_detail),
1228 PendingIntent.getActivity(mContext, 0, root.intent,
1229 PendingIntent.FLAG_CANCEL_CURRENT));
1230
1231 try {
1232 int[] outId = new int[1];
1233 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1234 notification, outId);
1235 } catch (RuntimeException e) {
1236 Slog.w(ActivityManagerService.TAG,
1237 "Error showing notification for heavy-weight app", e);
1238 } catch (RemoteException e) {
1239 }
1240 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001241 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001242 }
1243 } break;
1244 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1245 INotificationManager inm = NotificationManager.getService();
1246 if (inm == null) {
1247 return;
1248 }
1249 try {
1250 inm.cancelNotification("android",
1251 R.string.heavy_weight_notification);
1252 } catch (RuntimeException e) {
1253 Slog.w(ActivityManagerService.TAG,
1254 "Error canceling notification for service", e);
1255 } catch (RemoteException e) {
1256 }
1257 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001258 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1259 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001260 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001261 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001262 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1263 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001264 }
1265 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 }
1267 }
1268 };
1269
1270 public static void setSystemProcess() {
1271 try {
1272 ActivityManagerService m = mSelf;
1273
1274 ServiceManager.addService("activity", m);
1275 ServiceManager.addService("meminfo", new MemBinder(m));
1276 if (MONITOR_CPU_USAGE) {
1277 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 ServiceManager.addService("permission", new PermissionController(m));
1280
1281 ApplicationInfo info =
1282 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001283 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001284 mSystemThread.installSystemApplicationInfo(info);
1285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 synchronized (mSelf) {
1287 ProcessRecord app = mSelf.newProcessRecordLocked(
1288 mSystemThread.getApplicationThread(), info,
1289 info.processName);
1290 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001291 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 app.maxAdj = SYSTEM_ADJ;
1293 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1294 synchronized (mSelf.mPidsSelfLocked) {
1295 mSelf.mPidsSelfLocked.put(app.pid, app);
1296 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001297 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 }
1299 } catch (PackageManager.NameNotFoundException e) {
1300 throw new RuntimeException(
1301 "Unable to find android system package", e);
1302 }
1303 }
1304
1305 public void setWindowManager(WindowManagerService wm) {
1306 mWindowManager = wm;
1307 }
1308
1309 public static final Context main(int factoryTest) {
1310 AThread thr = new AThread();
1311 thr.start();
1312
1313 synchronized (thr) {
1314 while (thr.mService == null) {
1315 try {
1316 thr.wait();
1317 } catch (InterruptedException e) {
1318 }
1319 }
1320 }
1321
1322 ActivityManagerService m = thr.mService;
1323 mSelf = m;
1324 ActivityThread at = ActivityThread.systemMain();
1325 mSystemThread = at;
1326 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001327 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 m.mContext = context;
1329 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001330 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331
1332 m.mBatteryStatsService.publish(context);
1333 m.mUsageStatsService.publish(context);
1334
1335 synchronized (thr) {
1336 thr.mReady = true;
1337 thr.notifyAll();
1338 }
1339
1340 m.startRunning(null, null, null, null);
1341
1342 return context;
1343 }
1344
1345 public static ActivityManagerService self() {
1346 return mSelf;
1347 }
1348
1349 static class AThread extends Thread {
1350 ActivityManagerService mService;
1351 boolean mReady = false;
1352
1353 public AThread() {
1354 super("ActivityManager");
1355 }
1356
1357 public void run() {
1358 Looper.prepare();
1359
1360 android.os.Process.setThreadPriority(
1361 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001362 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363
1364 ActivityManagerService m = new ActivityManagerService();
1365
1366 synchronized (this) {
1367 mService = m;
1368 notifyAll();
1369 }
1370
1371 synchronized (this) {
1372 while (!mReady) {
1373 try {
1374 wait();
1375 } catch (InterruptedException e) {
1376 }
1377 }
1378 }
1379
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001380 // For debug builds, log event loop stalls to dropbox for analysis.
1381 if (StrictMode.conditionallyEnableDebugLogging()) {
1382 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1383 }
1384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 Looper.loop();
1386 }
1387 }
1388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 static class MemBinder extends Binder {
1390 ActivityManagerService mActivityManagerService;
1391 MemBinder(ActivityManagerService activityManagerService) {
1392 mActivityManagerService = activityManagerService;
1393 }
1394
1395 @Override
1396 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1397 ActivityManagerService service = mActivityManagerService;
1398 ArrayList<ProcessRecord> procs;
1399 synchronized (mActivityManagerService) {
1400 if (args != null && args.length > 0
1401 && args[0].charAt(0) != '-') {
1402 procs = new ArrayList<ProcessRecord>();
1403 int pid = -1;
1404 try {
1405 pid = Integer.parseInt(args[0]);
1406 } catch (NumberFormatException e) {
1407
1408 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001409 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1410 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 if (proc.pid == pid) {
1412 procs.add(proc);
1413 } else if (proc.processName.equals(args[0])) {
1414 procs.add(proc);
1415 }
1416 }
1417 if (procs.size() <= 0) {
1418 pw.println("No process found for: " + args[0]);
1419 return;
1420 }
1421 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001422 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1426 }
1427 }
1428
1429 static class CpuBinder extends Binder {
1430 ActivityManagerService mActivityManagerService;
1431 CpuBinder(ActivityManagerService activityManagerService) {
1432 mActivityManagerService = activityManagerService;
1433 }
1434
1435 @Override
1436 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1437 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001438 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1439 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1440 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 }
1442 }
1443 }
1444
1445 private ActivityManagerService() {
1446 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1447 if (v != null && Integer.getInteger(v) != 0) {
1448 mSimpleProcessManagement = true;
1449 }
1450 v = System.getenv("ANDROID_DEBUG_APP");
1451 if (v != null) {
1452 mSimpleProcessManagement = true;
1453 }
1454
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 File dataDir = Environment.getDataDirectory();
1458 File systemDir = new File(dataDir, "system");
1459 systemDir.mkdirs();
1460 mBatteryStatsService = new BatteryStatsService(new File(
1461 systemDir, "batterystats.bin").toString());
1462 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001463 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001464 mOnBattery = DEBUG_POWER ? true
1465 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001466 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001468 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001469 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Jack Palevichb90d28c2009-07-22 15:35:24 -07001471 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1472 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1473
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001474 mConfiguration.setToDefaults();
1475 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 mProcessStats.init();
1477
1478 // Add ourself to the Watchdog monitors.
1479 Watchdog.getInstance().addMonitor(this);
1480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 mProcessStatsThread = new Thread("ProcessStats") {
1482 public void run() {
1483 while (true) {
1484 try {
1485 try {
1486 synchronized(this) {
1487 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001488 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 // + ", write delay=" + nextWriteDelay);
1492 if (nextWriteDelay < nextCpuDelay) {
1493 nextCpuDelay = nextWriteDelay;
1494 }
1495 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001496 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 this.wait(nextCpuDelay);
1498 }
1499 }
1500 } catch (InterruptedException e) {
1501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 updateCpuStatsNow();
1503 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001504 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
1506 }
1507 }
1508 };
1509 mProcessStatsThread.start();
1510 }
1511
1512 @Override
1513 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1514 throws RemoteException {
1515 try {
1516 return super.onTransact(code, data, reply, flags);
1517 } catch (RuntimeException e) {
1518 // The activity manager only throws security exceptions, so let's
1519 // log all others.
1520 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 }
1523 throw e;
1524 }
1525 }
1526
1527 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001528 final long now = SystemClock.uptimeMillis();
1529 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1530 return;
1531 }
1532 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1533 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 mProcessStatsThread.notify();
1535 }
1536 }
1537 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 void updateCpuStatsNow() {
1540 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001541 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 final long now = SystemClock.uptimeMillis();
1543 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001546 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1547 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 haveNewCpuStats = true;
1549 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001550 //Slog.i(TAG, mProcessStats.printCurrentState());
1551 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 // + mProcessStats.getTotalCpuPercent() + "%");
1553
Joe Onorato8a9b2202010-02-26 18:56:32 -08001554 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 if ("true".equals(SystemProperties.get("events.cpu"))) {
1556 int user = mProcessStats.getLastUserTime();
1557 int system = mProcessStats.getLastSystemTime();
1558 int iowait = mProcessStats.getLastIoWaitTime();
1559 int irq = mProcessStats.getLastIrqTime();
1560 int softIrq = mProcessStats.getLastSoftIrqTime();
1561 int idle = mProcessStats.getLastIdleTime();
1562
1563 int total = user + system + iowait + irq + softIrq + idle;
1564 if (total == 0) total = 1;
1565
Doug Zongker2bec3d42009-12-04 12:52:44 -08001566 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 ((user+system+iowait+irq+softIrq) * 100) / total,
1568 (user * 100) / total,
1569 (system * 100) / total,
1570 (iowait * 100) / total,
1571 (irq * 100) / total,
1572 (softIrq * 100) / total);
1573 }
1574 }
1575
Amith Yamasanie43530a2009-08-21 13:11:37 -07001576 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001577 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001578 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 synchronized(mPidsSelfLocked) {
1580 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001581 if (mOnBattery) {
1582 int perc = bstats.startAddingCpuLocked();
1583 int totalUTime = 0;
1584 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001585 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001587 ProcessStats.Stats st = mProcessStats.getStats(i);
1588 if (!st.working) {
1589 continue;
1590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001592 int otherUTime = (st.rel_utime*perc)/100;
1593 int otherSTime = (st.rel_stime*perc)/100;
1594 totalUTime += otherUTime;
1595 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 if (pr != null) {
1597 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1599 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001600 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001601 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001602 } else {
1603 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001604 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001606 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1607 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001608 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 }
1611 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001612 bstats.finishAddingCpuLocked(perc, totalUTime,
1613 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
1615 }
1616 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1619 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001620 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 }
1622 }
1623 }
1624 }
1625
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001626 @Override
1627 public void batteryNeedsCpuUpdate() {
1628 updateCpuStatsNow();
1629 }
1630
1631 @Override
1632 public void batteryPowerChanged(boolean onBattery) {
1633 // When plugging in, update the CPU stats first before changing
1634 // the plug state.
1635 updateCpuStatsNow();
1636 synchronized (this) {
1637 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001638 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001639 }
1640 }
1641 }
1642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 /**
1644 * Initialize the application bind args. These are passed to each
1645 * process when the bindApplication() IPC is sent to the process. They're
1646 * lazily setup to make sure the services are running when they're asked for.
1647 */
1648 private HashMap<String, IBinder> getCommonServicesLocked() {
1649 if (mAppBindArgs == null) {
1650 mAppBindArgs = new HashMap<String, IBinder>();
1651
1652 // Setup the application init args
1653 mAppBindArgs.put("package", ServiceManager.getService("package"));
1654 mAppBindArgs.put("window", ServiceManager.getService("window"));
1655 mAppBindArgs.put(Context.ALARM_SERVICE,
1656 ServiceManager.getService(Context.ALARM_SERVICE));
1657 }
1658 return mAppBindArgs;
1659 }
1660
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001661 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 if (mFocusedActivity != r) {
1663 mFocusedActivity = r;
1664 mWindowManager.setFocusedApp(r, true);
1665 }
1666 }
1667
Dianne Hackborn906497c2010-05-10 15:57:38 -07001668 private final void updateLruProcessInternalLocked(ProcessRecord app,
1669 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001671 int lrui = mLruProcesses.indexOf(app);
1672 if (lrui >= 0) mLruProcesses.remove(lrui);
1673
1674 int i = mLruProcesses.size()-1;
1675 int skipTop = 0;
1676
Dianne Hackborn906497c2010-05-10 15:57:38 -07001677 app.lruSeq = mLruSeq;
1678
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001679 // compute the new weight for this process.
1680 if (updateActivityTime) {
1681 app.lastActivityTime = SystemClock.uptimeMillis();
1682 }
1683 if (app.activities.size() > 0) {
1684 // If this process has activities, we more strongly want to keep
1685 // it around.
1686 app.lruWeight = app.lastActivityTime;
1687 } else if (app.pubProviders.size() > 0) {
1688 // If this process contains content providers, we want to keep
1689 // it a little more strongly.
1690 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1691 // Also don't let it kick out the first few "real" hidden processes.
1692 skipTop = MIN_HIDDEN_APPS;
1693 } else {
1694 // If this process doesn't have activities, we less strongly
1695 // want to keep it around, and generally want to avoid getting
1696 // in front of any very recently used activities.
1697 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1698 // Also don't let it kick out the first few "real" hidden processes.
1699 skipTop = MIN_HIDDEN_APPS;
1700 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001701
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001702 while (i >= 0) {
1703 ProcessRecord p = mLruProcesses.get(i);
1704 // If this app shouldn't be in front of the first N background
1705 // apps, then skip over that many that are currently hidden.
1706 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1707 skipTop--;
1708 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001709 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001710 mLruProcesses.add(i+1, app);
1711 break;
1712 }
1713 i--;
1714 }
1715 if (i < 0) {
1716 mLruProcesses.add(0, app);
1717 }
1718
Dianne Hackborn906497c2010-05-10 15:57:38 -07001719 // If the app is currently using a content provider or service,
1720 // bump those processes as well.
1721 if (app.connections.size() > 0) {
1722 for (ConnectionRecord cr : app.connections) {
1723 if (cr.binding != null && cr.binding.service != null
1724 && cr.binding.service.app != null
1725 && cr.binding.service.app.lruSeq != mLruSeq) {
1726 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1727 updateActivityTime, i+1);
1728 }
1729 }
1730 }
1731 if (app.conProviders.size() > 0) {
1732 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1733 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1734 updateLruProcessInternalLocked(cpr.app, oomAdj,
1735 updateActivityTime, i+1);
1736 }
1737 }
1738 }
1739
Joe Onorato8a9b2202010-02-26 18:56:32 -08001740 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 if (oomAdj) {
1742 updateOomAdjLocked();
1743 }
1744 }
1745
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001746 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001747 boolean oomAdj, boolean updateActivityTime) {
1748 mLruSeq++;
1749 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1750 }
1751
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001752 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 String processName, int uid) {
1754 if (uid == Process.SYSTEM_UID) {
1755 // The system gets to run in any process. If there are multiple
1756 // processes with the same uid, just pick the first (this
1757 // should never happen).
1758 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1759 processName);
1760 return procs != null ? procs.valueAt(0) : null;
1761 }
1762 ProcessRecord proc = mProcessNames.get(processName, uid);
1763 return proc;
1764 }
1765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001766 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001767 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001768 try {
1769 if (pm.performDexOpt(packageName)) {
1770 mDidDexOpt = true;
1771 }
1772 } catch (RemoteException e) {
1773 }
1774 }
1775
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001776 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 int transit = mWindowManager.getPendingAppTransition();
1778 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1779 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1780 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1781 }
1782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001783 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001785 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1787 // We don't have to do anything more if:
1788 // (1) There is an existing application record; and
1789 // (2) The caller doesn't think it is dead, OR there is no thread
1790 // object attached to it so we know it couldn't have crashed; and
1791 // (3) There is a pid assigned to it, so it is either starting or
1792 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001793 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 + " app=" + app + " knownToBeDead=" + knownToBeDead
1795 + " thread=" + (app != null ? app.thread : null)
1796 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001797 if (app != null && app.pid > 0) {
1798 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001799 // We already have the app running, or are waiting for it to
1800 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001802 return app;
1803 } else {
1804 // An application record is attached to a previous process,
1805 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001806 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001807 handleAppDiedLocked(app, true);
1808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 String hostingNameStr = hostingName != null
1812 ? hostingName.flattenToShortString() : null;
1813
1814 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1815 // If we are in the background, then check to see if this process
1816 // is bad. If so, we will just silently fail.
1817 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001818 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1819 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 return null;
1821 }
1822 } else {
1823 // When the user is explicitly starting a process, then clear its
1824 // crash count so that we won't make it bad until they see at
1825 // least one crash dialog again, and make the process good again
1826 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001827 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1828 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 mProcessCrashTimes.remove(info.processName, info.uid);
1830 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001831 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 info.processName);
1833 mBadProcesses.remove(info.processName, info.uid);
1834 if (app != null) {
1835 app.bad = false;
1836 }
1837 }
1838 }
1839
1840 if (app == null) {
1841 app = newProcessRecordLocked(null, info, processName);
1842 mProcessNames.put(processName, info.uid, app);
1843 } else {
1844 // If this is a new package in the process, add the package to the list
1845 app.addPackage(info.packageName);
1846 }
1847
1848 // If the system is not ready yet, then hold off on starting this
1849 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001850 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001851 && !isAllowedWhileBooting(info)
1852 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 if (!mProcessesOnHold.contains(app)) {
1854 mProcessesOnHold.add(app);
1855 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001856 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 return app;
1858 }
1859
1860 startProcessLocked(app, hostingType, hostingNameStr);
1861 return (app.pid != 0) ? app : null;
1862 }
1863
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001864 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1865 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1866 }
1867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 private final void startProcessLocked(ProcessRecord app,
1869 String hostingType, String hostingNameStr) {
1870 if (app.pid > 0 && app.pid != MY_PID) {
1871 synchronized (mPidsSelfLocked) {
1872 mPidsSelfLocked.remove(app.pid);
1873 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1874 }
1875 app.pid = 0;
1876 }
1877
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001878 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1879 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 mProcessesOnHold.remove(app);
1881
1882 updateCpuStats();
1883
1884 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1885 mProcDeaths[0] = 0;
1886
1887 try {
1888 int uid = app.info.uid;
1889 int[] gids = null;
1890 try {
1891 gids = mContext.getPackageManager().getPackageGids(
1892 app.info.packageName);
1893 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
1896 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1897 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1898 && mTopComponent != null
1899 && app.processName.equals(mTopComponent.getPackageName())) {
1900 uid = 0;
1901 }
1902 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1903 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1904 uid = 0;
1905 }
1906 }
1907 int debugFlags = 0;
1908 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1909 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1910 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001911 // Run the app in safe mode if its manifest requests so or the
1912 // system is booted in safe mode.
1913 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1914 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001915 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1918 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1919 }
1920 if ("1".equals(SystemProperties.get("debug.assert"))) {
1921 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1922 }
1923 int pid = Process.start("android.app.ActivityThread",
1924 mSimpleProcessManagement ? app.processName : null, uid, uid,
1925 gids, debugFlags, null);
1926 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1927 synchronized (bs) {
1928 if (bs.isOnBattery()) {
1929 app.batteryStats.incStartsLocked();
1930 }
1931 }
1932
Doug Zongker2bec3d42009-12-04 12:52:44 -08001933 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 app.processName, hostingType,
1935 hostingNameStr != null ? hostingNameStr : "");
1936
1937 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001938 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001941 StringBuilder buf = mStringBuilder;
1942 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 buf.append("Start proc ");
1944 buf.append(app.processName);
1945 buf.append(" for ");
1946 buf.append(hostingType);
1947 if (hostingNameStr != null) {
1948 buf.append(" ");
1949 buf.append(hostingNameStr);
1950 }
1951 buf.append(": pid=");
1952 buf.append(pid);
1953 buf.append(" uid=");
1954 buf.append(uid);
1955 buf.append(" gids={");
1956 if (gids != null) {
1957 for (int gi=0; gi<gids.length; gi++) {
1958 if (gi != 0) buf.append(", ");
1959 buf.append(gids[gi]);
1960
1961 }
1962 }
1963 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001964 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 if (pid == 0 || pid == MY_PID) {
1966 // Processes are being emulated with threads.
1967 app.pid = MY_PID;
1968 app.removed = false;
1969 mStartingProcesses.add(app);
1970 } else if (pid > 0) {
1971 app.pid = pid;
1972 app.removed = false;
1973 synchronized (mPidsSelfLocked) {
1974 this.mPidsSelfLocked.put(pid, app);
1975 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1976 msg.obj = app;
1977 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1978 }
1979 } else {
1980 app.pid = 0;
1981 RuntimeException e = new RuntimeException(
1982 "Failure starting process " + app.processName
1983 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001984 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986 } catch (RuntimeException e) {
1987 // XXX do better error recovery.
1988 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001989 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 }
1991 }
1992
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 if (resumed) {
1995 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1996 } else {
1997 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1998 }
1999 }
2000
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002002 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2003 && mTopAction == null) {
2004 // We are running in factory test mode, but unable to find
2005 // the factory test app, so just sit around displaying the
2006 // error message and don't try to start anything.
2007 return false;
2008 }
2009 Intent intent = new Intent(
2010 mTopAction,
2011 mTopData != null ? Uri.parse(mTopData) : null);
2012 intent.setComponent(mTopComponent);
2013 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2014 intent.addCategory(Intent.CATEGORY_HOME);
2015 }
2016 ActivityInfo aInfo =
2017 intent.resolveActivityInfo(mContext.getPackageManager(),
2018 STOCK_PM_FLAGS);
2019 if (aInfo != null) {
2020 intent.setComponent(new ComponentName(
2021 aInfo.applicationInfo.packageName, aInfo.name));
2022 // Don't do this if the home app is currently being
2023 // instrumented.
2024 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2025 aInfo.applicationInfo.uid);
2026 if (app == null || app.instrumentationClass == null) {
2027 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002029 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002030 }
2031 }
2032
2033
2034 return true;
2035 }
2036
2037 /**
2038 * Starts the "new version setup screen" if appropriate.
2039 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002041 // Only do this once per boot.
2042 if (mCheckedForSetup) {
2043 return;
2044 }
2045
2046 // We will show this screen if the current one is a different
2047 // version than the last one shown, and we are not running in
2048 // low-level factory test mode.
2049 final ContentResolver resolver = mContext.getContentResolver();
2050 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2051 Settings.Secure.getInt(resolver,
2052 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2053 mCheckedForSetup = true;
2054
2055 // See if we should be showing the platform update setup UI.
2056 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2057 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2058 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2059
2060 // We don't allow third party apps to replace this.
2061 ResolveInfo ri = null;
2062 for (int i=0; ris != null && i<ris.size(); i++) {
2063 if ((ris.get(i).activityInfo.applicationInfo.flags
2064 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2065 ri = ris.get(i);
2066 break;
2067 }
2068 }
2069
2070 if (ri != null) {
2071 String vers = ri.activityInfo.metaData != null
2072 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2073 : null;
2074 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2075 vers = ri.activityInfo.applicationInfo.metaData.getString(
2076 Intent.METADATA_SETUP_VERSION);
2077 }
2078 String lastVers = Settings.Secure.getString(
2079 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2080 if (vers != null && !vers.equals(lastVers)) {
2081 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2082 intent.setComponent(new ComponentName(
2083 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002084 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002085 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002086 }
2087 }
2088 }
2089 }
2090
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002091 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002092 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002093
2094 final int identHash = System.identityHashCode(r);
2095 updateUsageStats(r, true);
2096
2097 int i = mWatchers.beginBroadcast();
2098 while (i > 0) {
2099 i--;
2100 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2101 if (w != null) {
2102 try {
2103 w.activityResuming(identHash);
2104 } catch (RemoteException e) {
2105 }
2106 }
2107 }
2108 mWatchers.finishBroadcast();
2109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002111 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002112 final int N = mPendingActivityLaunches.size();
2113 if (N <= 0) {
2114 return;
2115 }
2116 for (int i=0; i<N; i++) {
2117 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002118 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002119 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2120 doResume && i == (N-1));
2121 }
2122 mPendingActivityLaunches.clear();
2123 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002124
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002125 public final int startActivity(IApplicationThread caller,
2126 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2127 int grantedMode, IBinder resultTo,
2128 String resultWho, int requestCode, boolean onlyIfNeeded,
2129 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002130 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002131 grantedUriPermissions, grantedMode, resultTo, resultWho,
2132 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002133 }
2134
2135 public final WaitResult startActivityAndWait(IApplicationThread caller,
2136 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2137 int grantedMode, IBinder resultTo,
2138 String resultWho, int requestCode, boolean onlyIfNeeded,
2139 boolean debug) {
2140 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002141 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002142 grantedUriPermissions, grantedMode, resultTo, resultWho,
2143 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002144 return res;
2145 }
2146
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002147 public final int startActivityWithConfig(IApplicationThread caller,
2148 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2149 int grantedMode, IBinder resultTo,
2150 String resultWho, int requestCode, boolean onlyIfNeeded,
2151 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002152 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002153 grantedUriPermissions, grantedMode, resultTo, resultWho,
2154 requestCode, onlyIfNeeded, debug, null, config);
2155 }
2156
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002157 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002158 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002159 IBinder resultTo, String resultWho, int requestCode,
2160 int flagsMask, int flagsValues) {
2161 // Refuse possible leaked file descriptors
2162 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2163 throw new IllegalArgumentException("File descriptors passed in Intent");
2164 }
2165
2166 IIntentSender sender = intent.getTarget();
2167 if (!(sender instanceof PendingIntentRecord)) {
2168 throw new IllegalArgumentException("Bad PendingIntent object");
2169 }
2170
2171 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002172
2173 synchronized (this) {
2174 // If this is coming from the currently resumed activity, it is
2175 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002176 if (mMainStack.mResumedActivity != null
2177 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002178 Binder.getCallingUid()) {
2179 mAppSwitchesAllowedTime = 0;
2180 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002181 }
2182
2183 return pir.sendInner(0, fillInIntent, resolvedType,
2184 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2185 }
2186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 public boolean startNextMatchingActivity(IBinder callingActivity,
2188 Intent intent) {
2189 // Refuse possible leaked file descriptors
2190 if (intent != null && intent.hasFileDescriptors() == true) {
2191 throw new IllegalArgumentException("File descriptors passed in Intent");
2192 }
2193
2194 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 if (index < 0) {
2197 return false;
2198 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002199 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 if (r.app == null || r.app.thread == null) {
2201 // The caller is not running... d'oh!
2202 return false;
2203 }
2204 intent = new Intent(intent);
2205 // The caller is not allowed to change the data.
2206 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2207 // And we are resetting to find the next component...
2208 intent.setComponent(null);
2209
2210 ActivityInfo aInfo = null;
2211 try {
2212 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002213 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002215 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216
2217 // Look for the original activity in the list...
2218 final int N = resolves != null ? resolves.size() : 0;
2219 for (int i=0; i<N; i++) {
2220 ResolveInfo rInfo = resolves.get(i);
2221 if (rInfo.activityInfo.packageName.equals(r.packageName)
2222 && rInfo.activityInfo.name.equals(r.info.name)) {
2223 // We found the current one... the next matching is
2224 // after it.
2225 i++;
2226 if (i<N) {
2227 aInfo = resolves.get(i).activityInfo;
2228 }
2229 break;
2230 }
2231 }
2232 } catch (RemoteException e) {
2233 }
2234
2235 if (aInfo == null) {
2236 // Nobody who is next!
2237 return false;
2238 }
2239
2240 intent.setComponent(new ComponentName(
2241 aInfo.applicationInfo.packageName, aInfo.name));
2242 intent.setFlags(intent.getFlags()&~(
2243 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2244 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2245 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2246 Intent.FLAG_ACTIVITY_NEW_TASK));
2247
2248 // Okay now we need to start the new activity, replacing the
2249 // currently running activity. This is a little tricky because
2250 // we want to start the new one as if the current one is finished,
2251 // but not finish the current one first so that there is no flicker.
2252 // And thus...
2253 final boolean wasFinishing = r.finishing;
2254 r.finishing = true;
2255
2256 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002257 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 final String resultWho = r.resultWho;
2259 final int requestCode = r.requestCode;
2260 r.resultTo = null;
2261 if (resultTo != null) {
2262 resultTo.removeResultsLocked(r, resultWho, requestCode);
2263 }
2264
2265 final long origId = Binder.clearCallingIdentity();
2266 // XXX we are not dealing with propagating grantedUriPermissions...
2267 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002268 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002270 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 Binder.restoreCallingIdentity(origId);
2272
2273 r.finishing = wasFinishing;
2274 if (res != START_SUCCESS) {
2275 return false;
2276 }
2277 return true;
2278 }
2279 }
2280
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002281 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 Intent intent, String resolvedType, IBinder resultTo,
2283 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002284
2285 // This is so super not safe, that only the system (or okay root)
2286 // can do it.
2287 final int callingUid = Binder.getCallingUid();
2288 if (callingUid != 0 && callingUid != Process.myUid()) {
2289 throw new SecurityException(
2290 "startActivityInPackage only available to the system");
2291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002293 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2294 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2295 }
2296
2297 public final int startActivities(IApplicationThread caller,
2298 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2299 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2300 }
2301
2302 public final int startActivitiesInPackage(int uid,
2303 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2304
2305 // This is so super not safe, that only the system (or okay root)
2306 // can do it.
2307 final int callingUid = Binder.getCallingUid();
2308 if (callingUid != 0 && callingUid != Process.myUid()) {
2309 throw new SecurityException(
2310 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 }
2312
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002313 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 }
2315
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002316 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002318 // Quick case: check if the top-most recent task is the same.
2319 if (N > 0 && mRecentTasks.get(0) == task) {
2320 return;
2321 }
2322 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 for (int i=0; i<N; i++) {
2324 TaskRecord tr = mRecentTasks.get(i);
2325 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2326 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2327 mRecentTasks.remove(i);
2328 i--;
2329 N--;
2330 if (task.intent == null) {
2331 // If the new recent task we are adding is not fully
2332 // specified, then replace it with the existing recent task.
2333 task = tr;
2334 }
2335 }
2336 }
2337 if (N >= MAX_RECENT_TASKS) {
2338 mRecentTasks.remove(N-1);
2339 }
2340 mRecentTasks.add(0, task);
2341 }
2342
2343 public void setRequestedOrientation(IBinder token,
2344 int requestedOrientation) {
2345 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 if (index < 0) {
2348 return;
2349 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002350 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 final long origId = Binder.clearCallingIdentity();
2352 mWindowManager.setAppOrientation(r, requestedOrientation);
2353 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002354 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 r.mayFreezeScreenLocked(r.app) ? r : null);
2356 if (config != null) {
2357 r.frozenBeforeDestroy = true;
2358 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002359 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
2361 }
2362 Binder.restoreCallingIdentity(origId);
2363 }
2364 }
2365
2366 public int getRequestedOrientation(IBinder token) {
2367 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 if (index < 0) {
2370 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2371 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002372 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 return mWindowManager.getAppOrientation(r);
2374 }
2375 }
2376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 /**
2378 * This is the internal entry point for handling Activity.finish().
2379 *
2380 * @param token The Binder token referencing the Activity we want to finish.
2381 * @param resultCode Result code, if any, from this Activity.
2382 * @param resultData Result data (Intent), if any, from this Activity.
2383 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002384 * @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 -08002385 */
2386 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2387 // Refuse possible leaked file descriptors
2388 if (resultData != null && resultData.hasFileDescriptors() == true) {
2389 throw new IllegalArgumentException("File descriptors passed in Intent");
2390 }
2391
2392 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002393 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002395 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 if (next != null) {
2397 // ask watcher if this is allowed
2398 boolean resumeOK = true;
2399 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002400 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002402 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 }
2404
2405 if (!resumeOK) {
2406 return false;
2407 }
2408 }
2409 }
2410 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002411 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 resultData, "app-request");
2413 Binder.restoreCallingIdentity(origId);
2414 return res;
2415 }
2416 }
2417
Dianne Hackborn860755f2010-06-03 18:47:52 -07002418 public final void finishHeavyWeightApp() {
2419 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2420 != PackageManager.PERMISSION_GRANTED) {
2421 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2422 + Binder.getCallingPid()
2423 + ", uid=" + Binder.getCallingUid()
2424 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2425 Slog.w(TAG, msg);
2426 throw new SecurityException(msg);
2427 }
2428
2429 synchronized(this) {
2430 if (mHeavyWeightProcess == null) {
2431 return;
2432 }
2433
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002434 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002435 mHeavyWeightProcess.activities);
2436 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002437 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002440 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002441 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002442 null, "finish-heavy");
2443 }
2444 }
2445 }
2446
2447 mHeavyWeightProcess = null;
2448 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2449 }
2450 }
2451
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002452 public void crashApplication(int uid, int initialPid, String packageName,
2453 String message) {
2454 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2455 != PackageManager.PERMISSION_GRANTED) {
2456 String msg = "Permission Denial: crashApplication() from pid="
2457 + Binder.getCallingPid()
2458 + ", uid=" + Binder.getCallingUid()
2459 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2460 Slog.w(TAG, msg);
2461 throw new SecurityException(msg);
2462 }
2463
2464 synchronized(this) {
2465 ProcessRecord proc = null;
2466
2467 // Figure out which process to kill. We don't trust that initialPid
2468 // still has any relation to current pids, so must scan through the
2469 // list.
2470 synchronized (mPidsSelfLocked) {
2471 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2472 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2473 if (p.info.uid != uid) {
2474 continue;
2475 }
2476 if (p.pid == initialPid) {
2477 proc = p;
2478 break;
2479 }
2480 for (String str : p.pkgList) {
2481 if (str.equals(packageName)) {
2482 proc = p;
2483 }
2484 }
2485 }
2486 }
2487
2488 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002489 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002490 + " initialPid=" + initialPid
2491 + " packageName=" + packageName);
2492 return;
2493 }
2494
2495 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002496 if (proc.pid == Process.myPid()) {
2497 Log.w(TAG, "crashApplication: trying to crash self!");
2498 return;
2499 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002500 long ident = Binder.clearCallingIdentity();
2501 try {
2502 proc.thread.scheduleCrash(message);
2503 } catch (RemoteException e) {
2504 }
2505 Binder.restoreCallingIdentity(ident);
2506 }
2507 }
2508 }
2509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 public final void finishSubActivity(IBinder token, String resultWho,
2511 int requestCode) {
2512 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 if (index < 0) {
2515 return;
2516 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002517 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518
2519 final long origId = Binder.clearCallingIdentity();
2520
2521 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2523 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 if (r.resultTo == self && r.requestCode == requestCode) {
2525 if ((r.resultWho == null && resultWho == null) ||
2526 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 Activity.RESULT_CANCELED, null, "request-sub");
2529 }
2530 }
2531 }
2532
2533 Binder.restoreCallingIdentity(origId);
2534 }
2535 }
2536
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002537 public boolean willActivityBeVisible(IBinder token) {
2538 synchronized(this) {
2539 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2541 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002542 if (r == token) {
2543 return true;
2544 }
2545 if (r.fullscreen && !r.finishing) {
2546 return false;
2547 }
2548 }
2549 return true;
2550 }
2551 }
2552
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 public void overridePendingTransition(IBinder token, String packageName,
2554 int enterAnim, int exitAnim) {
2555 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002556 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002557 if (index < 0) {
2558 return;
2559 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002561
2562 final long origId = Binder.clearCallingIdentity();
2563
2564 if (self.state == ActivityState.RESUMED
2565 || self.state == ActivityState.PAUSING) {
2566 mWindowManager.overridePendingAppTransition(packageName,
2567 enterAnim, exitAnim);
2568 }
2569
2570 Binder.restoreCallingIdentity(origId);
2571 }
2572 }
2573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 * Main function for removing an existing process from the activity manager
2576 * as a result of that process going away. Clears out all connections
2577 * to the process.
2578 */
2579 private final void handleAppDiedLocked(ProcessRecord app,
2580 boolean restarting) {
2581 cleanUpApplicationRecordLocked(app, restarting, -1);
2582 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002583 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 }
2585
2586 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002587 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2588 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2589 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002591 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2592 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
2594
2595 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002596 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597
2598 boolean atTop = true;
2599 boolean hasVisibleActivities = false;
2600
2601 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002602 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002603 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 TAG, "Removing app " + app + " from history with " + i + " entries");
2605 while (i > 0) {
2606 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002607 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002608 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2610 if (r.app == app) {
2611 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 TAG, "Removing this entry! frozen=" + r.haveState
2614 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002615 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002616 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617
2618 r.inHistory = false;
2619 mWindowManager.removeAppToken(r);
2620 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002623 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624
2625 } else {
2626 // We have the current state for this activity, so
2627 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002628 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 TAG, "Keeping entry, setting app to null");
2630 if (r.visible) {
2631 hasVisibleActivities = true;
2632 }
2633 r.app = null;
2634 r.nowVisible = false;
2635 if (!r.haveState) {
2636 r.icicle = null;
2637 }
2638 }
2639
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002640 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 r.state = ActivityState.STOPPED;
2642 }
2643 atTop = false;
2644 }
2645
2646 app.activities.clear();
2647
2648 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002649 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 + " running instrumentation " + app.instrumentationClass);
2651 Bundle info = new Bundle();
2652 info.putString("shortMsg", "Process crashed.");
2653 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2654 }
2655
2656 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002657 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 // If there was nothing to resume, and we are not already
2659 // restarting this process, but there is a visible activity that
2660 // is hosted by the process... then make sure all visible
2661 // activities are running, taking care of restarting this
2662 // process.
2663 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002664 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666 }
2667 }
2668 }
2669
2670 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2671 IBinder threadBinder = thread.asBinder();
2672
2673 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002674 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2675 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2677 return i;
2678 }
2679 }
2680 return -1;
2681 }
2682
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002683 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 IApplicationThread thread) {
2685 if (thread == null) {
2686 return null;
2687 }
2688
2689 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002690 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
2692
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002693 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 IApplicationThread thread) {
2695
2696 mProcDeaths[0]++;
2697
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002698 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2699 synchronized (stats) {
2700 stats.noteProcessDiedLocked(app.info.uid, pid);
2701 }
2702
Magnus Edlund7bb25812010-02-24 15:45:06 +01002703 // Clean up already done if the process has been re-started.
2704 if (app.pid == pid && app.thread != null &&
2705 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002706 if (!app.killedBackground) {
2707 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2708 + ") has died.");
2709 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002710 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002711 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 TAG, "Dying app: " + app + ", pid: " + pid
2713 + ", thread: " + thread.asBinder());
2714 boolean doLowMem = app.instrumentationClass == null;
2715 handleAppDiedLocked(app, false);
2716
2717 if (doLowMem) {
2718 // If there are no longer any background processes running,
2719 // and the app that died was not running instrumentation,
2720 // then tell everyone we are now low on memory.
2721 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002722 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2723 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2725 haveBg = true;
2726 break;
2727 }
2728 }
2729
2730 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002731 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002732 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002733 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002734 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2735 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002736 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002737 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2738 // The low memory report is overriding any current
2739 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002740 // heavy/important/visible/foreground processes first.
2741 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002742 rec.lastRequestedGc = 0;
2743 } else {
2744 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002746 rec.reportLowMemory = true;
2747 rec.lastLowMemory = now;
2748 mProcessesToGc.remove(rec);
2749 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 }
2751 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002752 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 }
2754 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002755 } else if (app.pid != pid) {
2756 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002757 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002758 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002759 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002760 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002761 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 + thread.asBinder());
2763 }
2764 }
2765
Dan Egnor42471dd2010-01-07 17:25:22 -08002766 /**
2767 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002768 * @param clearTraces causes the dump file to be erased prior to the new
2769 * traces being written, if true; when false, the new traces will be
2770 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002771 * @param firstPids of dalvik VM processes to dump stack traces for first
2772 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002773 * @return file containing stack traces, or null if no dump file is configured
2774 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002775 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2776 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002777 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2778 if (tracesPath == null || tracesPath.length() == 0) {
2779 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002780 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002781
2782 File tracesFile = new File(tracesPath);
2783 try {
2784 File tracesDir = tracesFile.getParentFile();
2785 if (!tracesDir.exists()) tracesFile.mkdirs();
2786 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2787
Christopher Tate6ee412d2010-05-28 12:01:56 -07002788 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002789 tracesFile.createNewFile();
2790 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2791 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002792 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002793 return null;
2794 }
2795
2796 // Use a FileObserver to detect when traces finish writing.
2797 // The order of traces is considered important to maintain for legibility.
2798 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2799 public synchronized void onEvent(int event, String path) { notify(); }
2800 };
2801
2802 try {
2803 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002804
2805 // First collect all of the stacks of the most important pids.
2806 try {
2807 int num = firstPids.size();
2808 for (int i = 0; i < num; i++) {
2809 synchronized (observer) {
2810 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2811 observer.wait(200); // Wait for write-close, give up after 200msec
2812 }
2813 }
2814 } catch (InterruptedException e) {
2815 Log.wtf(TAG, e);
2816 }
2817
2818 // Next measure CPU usage.
2819 if (processStats != null) {
2820 processStats.init();
2821 System.gc();
2822 processStats.update();
2823 try {
2824 synchronized (processStats) {
2825 processStats.wait(500); // measure over 1/2 second.
2826 }
2827 } catch (InterruptedException e) {
2828 }
2829 processStats.update();
2830
2831 // We'll take the stack crawls of just the top apps using CPU.
2832 final int N = processStats.countWorkingStats();
2833 int numProcs = 0;
2834 for (int i=0; i<N && numProcs<5; i++) {
2835 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2836 if (lastPids.indexOfKey(stats.pid) >= 0) {
2837 numProcs++;
2838 try {
2839 synchronized (observer) {
2840 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2841 observer.wait(200); // Wait for write-close, give up after 200msec
2842 }
2843 } catch (InterruptedException e) {
2844 Log.wtf(TAG, e);
2845 }
2846
2847 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002848 }
2849 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002850
2851 return tracesFile;
2852
Dan Egnor42471dd2010-01-07 17:25:22 -08002853 } finally {
2854 observer.stopWatching();
2855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
2857
Jeff Brown4d94a762010-09-23 11:33:28 -07002858 private final class AppNotResponding implements Runnable {
2859 private final ProcessRecord mApp;
2860 private final String mAnnotation;
2861
2862 public AppNotResponding(ProcessRecord app, String annotation) {
2863 mApp = app;
2864 mAnnotation = annotation;
2865 }
2866
2867 @Override
2868 public void run() {
2869 appNotResponding(mApp, null, null, mAnnotation);
2870 }
2871 }
2872
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002873 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2874 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002875 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2876 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2877
Dianne Hackborn287952c2010-09-22 22:34:31 -07002878 if (mController != null) {
2879 try {
2880 // 0 == continue, -1 = kill process immediately
2881 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2882 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2883 } catch (RemoteException e) {
2884 mController = null;
2885 }
2886 }
2887
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002888 long anrTime = SystemClock.uptimeMillis();
2889 if (MONITOR_CPU_USAGE) {
2890 updateCpuStatsNow();
2891 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002892
2893 synchronized (this) {
2894 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2895 if (mShuttingDown) {
2896 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2897 return;
2898 } else if (app.notResponding) {
2899 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2900 return;
2901 } else if (app.crashing) {
2902 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2903 return;
2904 }
2905
2906 // In case we come through here for the same app before completing
2907 // this one, mark as anring now so we will bail out.
2908 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002909
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002910 // Log the ANR to the event log.
2911 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2912 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002913
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002914 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002915 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002916
2917 int parentPid = app.pid;
2918 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002919 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002920
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002921 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002922
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002923 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2924 ProcessRecord r = mLruProcesses.get(i);
2925 if (r != null && r.thread != null) {
2926 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002927 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2928 if (r.persistent) {
2929 firstPids.add(pid);
2930 } else {
2931 lastPids.put(pid, Boolean.TRUE);
2932 }
2933 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 }
2936 }
2937
Dan Egnor42471dd2010-01-07 17:25:22 -08002938 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002939 StringBuilder info = mStringBuilder;
2940 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002941 info.append("ANR in ").append(app.processName);
2942 if (activity != null && activity.shortComponentName != null) {
2943 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002944 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002945 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002947 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002949 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002950 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952
Dianne Hackborn287952c2010-09-22 22:34:31 -07002953 final ProcessStats processStats = new ProcessStats(true);
2954
2955 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2956
Dan Egnor42471dd2010-01-07 17:25:22 -08002957 String cpuInfo = null;
2958 if (MONITOR_CPU_USAGE) {
2959 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002960 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002961 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002962 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002963 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002964 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 }
2966
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002967 info.append(processStats.printCurrentState(anrTime));
2968
Joe Onorato8a9b2202010-02-26 18:56:32 -08002969 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002970 if (tracesFile == null) {
2971 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2972 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2973 }
2974
2975 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2976
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002977 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002979 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2980 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002982 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2983 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 }
2985 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002986 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 }
2989
Dan Egnor42471dd2010-01-07 17:25:22 -08002990 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2991 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2992 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002993
2994 synchronized (this) {
2995 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2996 Process.killProcess(app.pid);
2997 return;
2998 }
2999
3000 // Set the app's notResponding state, and look up the errorReportReceiver
3001 makeAppNotRespondingLocked(app,
3002 activity != null ? activity.shortComponentName : null,
3003 annotation != null ? "ANR " + annotation : "ANR",
3004 info.toString());
3005
3006 // Bring up the infamous App Not Responding dialog
3007 Message msg = Message.obtain();
3008 HashMap map = new HashMap();
3009 msg.what = SHOW_NOT_RESPONDING_MSG;
3010 msg.obj = map;
3011 map.put("app", app);
3012 if (activity != null) {
3013 map.put("activity", activity);
3014 }
3015
3016 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 }
3019
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003020 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3021 if (!mLaunchWarningShown) {
3022 mLaunchWarningShown = true;
3023 mHandler.post(new Runnable() {
3024 @Override
3025 public void run() {
3026 synchronized (ActivityManagerService.this) {
3027 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3028 d.show();
3029 mHandler.postDelayed(new Runnable() {
3030 @Override
3031 public void run() {
3032 synchronized (ActivityManagerService.this) {
3033 d.dismiss();
3034 mLaunchWarningShown = false;
3035 }
3036 }
3037 }, 4000);
3038 }
3039 }
3040 });
3041 }
3042 }
3043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 public boolean clearApplicationUserData(final String packageName,
3045 final IPackageDataObserver observer) {
3046 int uid = Binder.getCallingUid();
3047 int pid = Binder.getCallingPid();
3048 long callingId = Binder.clearCallingIdentity();
3049 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003050 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 int pkgUid = -1;
3052 synchronized(this) {
3053 try {
3054 pkgUid = pm.getPackageUid(packageName);
3055 } catch (RemoteException e) {
3056 }
3057 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003058 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 return false;
3060 }
3061 if (uid == pkgUid || checkComponentPermission(
3062 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003063 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003065 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 } else {
3067 throw new SecurityException(pid+" does not have permission:"+
3068 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3069 "for process:"+packageName);
3070 }
3071 }
3072
3073 try {
3074 //clear application user data
3075 pm.clearApplicationUserData(packageName, observer);
3076 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3077 Uri.fromParts("package", packageName, null));
3078 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003079 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3080 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 } catch (RemoteException e) {
3082 }
3083 } finally {
3084 Binder.restoreCallingIdentity(callingId);
3085 }
3086 return true;
3087 }
3088
Dianne Hackborn03abb812010-01-04 18:43:19 -08003089 public void killBackgroundProcesses(final String packageName) {
3090 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3091 != PackageManager.PERMISSION_GRANTED &&
3092 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3093 != PackageManager.PERMISSION_GRANTED) {
3094 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 + Binder.getCallingPid()
3096 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003097 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003098 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 throw new SecurityException(msg);
3100 }
3101
3102 long callingId = Binder.clearCallingIdentity();
3103 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003104 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 int pkgUid = -1;
3106 synchronized(this) {
3107 try {
3108 pkgUid = pm.getPackageUid(packageName);
3109 } catch (RemoteException e) {
3110 }
3111 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003112 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 return;
3114 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003115 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003116 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003117 }
3118 } finally {
3119 Binder.restoreCallingIdentity(callingId);
3120 }
3121 }
3122
3123 public void forceStopPackage(final String packageName) {
3124 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3125 != PackageManager.PERMISSION_GRANTED) {
3126 String msg = "Permission Denial: forceStopPackage() from pid="
3127 + Binder.getCallingPid()
3128 + ", uid=" + Binder.getCallingUid()
3129 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003130 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003131 throw new SecurityException(msg);
3132 }
3133
3134 long callingId = Binder.clearCallingIdentity();
3135 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003136 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003137 int pkgUid = -1;
3138 synchronized(this) {
3139 try {
3140 pkgUid = pm.getPackageUid(packageName);
3141 } catch (RemoteException e) {
3142 }
3143 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003144 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003145 return;
3146 }
3147 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 }
3149 } finally {
3150 Binder.restoreCallingIdentity(callingId);
3151 }
3152 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003153
3154 /*
3155 * The pkg name and uid have to be specified.
3156 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3157 */
3158 public void killApplicationWithUid(String pkg, int uid) {
3159 if (pkg == null) {
3160 return;
3161 }
3162 // Make sure the uid is valid.
3163 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003164 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003165 return;
3166 }
3167 int callerUid = Binder.getCallingUid();
3168 // Only the system server can kill an application
3169 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003170 // Post an aysnc message to kill the application
3171 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3172 msg.arg1 = uid;
3173 msg.arg2 = 0;
3174 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003175 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003176 } else {
3177 throw new SecurityException(callerUid + " cannot kill pkg: " +
3178 pkg);
3179 }
3180 }
3181
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003182 public void closeSystemDialogs(String reason) {
3183 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003184 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003185 if (reason != null) {
3186 intent.putExtra("reason", reason);
3187 }
3188
3189 final int uid = Binder.getCallingUid();
3190 final long origId = Binder.clearCallingIdentity();
3191 synchronized (this) {
3192 int i = mWatchers.beginBroadcast();
3193 while (i > 0) {
3194 i--;
3195 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3196 if (w != null) {
3197 try {
3198 w.closingSystemDialogs(reason);
3199 } catch (RemoteException e) {
3200 }
3201 }
3202 }
3203 mWatchers.finishBroadcast();
3204
Dianne Hackbornffa42482009-09-23 22:20:11 -07003205 mWindowManager.closeSystemDialogs(reason);
3206
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003207 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3208 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003209 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003210 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003211 Activity.RESULT_CANCELED, null, "close-sys");
3212 }
3213 }
3214
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003215 broadcastIntentLocked(null, null, intent, null,
3216 null, 0, null, null, null, false, false, -1, uid);
3217 }
3218 Binder.restoreCallingIdentity(origId);
3219 }
3220
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003221 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003222 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003223 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3224 for (int i=pids.length-1; i>=0; i--) {
3225 infos[i] = new Debug.MemoryInfo();
3226 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003227 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003228 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003229 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003230
3231 public void killApplicationProcess(String processName, int uid) {
3232 if (processName == null) {
3233 return;
3234 }
3235
3236 int callerUid = Binder.getCallingUid();
3237 // Only the system server can kill an application
3238 if (callerUid == Process.SYSTEM_UID) {
3239 synchronized (this) {
3240 ProcessRecord app = getProcessRecordLocked(processName, uid);
3241 if (app != null) {
3242 try {
3243 app.thread.scheduleSuicide();
3244 } catch (RemoteException e) {
3245 // If the other end already died, then our work here is done.
3246 }
3247 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003248 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003249 + processName + " / " + uid);
3250 }
3251 }
3252 } else {
3253 throw new SecurityException(callerUid + " cannot kill app process: " +
3254 processName);
3255 }
3256 }
3257
Dianne Hackborn03abb812010-01-04 18:43:19 -08003258 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003259 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3261 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003262 if (!mProcessesReady) {
3263 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 intent.putExtra(Intent.EXTRA_UID, uid);
3266 broadcastIntentLocked(null, null, intent,
3267 null, null, 0, null, null, null,
3268 false, false, MY_PID, Process.SYSTEM_UID);
3269 }
3270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003271 private final boolean killPackageProcessesLocked(String packageName, int uid,
3272 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003273 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274
Dianne Hackborn03abb812010-01-04 18:43:19 -08003275 // Remove all processes this package may have touched: all with the
3276 // same UID (except for the system or root user), and all whose name
3277 // matches the package name.
3278 final String procNamePrefix = packageName + ":";
3279 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3280 final int NA = apps.size();
3281 for (int ia=0; ia<NA; ia++) {
3282 ProcessRecord app = apps.valueAt(ia);
3283 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003284 if (doit) {
3285 procs.add(app);
3286 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003287 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3288 || app.processName.equals(packageName)
3289 || app.processName.startsWith(procNamePrefix)) {
3290 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003291 if (!doit) {
3292 return true;
3293 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003294 app.removed = true;
3295 procs.add(app);
3296 }
3297 }
3298 }
3299 }
3300
3301 int N = procs.size();
3302 for (int i=0; i<N; i++) {
3303 removeProcessLocked(procs.get(i), callerWillRestart);
3304 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003305 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003306 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003307
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003308 private final boolean forceStopPackageLocked(String name, int uid,
3309 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 int i, N;
3311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 if (uid < 0) {
3313 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003314 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 } catch (RemoteException e) {
3316 }
3317 }
3318
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003319 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003320 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003321
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003322 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3323 while (badApps.hasNext()) {
3324 SparseArray<Long> ba = badApps.next();
3325 if (ba.get(uid) != null) {
3326 badApps.remove();
3327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 }
3329 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003330
3331 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3332 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003334 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3335 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003337 if (!doit) {
3338 return true;
3339 }
3340 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003341 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 if (r.app != null) {
3343 r.app.removed = true;
3344 }
3345 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003346 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348 }
3349
3350 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3351 for (ServiceRecord service : mServices.values()) {
3352 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003353 if (!doit) {
3354 return true;
3355 }
3356 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003357 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 if (service.app != null) {
3359 service.app.removed = true;
3360 }
3361 service.app = null;
3362 services.add(service);
3363 }
3364 }
3365
3366 N = services.size();
3367 for (i=0; i<N; i++) {
3368 bringDownServiceLocked(services.get(i), true);
3369 }
3370
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003371 if (doit) {
3372 if (purgeCache) {
3373 AttributeCache ac = AttributeCache.instance();
3374 if (ac != null) {
3375 ac.removePackage(name);
3376 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003377 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003378 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003379 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003380
3381 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 }
3383
3384 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3385 final String name = app.processName;
3386 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003387 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 TAG, "Force removing process " + app + " (" + name
3389 + "/" + uid + ")");
3390
3391 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003392 if (mHeavyWeightProcess == app) {
3393 mHeavyWeightProcess = null;
3394 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 boolean needRestart = false;
3397 if (app.pid > 0 && app.pid != MY_PID) {
3398 int pid = app.pid;
3399 synchronized (mPidsSelfLocked) {
3400 mPidsSelfLocked.remove(pid);
3401 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3402 }
3403 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003404 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 Process.killProcess(pid);
3406
3407 if (app.persistent) {
3408 if (!callerWillRestart) {
3409 addAppLocked(app.info);
3410 } else {
3411 needRestart = true;
3412 }
3413 }
3414 } else {
3415 mRemovedProcesses.add(app);
3416 }
3417
3418 return needRestart;
3419 }
3420
3421 private final void processStartTimedOutLocked(ProcessRecord app) {
3422 final int pid = app.pid;
3423 boolean gone = false;
3424 synchronized (mPidsSelfLocked) {
3425 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3426 if (knownApp != null && knownApp.thread == null) {
3427 mPidsSelfLocked.remove(pid);
3428 gone = true;
3429 }
3430 }
3431
3432 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003434 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003435 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003437 if (mHeavyWeightProcess == app) {
3438 mHeavyWeightProcess = null;
3439 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3440 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003441 // Take care of any launching providers waiting for this process.
3442 checkAppInLaunchingProvidersLocked(app, true);
3443 // Take care of any services that are waiting for the process.
3444 for (int i=0; i<mPendingServices.size(); i++) {
3445 ServiceRecord sr = mPendingServices.get(i);
3446 if (app.info.uid == sr.appInfo.uid
3447 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003448 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003449 mPendingServices.remove(i);
3450 i--;
3451 bringDownServiceLocked(sr, true);
3452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003454 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003455 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003456 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003457 try {
3458 IBackupManager bm = IBackupManager.Stub.asInterface(
3459 ServiceManager.getService(Context.BACKUP_SERVICE));
3460 bm.agentDisconnected(app.info.packageName);
3461 } catch (RemoteException e) {
3462 // Can't happen; the backup manager is local
3463 }
3464 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003465 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003466 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003467 mPendingBroadcast.state = BroadcastRecord.IDLE;
3468 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003469 mPendingBroadcast = null;
3470 scheduleBroadcastsLocked();
3471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 }
3475 }
3476
3477 private final boolean attachApplicationLocked(IApplicationThread thread,
3478 int pid) {
3479
3480 // Find the application record that is being attached... either via
3481 // the pid if we are running in multiple processes, or just pull the
3482 // next app record if we are emulating process with anonymous threads.
3483 ProcessRecord app;
3484 if (pid != MY_PID && pid >= 0) {
3485 synchronized (mPidsSelfLocked) {
3486 app = mPidsSelfLocked.get(pid);
3487 }
3488 } else if (mStartingProcesses.size() > 0) {
3489 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003490 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 } else {
3492 app = null;
3493 }
3494
3495 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003498 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 if (pid > 0 && pid != MY_PID) {
3500 Process.killProcess(pid);
3501 } else {
3502 try {
3503 thread.scheduleExit();
3504 } catch (Exception e) {
3505 // Ignore exceptions.
3506 }
3507 }
3508 return false;
3509 }
3510
3511 // If this application record is still attached to a previous
3512 // process, clean it up now.
3513 if (app.thread != null) {
3514 handleAppDiedLocked(app, true);
3515 }
3516
3517 // Tell the process all about itself.
3518
Joe Onorato8a9b2202010-02-26 18:56:32 -08003519 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 TAG, "Binding process pid " + pid + " to record " + app);
3521
3522 String processName = app.processName;
3523 try {
3524 thread.asBinder().linkToDeath(new AppDeathRecipient(
3525 app, pid, thread), 0);
3526 } catch (RemoteException e) {
3527 app.resetPackageList();
3528 startProcessLocked(app, "link fail", processName);
3529 return false;
3530 }
3531
Doug Zongker2bec3d42009-12-04 12:52:44 -08003532 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533
3534 app.thread = thread;
3535 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003536 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3537 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 app.forcingToForeground = null;
3539 app.foregroundServices = false;
3540 app.debugging = false;
3541
3542 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3543
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003544 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003545 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003547 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003548 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003549 }
3550
Joe Onorato8a9b2202010-02-26 18:56:32 -08003551 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 TAG, "New app record " + app
3553 + " thread=" + thread.asBinder() + " pid=" + pid);
3554 try {
3555 int testMode = IApplicationThread.DEBUG_OFF;
3556 if (mDebugApp != null && mDebugApp.equals(processName)) {
3557 testMode = mWaitForDebugger
3558 ? IApplicationThread.DEBUG_WAIT
3559 : IApplicationThread.DEBUG_ON;
3560 app.debugging = true;
3561 if (mDebugTransient) {
3562 mDebugApp = mOrigDebugApp;
3563 mWaitForDebugger = mOrigWaitForDebugger;
3564 }
3565 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003566
Christopher Tate181fafa2009-05-14 11:12:14 -07003567 // If the app is being launched for restore or full backup, set it up specially
3568 boolean isRestrictedBackupMode = false;
3569 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3570 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3571 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3572 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003573
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003574 ensurePackageDexOpt(app.instrumentationInfo != null
3575 ? app.instrumentationInfo.packageName
3576 : app.info.packageName);
3577 if (app.instrumentationClass != null) {
3578 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003579 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003580 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003581 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003582 thread.bindApplication(processName, app.instrumentationInfo != null
3583 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 app.instrumentationClass, app.instrumentationProfileFile,
3585 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003586 isRestrictedBackupMode || !normalMode,
3587 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003588 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003589 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 } catch (Exception e) {
3591 // todo: Yikes! What should we do? For now we will try to
3592 // start another process, but that could easily get us in
3593 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003594 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595
3596 app.resetPackageList();
3597 startProcessLocked(app, "bind fail", processName);
3598 return false;
3599 }
3600
3601 // Remove this record from the list of starting applications.
3602 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003603 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3604 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 mProcessesOnHold.remove(app);
3606
3607 boolean badApp = false;
3608 boolean didSomething = false;
3609
3610 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003611 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003612 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3614 && processName.equals(hr.processName)) {
3615 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003616 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 didSomething = true;
3618 }
3619 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003620 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 + hr.intent.getComponent().flattenToShortString(), e);
3622 badApp = true;
3623 }
3624 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003625 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 }
3627 }
3628
3629 // Find any services that should be running in this process...
3630 if (!badApp && mPendingServices.size() > 0) {
3631 ServiceRecord sr = null;
3632 try {
3633 for (int i=0; i<mPendingServices.size(); i++) {
3634 sr = mPendingServices.get(i);
3635 if (app.info.uid != sr.appInfo.uid
3636 || !processName.equals(sr.processName)) {
3637 continue;
3638 }
3639
3640 mPendingServices.remove(i);
3641 i--;
3642 realStartServiceLocked(sr, app);
3643 didSomething = true;
3644 }
3645 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003646 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 + sr.shortName, e);
3648 badApp = true;
3649 }
3650 }
3651
3652 // Check if the next broadcast receiver is in this process...
3653 BroadcastRecord br = mPendingBroadcast;
3654 if (!badApp && br != null && br.curApp == app) {
3655 try {
3656 mPendingBroadcast = null;
3657 processCurBroadcastLocked(br, app);
3658 didSomething = true;
3659 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003660 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 + br.curComponent.flattenToShortString(), e);
3662 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003663 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3665 br.resultExtras, br.resultAbort, true);
3666 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003667 // We need to reset the state if we fails to start the receiver.
3668 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 }
3670 }
3671
Christopher Tate181fafa2009-05-14 11:12:14 -07003672 // Check whether the next backup agent is in this process...
3673 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003674 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003675 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003676 try {
3677 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3678 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003679 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003680 e.printStackTrace();
3681 }
3682 }
3683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 if (badApp) {
3685 // todo: Also need to kill application to deal with all
3686 // kinds of exceptions.
3687 handleAppDiedLocked(app, false);
3688 return false;
3689 }
3690
3691 if (!didSomething) {
3692 updateOomAdjLocked();
3693 }
3694
3695 return true;
3696 }
3697
3698 public final void attachApplication(IApplicationThread thread) {
3699 synchronized (this) {
3700 int callingPid = Binder.getCallingPid();
3701 final long origId = Binder.clearCallingIdentity();
3702 attachApplicationLocked(thread, callingPid);
3703 Binder.restoreCallingIdentity(origId);
3704 }
3705 }
3706
Dianne Hackborne88846e2009-09-30 21:34:25 -07003707 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003709 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 Binder.restoreCallingIdentity(origId);
3711 }
3712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003714 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003715 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 mWindowManager.enableScreenAfterBoot();
3717 }
3718
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003719 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003720 IntentFilter pkgFilter = new IntentFilter();
3721 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3722 pkgFilter.addDataScheme("package");
3723 mContext.registerReceiver(new BroadcastReceiver() {
3724 @Override
3725 public void onReceive(Context context, Intent intent) {
3726 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3727 if (pkgs != null) {
3728 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003729 synchronized (ActivityManagerService.this) {
3730 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3731 setResultCode(Activity.RESULT_OK);
3732 return;
3733 }
3734 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003735 }
3736 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003737 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003738 }, pkgFilter);
3739
3740 synchronized (this) {
3741 // Ensure that any processes we had put on hold are now started
3742 // up.
3743 final int NP = mProcessesOnHold.size();
3744 if (NP > 0) {
3745 ArrayList<ProcessRecord> procs =
3746 new ArrayList<ProcessRecord>(mProcessesOnHold);
3747 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003748 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3749 + procs.get(ip));
3750 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003751 }
3752 }
3753
3754 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003755 // Start looking for apps that are abusing wake locks.
3756 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003757 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003758 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003759 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003760 broadcastIntentLocked(null, null,
3761 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3762 null, null, 0, null, null,
3763 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3764 false, false, MY_PID, Process.SYSTEM_UID);
3765 }
3766 }
3767 }
3768
3769 final void ensureBootCompleted() {
3770 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003771 boolean enableScreen;
3772 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003773 booting = mBooting;
3774 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003775 enableScreen = !mBooted;
3776 mBooted = true;
3777 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003778
3779 if (booting) {
3780 finishBooting();
3781 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003782
3783 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003784 enableScreenAfterBoot();
3785 }
3786 }
3787
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003788 public final void activityPaused(IBinder token) {
3789 final long origId = Binder.clearCallingIdentity();
3790 mMainStack.activityPaused(token, false);
3791 Binder.restoreCallingIdentity(origId);
3792 }
3793
3794 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3795 CharSequence description) {
3796 if (localLOGV) Slog.v(
3797 TAG, "Activity stopped: token=" + token);
3798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 // Refuse possible leaked file descriptors
3800 if (icicle != null && icicle.hasFileDescriptors()) {
3801 throw new IllegalArgumentException("File descriptors passed in Bundle");
3802 }
3803
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003804 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805
3806 final long origId = Binder.clearCallingIdentity();
3807
3808 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003809 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003811 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003812 r.icicle = icicle;
3813 r.haveState = true;
3814 if (thumbnail != null) {
3815 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003816 if (r.task != null) {
3817 r.task.lastThumbnail = r.thumbnail;
3818 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003821 if (r.task != null) {
3822 r.task.lastDescription = r.description;
3823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 r.stopped = true;
3825 r.state = ActivityState.STOPPED;
3826 if (!r.finishing) {
3827 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003828 r.stack.destroyActivityLocked(r, true);
3829 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 }
3831 }
3832 }
3833 }
3834
3835 if (r != null) {
3836 sendPendingThumbnail(r, null, null, null, false);
3837 }
3838
3839 trimApplications();
3840
3841 Binder.restoreCallingIdentity(origId);
3842 }
3843
3844 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003845 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003846 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 }
3848
3849 public String getCallingPackage(IBinder token) {
3850 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003851 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003852 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003853 }
3854 }
3855
3856 public ComponentName getCallingActivity(IBinder token) {
3857 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003858 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 return r != null ? r.intent.getComponent() : null;
3860 }
3861 }
3862
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003863 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003864 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003866 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 if (r != null) {
3868 return r.resultTo;
3869 }
3870 }
3871 return null;
3872 }
3873
3874 public ComponentName getActivityClassForToken(IBinder token) {
3875 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003876 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003878 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 return r.intent.getComponent();
3880 }
3881 return null;
3882 }
3883 }
3884
3885 public String getPackageForToken(IBinder token) {
3886 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003887 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003889 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 return r.packageName;
3891 }
3892 return null;
3893 }
3894 }
3895
3896 public IIntentSender getIntentSender(int type,
3897 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003898 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003900 if (intents != null) {
3901 if (intents.length < 1) {
3902 throw new IllegalArgumentException("Intents array length must be >= 1");
3903 }
3904 for (int i=0; i<intents.length; i++) {
3905 Intent intent = intents[i];
3906 if (intent == null) {
3907 throw new IllegalArgumentException("Null intent at index " + i);
3908 }
3909 if (intent.hasFileDescriptors()) {
3910 throw new IllegalArgumentException("File descriptors passed in Intent");
3911 }
3912 if (type == INTENT_SENDER_BROADCAST &&
3913 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3914 throw new IllegalArgumentException(
3915 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3916 }
3917 intents[i] = new Intent(intent);
3918 }
3919 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003920 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003921 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003922 }
3923 }
3924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 synchronized(this) {
3926 int callingUid = Binder.getCallingUid();
3927 try {
3928 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3929 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003930 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 .getPackageUid(packageName);
3932 if (uid != Binder.getCallingUid()) {
3933 String msg = "Permission Denial: getIntentSender() from pid="
3934 + Binder.getCallingPid()
3935 + ", uid=" + Binder.getCallingUid()
3936 + ", (need uid=" + uid + ")"
3937 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003938 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 throw new SecurityException(msg);
3940 }
3941 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003942
3943 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003944 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946 } catch (RemoteException e) {
3947 throw new SecurityException(e);
3948 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003949 }
3950 }
3951
3952 IIntentSender getIntentSenderLocked(int type,
3953 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003954 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003955 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003956 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003957 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003958 if (index < 0) {
3959 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003961 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003962 if (activity.finishing) {
3963 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003965 }
3966
3967 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3968 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3969 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3970 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3971 |PendingIntent.FLAG_UPDATE_CURRENT);
3972
3973 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3974 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003975 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003976 WeakReference<PendingIntentRecord> ref;
3977 ref = mIntentSenderRecords.get(key);
3978 PendingIntentRecord rec = ref != null ? ref.get() : null;
3979 if (rec != null) {
3980 if (!cancelCurrent) {
3981 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003982 if (rec.key.requestIntent != null) {
3983 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3984 }
3985 if (intents != null) {
3986 intents[intents.length-1] = rec.key.requestIntent;
3987 rec.key.allIntents = intents;
3988 rec.key.allResolvedTypes = resolvedTypes;
3989 } else {
3990 rec.key.allIntents = null;
3991 rec.key.allResolvedTypes = null;
3992 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 return rec;
3995 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003996 rec.canceled = true;
3997 mIntentSenderRecords.remove(key);
3998 }
3999 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 return rec;
4001 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004002 rec = new PendingIntentRecord(this, key, callingUid);
4003 mIntentSenderRecords.put(key, rec.ref);
4004 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4005 if (activity.pendingResults == null) {
4006 activity.pendingResults
4007 = new HashSet<WeakReference<PendingIntentRecord>>();
4008 }
4009 activity.pendingResults.add(rec.ref);
4010 }
4011 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 }
4013
4014 public void cancelIntentSender(IIntentSender sender) {
4015 if (!(sender instanceof PendingIntentRecord)) {
4016 return;
4017 }
4018 synchronized(this) {
4019 PendingIntentRecord rec = (PendingIntentRecord)sender;
4020 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004021 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 .getPackageUid(rec.key.packageName);
4023 if (uid != Binder.getCallingUid()) {
4024 String msg = "Permission Denial: cancelIntentSender() from pid="
4025 + Binder.getCallingPid()
4026 + ", uid=" + Binder.getCallingUid()
4027 + " is not allowed to cancel packges "
4028 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004029 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 throw new SecurityException(msg);
4031 }
4032 } catch (RemoteException e) {
4033 throw new SecurityException(e);
4034 }
4035 cancelIntentSenderLocked(rec, true);
4036 }
4037 }
4038
4039 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4040 rec.canceled = true;
4041 mIntentSenderRecords.remove(rec.key);
4042 if (cleanActivity && rec.key.activity != null) {
4043 rec.key.activity.pendingResults.remove(rec.ref);
4044 }
4045 }
4046
4047 public String getPackageForIntentSender(IIntentSender pendingResult) {
4048 if (!(pendingResult instanceof PendingIntentRecord)) {
4049 return null;
4050 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004051 try {
4052 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4053 return res.key.packageName;
4054 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 }
4056 return null;
4057 }
4058
4059 public void setProcessLimit(int max) {
4060 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4061 "setProcessLimit()");
4062 mProcessLimit = max;
4063 }
4064
4065 public int getProcessLimit() {
4066 return mProcessLimit;
4067 }
4068
4069 void foregroundTokenDied(ForegroundToken token) {
4070 synchronized (ActivityManagerService.this) {
4071 synchronized (mPidsSelfLocked) {
4072 ForegroundToken cur
4073 = mForegroundProcesses.get(token.pid);
4074 if (cur != token) {
4075 return;
4076 }
4077 mForegroundProcesses.remove(token.pid);
4078 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4079 if (pr == null) {
4080 return;
4081 }
4082 pr.forcingToForeground = null;
4083 pr.foregroundServices = false;
4084 }
4085 updateOomAdjLocked();
4086 }
4087 }
4088
4089 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4090 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4091 "setProcessForeground()");
4092 synchronized(this) {
4093 boolean changed = false;
4094
4095 synchronized (mPidsSelfLocked) {
4096 ProcessRecord pr = mPidsSelfLocked.get(pid);
4097 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004098 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 return;
4100 }
4101 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4102 if (oldToken != null) {
4103 oldToken.token.unlinkToDeath(oldToken, 0);
4104 mForegroundProcesses.remove(pid);
4105 pr.forcingToForeground = null;
4106 changed = true;
4107 }
4108 if (isForeground && token != null) {
4109 ForegroundToken newToken = new ForegroundToken() {
4110 public void binderDied() {
4111 foregroundTokenDied(this);
4112 }
4113 };
4114 newToken.pid = pid;
4115 newToken.token = token;
4116 try {
4117 token.linkToDeath(newToken, 0);
4118 mForegroundProcesses.put(pid, newToken);
4119 pr.forcingToForeground = token;
4120 changed = true;
4121 } catch (RemoteException e) {
4122 // If the process died while doing this, we will later
4123 // do the cleanup with the process death link.
4124 }
4125 }
4126 }
4127
4128 if (changed) {
4129 updateOomAdjLocked();
4130 }
4131 }
4132 }
4133
4134 // =========================================================
4135 // PERMISSIONS
4136 // =========================================================
4137
4138 static class PermissionController extends IPermissionController.Stub {
4139 ActivityManagerService mActivityManagerService;
4140 PermissionController(ActivityManagerService activityManagerService) {
4141 mActivityManagerService = activityManagerService;
4142 }
4143
4144 public boolean checkPermission(String permission, int pid, int uid) {
4145 return mActivityManagerService.checkPermission(permission, pid,
4146 uid) == PackageManager.PERMISSION_GRANTED;
4147 }
4148 }
4149
4150 /**
4151 * This can be called with or without the global lock held.
4152 */
4153 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004154 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 // We might be performing an operation on behalf of an indirect binder
4156 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4157 // client identity accordingly before proceeding.
4158 Identity tlsIdentity = sCallerIdentity.get();
4159 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004160 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4162 uid = tlsIdentity.uid;
4163 pid = tlsIdentity.pid;
4164 }
4165
4166 // Root, system server and our own process get to do everything.
4167 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4168 !Process.supportsProcesses()) {
4169 return PackageManager.PERMISSION_GRANTED;
4170 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004171 // If there is a uid that owns whatever is being accessed, it has
4172 // blanket access to it regardless of the permissions it requires.
4173 if (owningUid >= 0 && uid == owningUid) {
4174 return PackageManager.PERMISSION_GRANTED;
4175 }
4176 // If the target is not exported, then nobody else can get to it.
4177 if (!exported) {
4178 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 return PackageManager.PERMISSION_DENIED;
4180 }
4181 if (permission == null) {
4182 return PackageManager.PERMISSION_GRANTED;
4183 }
4184 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004185 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 .checkUidPermission(permission, uid);
4187 } catch (RemoteException e) {
4188 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004189 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 }
4191 return PackageManager.PERMISSION_DENIED;
4192 }
4193
4194 /**
4195 * As the only public entry point for permissions checking, this method
4196 * can enforce the semantic that requesting a check on a null global
4197 * permission is automatically denied. (Internally a null permission
4198 * string is used when calling {@link #checkComponentPermission} in cases
4199 * when only uid-based security is needed.)
4200 *
4201 * This can be called with or without the global lock held.
4202 */
4203 public int checkPermission(String permission, int pid, int uid) {
4204 if (permission == null) {
4205 return PackageManager.PERMISSION_DENIED;
4206 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004207 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 }
4209
4210 /**
4211 * Binder IPC calls go through the public entry point.
4212 * This can be called with or without the global lock held.
4213 */
4214 int checkCallingPermission(String permission) {
4215 return checkPermission(permission,
4216 Binder.getCallingPid(),
4217 Binder.getCallingUid());
4218 }
4219
4220 /**
4221 * This can be called with or without the global lock held.
4222 */
4223 void enforceCallingPermission(String permission, String func) {
4224 if (checkCallingPermission(permission)
4225 == PackageManager.PERMISSION_GRANTED) {
4226 return;
4227 }
4228
4229 String msg = "Permission Denial: " + func + " from pid="
4230 + Binder.getCallingPid()
4231 + ", uid=" + Binder.getCallingUid()
4232 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004233 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 throw new SecurityException(msg);
4235 }
4236
4237 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004238 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4239 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4240 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4241 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4242 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004244 // Is the component private from the target uid?
4245 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4246
4247 // Acceptable if the there is no read permission needed from the
4248 // target or the target is holding the read permission.
4249 if (!readPerm) {
4250 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004252 == PackageManager.PERMISSION_GRANTED)) {
4253 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 }
4255 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004256
4257 // Acceptable if the there is no write permission needed from the
4258 // target or the target is holding the read permission.
4259 if (!writePerm) {
4260 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004262 == PackageManager.PERMISSION_GRANTED)) {
4263 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 }
4265 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004266
4267 // Acceptable if there is a path permission matching the URI that
4268 // the target holds the permission on.
4269 PathPermission[] pps = pi.pathPermissions;
4270 if (pps != null && (!readPerm || !writePerm)) {
4271 final String path = uri.getPath();
4272 int i = pps.length;
4273 while (i > 0 && (!readPerm || !writePerm)) {
4274 i--;
4275 PathPermission pp = pps[i];
4276 if (!readPerm) {
4277 final String pprperm = pp.getReadPermission();
4278 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4279 + pprperm + " for " + pp.getPath()
4280 + ": match=" + pp.match(path)
4281 + " check=" + pm.checkUidPermission(pprperm, uid));
4282 if (pprperm != null && pp.match(path) &&
4283 (pm.checkUidPermission(pprperm, uid)
4284 == PackageManager.PERMISSION_GRANTED)) {
4285 readPerm = true;
4286 }
4287 }
4288 if (!writePerm) {
4289 final String ppwperm = pp.getWritePermission();
4290 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4291 + ppwperm + " for " + pp.getPath()
4292 + ": match=" + pp.match(path)
4293 + " check=" + pm.checkUidPermission(ppwperm, uid));
4294 if (ppwperm != null && pp.match(path) &&
4295 (pm.checkUidPermission(ppwperm, uid)
4296 == PackageManager.PERMISSION_GRANTED)) {
4297 writePerm = true;
4298 }
4299 }
4300 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 } catch (RemoteException e) {
4303 return false;
4304 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004305
4306 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4310 int modeFlags) {
4311 // Root gets to do everything.
4312 if (uid == 0 || !Process.supportsProcesses()) {
4313 return true;
4314 }
4315 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4316 if (perms == null) return false;
4317 UriPermission perm = perms.get(uri);
4318 if (perm == null) return false;
4319 return (modeFlags&perm.modeFlags) == modeFlags;
4320 }
4321
4322 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4323 // Another redirected-binder-call permissions check as in
4324 // {@link checkComponentPermission}.
4325 Identity tlsIdentity = sCallerIdentity.get();
4326 if (tlsIdentity != null) {
4327 uid = tlsIdentity.uid;
4328 pid = tlsIdentity.pid;
4329 }
4330
4331 // Our own process gets to do everything.
4332 if (pid == MY_PID) {
4333 return PackageManager.PERMISSION_GRANTED;
4334 }
4335 synchronized(this) {
4336 return checkUriPermissionLocked(uri, uid, modeFlags)
4337 ? PackageManager.PERMISSION_GRANTED
4338 : PackageManager.PERMISSION_DENIED;
4339 }
4340 }
4341
Dianne Hackborn39792d22010-08-19 18:01:52 -07004342 /**
4343 * Check if the targetPkg can be granted permission to access uri by
4344 * the callingUid using the given modeFlags. Throws a security exception
4345 * if callingUid is not allowed to do this. Returns the uid of the target
4346 * if the URI permission grant should be performed; returns -1 if it is not
4347 * needed (for example targetPkg already has permission to access the URI).
4348 */
4349 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4350 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4352 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4353 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004354 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 }
4356
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004357 if (targetPkg != null) {
4358 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4359 "Checking grant " + targetPkg + " permission to " + uri);
4360 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004361
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004362 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363
4364 // If this is not a content: uri, we can't do anything with it.
4365 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004366 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004367 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004368 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 }
4370
4371 String name = uri.getAuthority();
4372 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004373 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 if (cpr != null) {
4375 pi = cpr.info;
4376 } else {
4377 try {
4378 pi = pm.resolveContentProvider(name,
4379 PackageManager.GET_URI_PERMISSION_PATTERNS);
4380 } catch (RemoteException ex) {
4381 }
4382 }
4383 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004384 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004385 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 }
4387
4388 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004389 if (targetPkg != null) {
4390 try {
4391 targetUid = pm.getPackageUid(targetPkg);
4392 if (targetUid < 0) {
4393 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4394 "Can't grant URI permission no uid for: " + targetPkg);
4395 return -1;
4396 }
4397 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004398 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004400 } else {
4401 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 }
4403
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004404 if (targetUid >= 0) {
4405 // First... does the target actually need this permission?
4406 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4407 // No need to grant the target this permission.
4408 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4409 "Target " + targetPkg + " already has full permission to " + uri);
4410 return -1;
4411 }
4412 } else {
4413 // First... there is no target package, so can anyone access it?
4414 boolean allowed = pi.exported;
4415 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4416 if (pi.readPermission != null) {
4417 allowed = false;
4418 }
4419 }
4420 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4421 if (pi.writePermission != null) {
4422 allowed = false;
4423 }
4424 }
4425 if (allowed) {
4426 return -1;
4427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 }
4429
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004430 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 if (!pi.grantUriPermissions) {
4432 throw new SecurityException("Provider " + pi.packageName
4433 + "/" + pi.name
4434 + " does not allow granting of Uri permissions (uri "
4435 + uri + ")");
4436 }
4437 if (pi.uriPermissionPatterns != null) {
4438 final int N = pi.uriPermissionPatterns.length;
4439 boolean allowed = false;
4440 for (int i=0; i<N; i++) {
4441 if (pi.uriPermissionPatterns[i] != null
4442 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4443 allowed = true;
4444 break;
4445 }
4446 }
4447 if (!allowed) {
4448 throw new SecurityException("Provider " + pi.packageName
4449 + "/" + pi.name
4450 + " does not allow granting of permission to path of Uri "
4451 + uri);
4452 }
4453 }
4454
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004455 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004457 if (callingUid != Process.myUid()) {
4458 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4459 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4460 throw new SecurityException("Uid " + callingUid
4461 + " does not have permission to uri " + uri);
4462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 }
4464 }
4465
Dianne Hackborn39792d22010-08-19 18:01:52 -07004466 return targetUid;
4467 }
4468
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004469 public int checkGrantUriPermission(int callingUid, String targetPkg,
4470 Uri uri, int modeFlags) {
4471 synchronized(this) {
4472 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4473 }
4474 }
4475
Dianne Hackborn39792d22010-08-19 18:01:52 -07004476 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4477 Uri uri, int modeFlags, UriPermissionOwner owner) {
4478 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4479 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4480 if (modeFlags == 0) {
4481 return;
4482 }
4483
4484 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 // to the uri, and the target doesn't. Let's now give this to
4486 // the target.
4487
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004489 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 HashMap<Uri, UriPermission> targetUris
4492 = mGrantedUriPermissions.get(targetUid);
4493 if (targetUris == null) {
4494 targetUris = new HashMap<Uri, UriPermission>();
4495 mGrantedUriPermissions.put(targetUid, targetUris);
4496 }
4497
4498 UriPermission perm = targetUris.get(uri);
4499 if (perm == null) {
4500 perm = new UriPermission(targetUid, uri);
4501 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004505 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 perm.globalModeFlags |= modeFlags;
4507 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004508 perm.readOwners.add(owner);
4509 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004511 perm.writeOwners.add(owner);
4512 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 }
4514 }
4515
Dianne Hackborn39792d22010-08-19 18:01:52 -07004516 void grantUriPermissionLocked(int callingUid,
4517 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004518 if (targetPkg == null) {
4519 throw new NullPointerException("targetPkg");
4520 }
4521
Dianne Hackborn39792d22010-08-19 18:01:52 -07004522 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4523 if (targetUid < 0) {
4524 return;
4525 }
4526
4527 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4528 }
4529
4530 /**
4531 * Like checkGrantUriPermissionLocked, but takes an Intent.
4532 */
4533 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4534 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004535 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004536 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004537 + " from " + intent + "; flags=0x"
4538 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4539
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004540 if (targetPkg == null) {
4541 throw new NullPointerException("targetPkg");
4542 }
4543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004545 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 }
4547 Uri data = intent.getData();
4548 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004549 return -1;
4550 }
4551 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4552 intent.getFlags());
4553 }
4554
4555 /**
4556 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4557 */
4558 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4559 String targetPkg, Intent intent, UriPermissionOwner owner) {
4560 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4561 intent.getFlags(), owner);
4562 }
4563
4564 void grantUriPermissionFromIntentLocked(int callingUid,
4565 String targetPkg, Intent intent, UriPermissionOwner owner) {
4566 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4567 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 return;
4569 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004570
4571 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 }
4573
4574 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4575 Uri uri, int modeFlags) {
4576 synchronized(this) {
4577 final ProcessRecord r = getRecordForAppLocked(caller);
4578 if (r == null) {
4579 throw new SecurityException("Unable to find app for caller "
4580 + caller
4581 + " when granting permission to uri " + uri);
4582 }
4583 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004584 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 }
4586 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004587 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 }
4589
4590 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4591 null);
4592 }
4593 }
4594
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004595 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4597 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4598 HashMap<Uri, UriPermission> perms
4599 = mGrantedUriPermissions.get(perm.uid);
4600 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004601 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004602 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 perms.remove(perm.uri);
4604 if (perms.size() == 0) {
4605 mGrantedUriPermissions.remove(perm.uid);
4606 }
4607 }
4608 }
4609 }
4610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4612 int modeFlags) {
4613 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4614 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4615 if (modeFlags == 0) {
4616 return;
4617 }
4618
Joe Onorato8a9b2202010-02-26 18:56:32 -08004619 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004620 "Revoking all granted permissions to " + uri);
4621
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004622 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623
4624 final String authority = uri.getAuthority();
4625 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004626 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 if (cpr != null) {
4628 pi = cpr.info;
4629 } else {
4630 try {
4631 pi = pm.resolveContentProvider(authority,
4632 PackageManager.GET_URI_PERMISSION_PATTERNS);
4633 } catch (RemoteException ex) {
4634 }
4635 }
4636 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004637 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 return;
4639 }
4640
4641 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004642 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 // Right now, if you are not the original owner of the permission,
4644 // you are not allowed to revoke it.
4645 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4646 throw new SecurityException("Uid " + callingUid
4647 + " does not have permission to uri " + uri);
4648 //}
4649 }
4650
4651 // Go through all of the permissions and remove any that match.
4652 final List<String> SEGMENTS = uri.getPathSegments();
4653 if (SEGMENTS != null) {
4654 final int NS = SEGMENTS.size();
4655 int N = mGrantedUriPermissions.size();
4656 for (int i=0; i<N; i++) {
4657 HashMap<Uri, UriPermission> perms
4658 = mGrantedUriPermissions.valueAt(i);
4659 Iterator<UriPermission> it = perms.values().iterator();
4660 toploop:
4661 while (it.hasNext()) {
4662 UriPermission perm = it.next();
4663 Uri targetUri = perm.uri;
4664 if (!authority.equals(targetUri.getAuthority())) {
4665 continue;
4666 }
4667 List<String> targetSegments = targetUri.getPathSegments();
4668 if (targetSegments == null) {
4669 continue;
4670 }
4671 if (targetSegments.size() < NS) {
4672 continue;
4673 }
4674 for (int j=0; j<NS; j++) {
4675 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4676 continue toploop;
4677 }
4678 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004679 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004680 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 perm.clearModes(modeFlags);
4682 if (perm.modeFlags == 0) {
4683 it.remove();
4684 }
4685 }
4686 if (perms.size() == 0) {
4687 mGrantedUriPermissions.remove(
4688 mGrantedUriPermissions.keyAt(i));
4689 N--;
4690 i--;
4691 }
4692 }
4693 }
4694 }
4695
4696 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4697 int modeFlags) {
4698 synchronized(this) {
4699 final ProcessRecord r = getRecordForAppLocked(caller);
4700 if (r == null) {
4701 throw new SecurityException("Unable to find app for caller "
4702 + caller
4703 + " when revoking permission to uri " + uri);
4704 }
4705 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004706 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 return;
4708 }
4709
4710 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4711 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4712 if (modeFlags == 0) {
4713 return;
4714 }
4715
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004716 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717
4718 final String authority = uri.getAuthority();
4719 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004720 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 if (cpr != null) {
4722 pi = cpr.info;
4723 } else {
4724 try {
4725 pi = pm.resolveContentProvider(authority,
4726 PackageManager.GET_URI_PERMISSION_PATTERNS);
4727 } catch (RemoteException ex) {
4728 }
4729 }
4730 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004731 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 return;
4733 }
4734
4735 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4736 }
4737 }
4738
Dianne Hackborn7e269642010-08-25 19:50:20 -07004739 @Override
4740 public IBinder newUriPermissionOwner(String name) {
4741 synchronized(this) {
4742 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4743 return owner.getExternalTokenLocked();
4744 }
4745 }
4746
4747 @Override
4748 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4749 Uri uri, int modeFlags) {
4750 synchronized(this) {
4751 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4752 if (owner == null) {
4753 throw new IllegalArgumentException("Unknown owner: " + token);
4754 }
4755 if (fromUid != Binder.getCallingUid()) {
4756 if (Binder.getCallingUid() != Process.myUid()) {
4757 // Only system code can grant URI permissions on behalf
4758 // of other users.
4759 throw new SecurityException("nice try");
4760 }
4761 }
4762 if (targetPkg == null) {
4763 throw new IllegalArgumentException("null target");
4764 }
4765 if (uri == null) {
4766 throw new IllegalArgumentException("null uri");
4767 }
4768
4769 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4770 }
4771 }
4772
4773 @Override
4774 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4775 synchronized(this) {
4776 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4777 if (owner == null) {
4778 throw new IllegalArgumentException("Unknown owner: " + token);
4779 }
4780
4781 if (uri == null) {
4782 owner.removeUriPermissionsLocked(mode);
4783 } else {
4784 owner.removeUriPermissionLocked(uri, mode);
4785 }
4786 }
4787 }
4788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4790 synchronized (this) {
4791 ProcessRecord app =
4792 who != null ? getRecordForAppLocked(who) : null;
4793 if (app == null) return;
4794
4795 Message msg = Message.obtain();
4796 msg.what = WAIT_FOR_DEBUGGER_MSG;
4797 msg.obj = app;
4798 msg.arg1 = waiting ? 1 : 0;
4799 mHandler.sendMessage(msg);
4800 }
4801 }
4802
4803 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4804 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004805 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004807 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 }
4809
4810 // =========================================================
4811 // TASK MANAGEMENT
4812 // =========================================================
4813
4814 public List getTasks(int maxNum, int flags,
4815 IThumbnailReceiver receiver) {
4816 ArrayList list = new ArrayList();
4817
4818 PendingThumbnailsRecord pending = null;
4819 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004820 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821
4822 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004823 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4825 + ", receiver=" + receiver);
4826
4827 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4828 != PackageManager.PERMISSION_GRANTED) {
4829 if (receiver != null) {
4830 // If the caller wants to wait for pending thumbnails,
4831 // it ain't gonna get them.
4832 try {
4833 receiver.finished();
4834 } catch (RemoteException ex) {
4835 }
4836 }
4837 String msg = "Permission Denial: getTasks() from pid="
4838 + Binder.getCallingPid()
4839 + ", uid=" + Binder.getCallingUid()
4840 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004841 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004842 throw new SecurityException(msg);
4843 }
4844
Dianne Hackbornd2835932010-12-13 16:28:46 -08004845 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4846 && checkCallingPermission(
4847 android.Manifest.permission.READ_FRAME_BUFFER)
4848 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004849
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004850 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004851 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004852 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004853 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 CharSequence topDescription = null;
4855 TaskRecord curTask = null;
4856 int numActivities = 0;
4857 int numRunning = 0;
4858 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004859 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004861 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862
4863 // Initialize state for next task if needed.
4864 if (top == null ||
4865 (top.state == ActivityState.INITIALIZING
4866 && top.task == r.task)) {
4867 top = r;
4868 topDescription = r.description;
4869 curTask = r.task;
4870 numActivities = numRunning = 0;
4871 }
4872
4873 // Add 'r' into the current task.
4874 numActivities++;
4875 if (r.app != null && r.app.thread != null) {
4876 numRunning++;
4877 }
4878 if (topDescription == null) {
4879 topDescription = r.description;
4880 }
4881
Joe Onorato8a9b2202010-02-26 18:56:32 -08004882 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 TAG, r.intent.getComponent().flattenToShortString()
4884 + ": task=" + r.task);
4885
4886 // If the next one is a different task, generate a new
4887 // TaskInfo entry for what we have.
4888 if (next == null || next.task != curTask) {
4889 ActivityManager.RunningTaskInfo ci
4890 = new ActivityManager.RunningTaskInfo();
4891 ci.id = curTask.taskId;
4892 ci.baseActivity = r.intent.getComponent();
4893 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004894 if (canReadFb) {
4895 if (top.thumbnail != null) {
4896 ci.thumbnail = top.thumbnail;
4897 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004898 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004899 }
4900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 ci.description = topDescription;
4902 ci.numActivities = numActivities;
4903 ci.numRunning = numRunning;
4904 //System.out.println(
4905 // "#" + maxNum + ": " + " descr=" + ci.description);
4906 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004907 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 TAG, "State=" + top.state + "Idle=" + top.idle
4909 + " app=" + top.app
4910 + " thr=" + (top.app != null ? top.app.thread : null));
4911 if (top.state == ActivityState.RESUMED
4912 || top.state == ActivityState.PAUSING) {
4913 if (top.idle && top.app != null
4914 && top.app.thread != null) {
4915 topRecord = top;
4916 topThumbnail = top.app.thread;
4917 } else {
4918 top.thumbnailNeeded = true;
4919 }
4920 }
4921 if (pending == null) {
4922 pending = new PendingThumbnailsRecord(receiver);
4923 }
4924 pending.pendingRecords.add(top);
4925 }
4926 list.add(ci);
4927 maxNum--;
4928 top = null;
4929 }
4930 }
4931
4932 if (pending != null) {
4933 mPendingThumbnails.add(pending);
4934 }
4935 }
4936
Joe Onorato8a9b2202010-02-26 18:56:32 -08004937 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004938
4939 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004940 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 try {
4942 topThumbnail.requestThumbnail(topRecord);
4943 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 sendPendingThumbnail(null, topRecord, null, null, true);
4946 }
4947 }
4948
4949 if (pending == null && receiver != null) {
4950 // In this case all thumbnails were available and the client
4951 // is being asked to be told when the remaining ones come in...
4952 // which is unusually, since the top-most currently running
4953 // activity should never have a canned thumbnail! Oh well.
4954 try {
4955 receiver.finished();
4956 } catch (RemoteException ex) {
4957 }
4958 }
4959
4960 return list;
4961 }
4962
4963 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4964 int flags) {
4965 synchronized (this) {
4966 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4967 "getRecentTasks()");
4968
Dianne Hackbornd2835932010-12-13 16:28:46 -08004969 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4970 && checkCallingPermission(
4971 android.Manifest.permission.READ_FRAME_BUFFER)
4972 == PackageManager.PERMISSION_GRANTED;
4973
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004974 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004975
Dianne Hackbornd2835932010-12-13 16:28:46 -08004976 ActivityRecord resumed = mMainStack.mResumedActivity;
4977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 final int N = mRecentTasks.size();
4979 ArrayList<ActivityManager.RecentTaskInfo> res
4980 = new ArrayList<ActivityManager.RecentTaskInfo>(
4981 maxNum < N ? maxNum : N);
4982 for (int i=0; i<N && maxNum > 0; i++) {
4983 TaskRecord tr = mRecentTasks.get(i);
4984 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4985 || (tr.intent == null)
4986 || ((tr.intent.getFlags()
4987 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4988 ActivityManager.RecentTaskInfo rti
4989 = new ActivityManager.RecentTaskInfo();
4990 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4991 rti.baseIntent = new Intent(
4992 tr.intent != null ? tr.intent : tr.affinityIntent);
4993 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004994
Dianne Hackbornd2835932010-12-13 16:28:46 -08004995 if (canReadFb) {
4996 if (resumed != null && resumed.task == tr) {
4997 rti.thumbnail = resumed.stack.screenshotActivities(resumed);
4998 } else {
4999 rti.thumbnail = tr.lastThumbnail;
5000 }
5001 }
5002 rti.description = tr.lastDescription;
5003
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005004 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5005 // Check whether this activity is currently available.
5006 try {
5007 if (rti.origActivity != null) {
5008 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5009 continue;
5010 }
5011 } else if (rti.baseIntent != null) {
5012 if (pm.queryIntentActivities(rti.baseIntent,
5013 null, 0) == null) {
5014 continue;
5015 }
5016 }
5017 } catch (RemoteException e) {
5018 // Will never happen.
5019 }
5020 }
5021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 res.add(rti);
5023 maxNum--;
5024 }
5025 }
5026 return res;
5027 }
5028 }
5029
5030 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5031 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005032 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 TaskRecord jt = startTask;
5034
5035 // First look backwards
5036 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005037 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 if (r.task != jt) {
5039 jt = r.task;
5040 if (affinity.equals(jt.affinity)) {
5041 return j;
5042 }
5043 }
5044 }
5045
5046 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005047 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 jt = startTask;
5049 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005050 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 if (r.task != jt) {
5052 if (affinity.equals(jt.affinity)) {
5053 return j;
5054 }
5055 jt = r.task;
5056 }
5057 }
5058
5059 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005060 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 return N-1;
5062 }
5063
5064 return -1;
5065 }
5066
5067 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005068 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005070 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5072 "moveTaskToFront()");
5073
5074 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005075 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5076 Binder.getCallingUid(), "Task to front")) {
5077 return;
5078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 final long origId = Binder.clearCallingIdentity();
5080 try {
5081 int N = mRecentTasks.size();
5082 for (int i=0; i<N; i++) {
5083 TaskRecord tr = mRecentTasks.get(i);
5084 if (tr.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005085 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5086 // Caller wants the home activity moved with it. To accomplish this,
5087 // we'll just move the home task to the top first.
5088 mMainStack.moveHomeToFrontLocked();
5089 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005090 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091 return;
5092 }
5093 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005094 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5095 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 if (hr.task.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005097 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5098 // Caller wants the home activity moved with it. To accomplish this,
5099 // we'll just move the home task to the top first.
5100 mMainStack.moveHomeToFrontLocked();
5101 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005102 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 return;
5104 }
5105 }
5106 } finally {
5107 Binder.restoreCallingIdentity(origId);
5108 }
5109 }
5110 }
5111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 public void moveTaskToBack(int task) {
5113 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5114 "moveTaskToBack()");
5115
5116 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005117 if (mMainStack.mResumedActivity != null
5118 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005119 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5120 Binder.getCallingUid(), "Task to back")) {
5121 return;
5122 }
5123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005125 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005126 Binder.restoreCallingIdentity(origId);
5127 }
5128 }
5129
5130 /**
5131 * Moves an activity, and all of the other activities within the same task, to the bottom
5132 * of the history stack. The activity's order within the task is unchanged.
5133 *
5134 * @param token A reference to the activity we wish to move
5135 * @param nonRoot If false then this only works if the activity is the root
5136 * of a task; if true it will work for any activity in a task.
5137 * @return Returns true if the move completed, false if not.
5138 */
5139 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5140 synchronized(this) {
5141 final long origId = Binder.clearCallingIdentity();
5142 int taskId = getTaskForActivityLocked(token, !nonRoot);
5143 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005144 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 }
5146 Binder.restoreCallingIdentity(origId);
5147 }
5148 return false;
5149 }
5150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 public void moveTaskBackwards(int task) {
5152 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5153 "moveTaskBackwards()");
5154
5155 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005156 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5157 Binder.getCallingUid(), "Task backwards")) {
5158 return;
5159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 final long origId = Binder.clearCallingIdentity();
5161 moveTaskBackwardsLocked(task);
5162 Binder.restoreCallingIdentity(origId);
5163 }
5164 }
5165
5166 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005167 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 }
5169
5170 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5171 synchronized(this) {
5172 return getTaskForActivityLocked(token, onlyRoot);
5173 }
5174 }
5175
5176 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005177 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 TaskRecord lastTask = null;
5179 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005180 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 if (r == token) {
5182 if (!onlyRoot || lastTask != r.task) {
5183 return r.task.taskId;
5184 }
5185 return -1;
5186 }
5187 lastTask = r.task;
5188 }
5189
5190 return -1;
5191 }
5192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 public void finishOtherInstances(IBinder token, ComponentName className) {
5194 synchronized(this) {
5195 final long origId = Binder.clearCallingIdentity();
5196
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005197 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 TaskRecord lastTask = null;
5199 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005200 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 if (r.realActivity.equals(className)
5202 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005203 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 null, "others")) {
5205 i--;
5206 N--;
5207 }
5208 }
5209 lastTask = r.task;
5210 }
5211
5212 Binder.restoreCallingIdentity(origId);
5213 }
5214 }
5215
5216 // =========================================================
5217 // THUMBNAILS
5218 // =========================================================
5219
5220 public void reportThumbnail(IBinder token,
5221 Bitmap thumbnail, CharSequence description) {
5222 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5223 final long origId = Binder.clearCallingIdentity();
5224 sendPendingThumbnail(null, token, thumbnail, description, true);
5225 Binder.restoreCallingIdentity(origId);
5226 }
5227
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005228 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 Bitmap thumbnail, CharSequence description, boolean always) {
5230 TaskRecord task = null;
5231 ArrayList receivers = null;
5232
5233 //System.out.println("Send pending thumbnail: " + r);
5234
5235 synchronized(this) {
5236 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005237 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 if (index < 0) {
5239 return;
5240 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005241 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 }
5243 if (thumbnail == null) {
5244 thumbnail = r.thumbnail;
5245 description = r.description;
5246 }
5247 if (thumbnail == null && !always) {
5248 // If there is no thumbnail, and this entry is not actually
5249 // going away, then abort for now and pick up the next
5250 // thumbnail we get.
5251 return;
5252 }
5253 task = r.task;
5254
5255 int N = mPendingThumbnails.size();
5256 int i=0;
5257 while (i<N) {
5258 PendingThumbnailsRecord pr =
5259 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5260 //System.out.println("Looking in " + pr.pendingRecords);
5261 if (pr.pendingRecords.remove(r)) {
5262 if (receivers == null) {
5263 receivers = new ArrayList();
5264 }
5265 receivers.add(pr);
5266 if (pr.pendingRecords.size() == 0) {
5267 pr.finished = true;
5268 mPendingThumbnails.remove(i);
5269 N--;
5270 continue;
5271 }
5272 }
5273 i++;
5274 }
5275 }
5276
5277 if (receivers != null) {
5278 final int N = receivers.size();
5279 for (int i=0; i<N; i++) {
5280 try {
5281 PendingThumbnailsRecord pr =
5282 (PendingThumbnailsRecord)receivers.get(i);
5283 pr.receiver.newThumbnail(
5284 task != null ? task.taskId : -1, thumbnail, description);
5285 if (pr.finished) {
5286 pr.receiver.finished();
5287 }
5288 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005289 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 }
5291 }
5292 }
5293 }
5294
5295 // =========================================================
5296 // CONTENT PROVIDERS
5297 // =========================================================
5298
5299 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5300 List providers = null;
5301 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005302 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005304 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 } catch (RemoteException ex) {
5306 }
5307 if (providers != null) {
5308 final int N = providers.size();
5309 for (int i=0; i<N; i++) {
5310 ProviderInfo cpi =
5311 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005312 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005313 if (cpr == null) {
5314 cpr = new ContentProviderRecord(cpi, app.info);
5315 mProvidersByClass.put(cpi.name, cpr);
5316 }
5317 app.pubProviders.put(cpi.name, cpr);
5318 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005319 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 }
5321 }
5322 return providers;
5323 }
5324
5325 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005326 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5328 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5329 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005330 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005331 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 return null;
5333 }
5334 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005335 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005336 == PackageManager.PERMISSION_GRANTED) {
5337 return null;
5338 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005339
5340 PathPermission[] pps = cpi.pathPermissions;
5341 if (pps != null) {
5342 int i = pps.length;
5343 while (i > 0) {
5344 i--;
5345 PathPermission pp = pps[i];
5346 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005347 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005348 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005349 return null;
5350 }
5351 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005352 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005353 == PackageManager.PERMISSION_GRANTED) {
5354 return null;
5355 }
5356 }
5357 }
5358
Dianne Hackbornb424b632010-08-18 15:59:05 -07005359 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5360 if (perms != null) {
5361 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5362 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5363 return null;
5364 }
5365 }
5366 }
5367
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005368 String msg;
5369 if (!cpi.exported) {
5370 msg = "Permission Denial: opening provider " + cpi.name
5371 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5372 + ", uid=" + callingUid + ") that is not exported from uid "
5373 + cpi.applicationInfo.uid;
5374 } else {
5375 msg = "Permission Denial: opening provider " + cpi.name
5376 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5377 + ", uid=" + callingUid + ") requires "
5378 + cpi.readPermission + " or " + cpi.writePermission;
5379 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005380 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 return msg;
5382 }
5383
5384 private final ContentProviderHolder getContentProviderImpl(
5385 IApplicationThread caller, String name) {
5386 ContentProviderRecord cpr;
5387 ProviderInfo cpi = null;
5388
5389 synchronized(this) {
5390 ProcessRecord r = null;
5391 if (caller != null) {
5392 r = getRecordForAppLocked(caller);
5393 if (r == null) {
5394 throw new SecurityException(
5395 "Unable to find app for caller " + caller
5396 + " (pid=" + Binder.getCallingPid()
5397 + ") when getting content provider " + name);
5398 }
5399 }
5400
5401 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005402 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 if (cpr != null) {
5404 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005405 String msg;
5406 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5407 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 }
5409
5410 if (r != null && cpr.canRunHere(r)) {
5411 // This provider has been published or is in the process
5412 // of being published... but it is also allowed to run
5413 // in the caller's process, so don't make a connection
5414 // and just let the caller instantiate its own instance.
5415 if (cpr.provider != null) {
5416 // don't give caller the provider object, it needs
5417 // to make its own.
5418 cpr = new ContentProviderRecord(cpr);
5419 }
5420 return cpr;
5421 }
5422
5423 final long origId = Binder.clearCallingIdentity();
5424
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005425 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 // return it right away.
5427 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005428 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005429 "Adding provider requested by "
5430 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005431 + cpr.info.processName);
5432 Integer cnt = r.conProviders.get(cpr);
5433 if (cnt == null) {
5434 r.conProviders.put(cpr, new Integer(1));
5435 } else {
5436 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005439 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5440 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005441 // make sure to count it as being accessed and thus
5442 // back up on the LRU list. This is good because
5443 // content providers are often expensive to start.
5444 updateLruProcessLocked(cpr.app, false, true);
5445 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005446 } else {
5447 cpr.externals++;
5448 }
5449
5450 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 updateOomAdjLocked(cpr.app);
5452 }
5453
5454 Binder.restoreCallingIdentity(origId);
5455
5456 } else {
5457 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005458 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005459 resolveContentProvider(name,
5460 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005461 } catch (RemoteException ex) {
5462 }
5463 if (cpi == null) {
5464 return null;
5465 }
5466
Dianne Hackbornb424b632010-08-18 15:59:05 -07005467 String msg;
5468 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5469 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 }
5471
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005472 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005473 && !cpi.processName.equals("system")) {
5474 // If this content provider does not run in the system
5475 // process, and the system is not yet ready to run other
5476 // processes, then fail fast instead of hanging.
5477 throw new IllegalArgumentException(
5478 "Attempt to launch content provider before system ready");
5479 }
5480
Dianne Hackborn860755f2010-06-03 18:47:52 -07005481 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 final boolean firstClass = cpr == null;
5483 if (firstClass) {
5484 try {
5485 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005486 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 getApplicationInfo(
5488 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005489 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005491 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 + cpi.name);
5493 return null;
5494 }
5495 cpr = new ContentProviderRecord(cpi, ai);
5496 } catch (RemoteException ex) {
5497 // pm is in same process, this will never happen.
5498 }
5499 }
5500
5501 if (r != null && cpr.canRunHere(r)) {
5502 // If this is a multiprocess provider, then just return its
5503 // info and allow the caller to instantiate it. Only do
5504 // this if the provider is the same user as the caller's
5505 // process, or can run as root (so can be in any process).
5506 return cpr;
5507 }
5508
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005509 if (DEBUG_PROVIDER) {
5510 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005511 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005512 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 }
5514
5515 // This is single process, and our app is now connecting to it.
5516 // See if we are already in the process of launching this
5517 // provider.
5518 final int N = mLaunchingProviders.size();
5519 int i;
5520 for (i=0; i<N; i++) {
5521 if (mLaunchingProviders.get(i) == cpr) {
5522 break;
5523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 }
5525
5526 // If the provider is not already being launched, then get it
5527 // started.
5528 if (i >= N) {
5529 final long origId = Binder.clearCallingIdentity();
5530 ProcessRecord proc = startProcessLocked(cpi.processName,
5531 cpr.appInfo, false, 0, "content provider",
5532 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005533 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005535 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 + cpi.applicationInfo.packageName + "/"
5537 + cpi.applicationInfo.uid + " for provider "
5538 + name + ": process is bad");
5539 return null;
5540 }
5541 cpr.launchingApp = proc;
5542 mLaunchingProviders.add(cpr);
5543 Binder.restoreCallingIdentity(origId);
5544 }
5545
5546 // Make sure the provider is published (the same provider class
5547 // may be published under multiple names).
5548 if (firstClass) {
5549 mProvidersByClass.put(cpi.name, cpr);
5550 }
5551 mProvidersByName.put(name, cpr);
5552
5553 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005554 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005555 "Adding provider requested by "
5556 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005557 + cpr.info.processName);
5558 Integer cnt = r.conProviders.get(cpr);
5559 if (cnt == null) {
5560 r.conProviders.put(cpr, new Integer(1));
5561 } else {
5562 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564 cpr.clients.add(r);
5565 } else {
5566 cpr.externals++;
5567 }
5568 }
5569 }
5570
5571 // Wait for the provider to be published...
5572 synchronized (cpr) {
5573 while (cpr.provider == null) {
5574 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005575 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 + cpi.applicationInfo.packageName + "/"
5577 + cpi.applicationInfo.uid + " for provider "
5578 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005579 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 cpi.applicationInfo.packageName,
5581 cpi.applicationInfo.uid, name);
5582 return null;
5583 }
5584 try {
5585 cpr.wait();
5586 } catch (InterruptedException ex) {
5587 }
5588 }
5589 }
5590 return cpr;
5591 }
5592
5593 public final ContentProviderHolder getContentProvider(
5594 IApplicationThread caller, String name) {
5595 if (caller == null) {
5596 String msg = "null IApplicationThread when getting content provider "
5597 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005598 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 throw new SecurityException(msg);
5600 }
5601
5602 return getContentProviderImpl(caller, name);
5603 }
5604
5605 private ContentProviderHolder getContentProviderExternal(String name) {
5606 return getContentProviderImpl(null, name);
5607 }
5608
5609 /**
5610 * Drop a content provider from a ProcessRecord's bookkeeping
5611 * @param cpr
5612 */
5613 public void removeContentProvider(IApplicationThread caller, String name) {
5614 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005615 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005617 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005618 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005619 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 return;
5621 }
5622 final ProcessRecord r = getRecordForAppLocked(caller);
5623 if (r == null) {
5624 throw new SecurityException(
5625 "Unable to find app for caller " + caller +
5626 " when removing content provider " + name);
5627 }
5628 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005629 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005630 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005631 + r.info.processName + " from process "
5632 + localCpr.appInfo.processName);
5633 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005635 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005636 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 return;
5638 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005639 Integer cnt = r.conProviders.get(localCpr);
5640 if (cnt == null || cnt.intValue() <= 1) {
5641 localCpr.clients.remove(r);
5642 r.conProviders.remove(localCpr);
5643 } else {
5644 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005646 }
5647 updateOomAdjLocked();
5648 }
5649 }
5650
5651 private void removeContentProviderExternal(String name) {
5652 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005653 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 if(cpr == null) {
5655 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005656 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 return;
5658 }
5659
5660 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005661 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 localCpr.externals--;
5663 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005664 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 }
5666 updateOomAdjLocked();
5667 }
5668 }
5669
5670 public final void publishContentProviders(IApplicationThread caller,
5671 List<ContentProviderHolder> providers) {
5672 if (providers == null) {
5673 return;
5674 }
5675
5676 synchronized(this) {
5677 final ProcessRecord r = getRecordForAppLocked(caller);
5678 if (r == null) {
5679 throw new SecurityException(
5680 "Unable to find app for caller " + caller
5681 + " (pid=" + Binder.getCallingPid()
5682 + ") when publishing content providers");
5683 }
5684
5685 final long origId = Binder.clearCallingIdentity();
5686
5687 final int N = providers.size();
5688 for (int i=0; i<N; i++) {
5689 ContentProviderHolder src = providers.get(i);
5690 if (src == null || src.info == null || src.provider == null) {
5691 continue;
5692 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005693 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 if (dst != null) {
5695 mProvidersByClass.put(dst.info.name, dst);
5696 String names[] = dst.info.authority.split(";");
5697 for (int j = 0; j < names.length; j++) {
5698 mProvidersByName.put(names[j], dst);
5699 }
5700
5701 int NL = mLaunchingProviders.size();
5702 int j;
5703 for (j=0; j<NL; j++) {
5704 if (mLaunchingProviders.get(j) == dst) {
5705 mLaunchingProviders.remove(j);
5706 j--;
5707 NL--;
5708 }
5709 }
5710 synchronized (dst) {
5711 dst.provider = src.provider;
5712 dst.app = r;
5713 dst.notifyAll();
5714 }
5715 updateOomAdjLocked(r);
5716 }
5717 }
5718
5719 Binder.restoreCallingIdentity(origId);
5720 }
5721 }
5722
5723 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005724 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005725 synchronized (mSelf) {
5726 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5727 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005728 if (providers != null) {
5729 for (int i=providers.size()-1; i>=0; i--) {
5730 ProviderInfo pi = (ProviderInfo)providers.get(i);
5731 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5732 Slog.w(TAG, "Not installing system proc provider " + pi.name
5733 + ": not system .apk");
5734 providers.remove(i);
5735 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005736 }
5737 }
5738 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005739 if (providers != null) {
5740 mSystemThread.installSystemProviders(providers);
5741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005742 }
5743
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005744 /**
5745 * Allows app to retrieve the MIME type of a URI without having permission
5746 * to access its content provider.
5747 *
5748 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5749 *
5750 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5751 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5752 */
5753 public String getProviderMimeType(Uri uri) {
5754 final String name = uri.getAuthority();
5755 final long ident = Binder.clearCallingIdentity();
5756 ContentProviderHolder holder = null;
5757
5758 try {
5759 holder = getContentProviderExternal(name);
5760 if (holder != null) {
5761 return holder.provider.getType(uri);
5762 }
5763 } catch (RemoteException e) {
5764 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5765 return null;
5766 } finally {
5767 if (holder != null) {
5768 removeContentProviderExternal(name);
5769 }
5770 Binder.restoreCallingIdentity(ident);
5771 }
5772
5773 return null;
5774 }
5775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 // =========================================================
5777 // GLOBAL MANAGEMENT
5778 // =========================================================
5779
5780 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5781 ApplicationInfo info, String customProcess) {
5782 String proc = customProcess != null ? customProcess : info.processName;
5783 BatteryStatsImpl.Uid.Proc ps = null;
5784 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5785 synchronized (stats) {
5786 ps = stats.getProcessStatsLocked(info.uid, proc);
5787 }
5788 return new ProcessRecord(ps, thread, info, proc);
5789 }
5790
5791 final ProcessRecord addAppLocked(ApplicationInfo info) {
5792 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5793
5794 if (app == null) {
5795 app = newProcessRecordLocked(null, info, null);
5796 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005797 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005798 }
5799
5800 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5801 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5802 app.persistent = true;
5803 app.maxAdj = CORE_SERVER_ADJ;
5804 }
5805 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5806 mPersistentStartingProcesses.add(app);
5807 startProcessLocked(app, "added application", app.processName);
5808 }
5809
5810 return app;
5811 }
5812
5813 public void unhandledBack() {
5814 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5815 "unhandledBack()");
5816
5817 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005818 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005819 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 TAG, "Performing unhandledBack(): stack size = " + count);
5821 if (count > 1) {
5822 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005823 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005824 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5825 Binder.restoreCallingIdentity(origId);
5826 }
5827 }
5828 }
5829
5830 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5831 String name = uri.getAuthority();
5832 ContentProviderHolder cph = getContentProviderExternal(name);
5833 ParcelFileDescriptor pfd = null;
5834 if (cph != null) {
5835 // We record the binder invoker's uid in thread-local storage before
5836 // going to the content provider to open the file. Later, in the code
5837 // that handles all permissions checks, we look for this uid and use
5838 // that rather than the Activity Manager's own uid. The effect is that
5839 // we do the check against the caller's permissions even though it looks
5840 // to the content provider like the Activity Manager itself is making
5841 // the request.
5842 sCallerIdentity.set(new Identity(
5843 Binder.getCallingPid(), Binder.getCallingUid()));
5844 try {
5845 pfd = cph.provider.openFile(uri, "r");
5846 } catch (FileNotFoundException e) {
5847 // do nothing; pfd will be returned null
5848 } finally {
5849 // Ensure that whatever happens, we clean up the identity state
5850 sCallerIdentity.remove();
5851 }
5852
5853 // We've got the fd now, so we're done with the provider.
5854 removeContentProviderExternal(name);
5855 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005856 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 }
5858 return pfd;
5859 }
5860
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005861 // Actually is sleeping or shutting down or whatever else in the future
5862 // is an inactive state.
5863 public boolean isSleeping() {
5864 return mSleeping || mShuttingDown;
5865 }
5866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 public void goingToSleep() {
5868 synchronized(this) {
5869 mSleeping = true;
5870 mWindowManager.setEventDispatching(false);
5871
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005872 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005873
5874 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005875 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005876 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5877 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005878 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 }
5880 }
5881
Dianne Hackborn55280a92009-05-07 15:53:46 -07005882 public boolean shutdown(int timeout) {
5883 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5884 != PackageManager.PERMISSION_GRANTED) {
5885 throw new SecurityException("Requires permission "
5886 + android.Manifest.permission.SHUTDOWN);
5887 }
5888
5889 boolean timedout = false;
5890
5891 synchronized(this) {
5892 mShuttingDown = true;
5893 mWindowManager.setEventDispatching(false);
5894
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005895 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005896 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005897 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005898 while (mMainStack.mResumedActivity != null
5899 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005900 long delay = endTime - System.currentTimeMillis();
5901 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005902 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005903 timedout = true;
5904 break;
5905 }
5906 try {
5907 this.wait();
5908 } catch (InterruptedException e) {
5909 }
5910 }
5911 }
5912 }
5913
5914 mUsageStatsService.shutdown();
5915 mBatteryStatsService.shutdown();
5916
5917 return timedout;
5918 }
5919
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005920 public final void activitySlept(IBinder token) {
5921 if (localLOGV) Slog.v(
5922 TAG, "Activity slept: token=" + token);
5923
5924 ActivityRecord r = null;
5925
5926 final long origId = Binder.clearCallingIdentity();
5927
5928 synchronized (this) {
5929 int index = mMainStack.indexOfTokenLocked(token);
5930 if (index >= 0) {
5931 r = (ActivityRecord)mMainStack.mHistory.get(index);
5932 mMainStack.activitySleptLocked(r);
5933 }
5934 }
5935
5936 Binder.restoreCallingIdentity(origId);
5937 }
5938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 public void wakingUp() {
5940 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 mWindowManager.setEventDispatching(true);
5942 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005943 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005944 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005945 }
5946 }
5947
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005948 public void stopAppSwitches() {
5949 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5950 != PackageManager.PERMISSION_GRANTED) {
5951 throw new SecurityException("Requires permission "
5952 + android.Manifest.permission.STOP_APP_SWITCHES);
5953 }
5954
5955 synchronized(this) {
5956 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5957 + APP_SWITCH_DELAY_TIME;
5958 mDidAppSwitch = false;
5959 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5960 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5961 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5962 }
5963 }
5964
5965 public void resumeAppSwitches() {
5966 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5967 != PackageManager.PERMISSION_GRANTED) {
5968 throw new SecurityException("Requires permission "
5969 + android.Manifest.permission.STOP_APP_SWITCHES);
5970 }
5971
5972 synchronized(this) {
5973 // Note that we don't execute any pending app switches... we will
5974 // let those wait until either the timeout, or the next start
5975 // activity request.
5976 mAppSwitchesAllowedTime = 0;
5977 }
5978 }
5979
5980 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5981 String name) {
5982 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5983 return true;
5984 }
5985
5986 final int perm = checkComponentPermission(
5987 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005988 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005989 if (perm == PackageManager.PERMISSION_GRANTED) {
5990 return true;
5991 }
5992
Joe Onorato8a9b2202010-02-26 18:56:32 -08005993 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005994 return false;
5995 }
5996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 public void setDebugApp(String packageName, boolean waitForDebugger,
5998 boolean persistent) {
5999 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6000 "setDebugApp()");
6001
6002 // Note that this is not really thread safe if there are multiple
6003 // callers into it at the same time, but that's not a situation we
6004 // care about.
6005 if (persistent) {
6006 final ContentResolver resolver = mContext.getContentResolver();
6007 Settings.System.putString(
6008 resolver, Settings.System.DEBUG_APP,
6009 packageName);
6010 Settings.System.putInt(
6011 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6012 waitForDebugger ? 1 : 0);
6013 }
6014
6015 synchronized (this) {
6016 if (!persistent) {
6017 mOrigDebugApp = mDebugApp;
6018 mOrigWaitForDebugger = mWaitForDebugger;
6019 }
6020 mDebugApp = packageName;
6021 mWaitForDebugger = waitForDebugger;
6022 mDebugTransient = !persistent;
6023 if (packageName != null) {
6024 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006025 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006026 Binder.restoreCallingIdentity(origId);
6027 }
6028 }
6029 }
6030
6031 public void setAlwaysFinish(boolean enabled) {
6032 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6033 "setAlwaysFinish()");
6034
6035 Settings.System.putInt(
6036 mContext.getContentResolver(),
6037 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6038
6039 synchronized (this) {
6040 mAlwaysFinishActivities = enabled;
6041 }
6042 }
6043
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006044 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006045 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006046 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006048 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 }
6050 }
6051
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006052 public boolean isUserAMonkey() {
6053 // For now the fact that there is a controller implies
6054 // we have a monkey.
6055 synchronized (this) {
6056 return mController != null;
6057 }
6058 }
6059
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006060 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006061 synchronized (this) {
6062 mWatchers.register(watcher);
6063 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006064 }
6065
6066 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006067 synchronized (this) {
6068 mWatchers.unregister(watcher);
6069 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006070 }
6071
Daniel Sandler69a48172010-06-23 16:29:36 -04006072 public void setImmersive(IBinder token, boolean immersive) {
6073 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006074 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006075 if (index < 0) {
6076 throw new IllegalArgumentException();
6077 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006078 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006079 r.immersive = immersive;
6080 }
6081 }
6082
6083 public boolean isImmersive(IBinder token) {
6084 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006085 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006086 if (index < 0) {
6087 throw new IllegalArgumentException();
6088 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006089 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006090 return r.immersive;
6091 }
6092 }
6093
6094 public boolean isTopActivityImmersive() {
6095 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006096 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006097 return (r != null) ? r.immersive : false;
6098 }
6099 }
6100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 public final void enterSafeMode() {
6102 synchronized(this) {
6103 // It only makes sense to do this before the system is ready
6104 // and started launching other packages.
6105 if (!mSystemReady) {
6106 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006107 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 } catch (RemoteException e) {
6109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110 }
6111 }
6112 }
6113
Jeff Brownb09abc12011-01-13 21:08:27 -08006114 public final void showSafeModeOverlay() {
6115 View v = LayoutInflater.from(mContext).inflate(
6116 com.android.internal.R.layout.safe_mode, null);
6117 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6118 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6119 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6120 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6121 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6122 lp.format = v.getBackground().getOpacity();
6123 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6124 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6125 ((WindowManager)mContext.getSystemService(
6126 Context.WINDOW_SERVICE)).addView(v, lp);
6127 }
6128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 public void noteWakeupAlarm(IIntentSender sender) {
6130 if (!(sender instanceof PendingIntentRecord)) {
6131 return;
6132 }
6133 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6134 synchronized (stats) {
6135 if (mBatteryStatsService.isOnBattery()) {
6136 mBatteryStatsService.enforceCallingPermission();
6137 PendingIntentRecord rec = (PendingIntentRecord)sender;
6138 int MY_UID = Binder.getCallingUid();
6139 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6140 BatteryStatsImpl.Uid.Pkg pkg =
6141 stats.getPackageStatsLocked(uid, rec.key.packageName);
6142 pkg.incWakeupsLocked();
6143 }
6144 }
6145 }
6146
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006147 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006149 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006150 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006151 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006152 // XXX Note: don't acquire main activity lock here, because the window
6153 // manager calls in with its locks held.
6154
6155 boolean killed = false;
6156 synchronized (mPidsSelfLocked) {
6157 int[] types = new int[pids.length];
6158 int worstType = 0;
6159 for (int i=0; i<pids.length; i++) {
6160 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6161 if (proc != null) {
6162 int type = proc.setAdj;
6163 types[i] = type;
6164 if (type > worstType) {
6165 worstType = type;
6166 }
6167 }
6168 }
6169
6170 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6171 // then constrain it so we will kill all hidden procs.
6172 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6173 worstType = HIDDEN_APP_MIN_ADJ;
6174 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006175 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 for (int i=0; i<pids.length; i++) {
6177 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6178 if (proc == null) {
6179 continue;
6180 }
6181 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006182 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006183 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006184 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6185 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006187 proc.killedBackground = true;
6188 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006189 }
6190 }
6191 }
6192 return killed;
6193 }
6194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 public final void startRunning(String pkg, String cls, String action,
6196 String data) {
6197 synchronized(this) {
6198 if (mStartRunning) {
6199 return;
6200 }
6201 mStartRunning = true;
6202 mTopComponent = pkg != null && cls != null
6203 ? new ComponentName(pkg, cls) : null;
6204 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6205 mTopData = data;
6206 if (!mSystemReady) {
6207 return;
6208 }
6209 }
6210
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006211 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 }
6213
6214 private void retrieveSettings() {
6215 final ContentResolver resolver = mContext.getContentResolver();
6216 String debugApp = Settings.System.getString(
6217 resolver, Settings.System.DEBUG_APP);
6218 boolean waitForDebugger = Settings.System.getInt(
6219 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6220 boolean alwaysFinishActivities = Settings.System.getInt(
6221 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6222
6223 Configuration configuration = new Configuration();
6224 Settings.System.getConfiguration(resolver, configuration);
6225
6226 synchronized (this) {
6227 mDebugApp = mOrigDebugApp = debugApp;
6228 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6229 mAlwaysFinishActivities = alwaysFinishActivities;
6230 // This happens before any activities are started, so we can
6231 // change mConfiguration in-place.
6232 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006233 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006234 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006235 }
6236 }
6237
6238 public boolean testIsSystemReady() {
6239 // no need to synchronize(this) just to read & return the value
6240 return mSystemReady;
6241 }
6242
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006243 private static File getCalledPreBootReceiversFile() {
6244 File dataDir = Environment.getDataDirectory();
6245 File systemDir = new File(dataDir, "system");
6246 File fname = new File(systemDir, "called_pre_boots.dat");
6247 return fname;
6248 }
6249
6250 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6251 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6252 File file = getCalledPreBootReceiversFile();
6253 FileInputStream fis = null;
6254 try {
6255 fis = new FileInputStream(file);
6256 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6257 int vers = dis.readInt();
6258 String codename = dis.readUTF();
6259 if (vers == android.os.Build.VERSION.SDK_INT
6260 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6261 int num = dis.readInt();
6262 while (num > 0) {
6263 num--;
6264 String pkg = dis.readUTF();
6265 String cls = dis.readUTF();
6266 lastDoneReceivers.add(new ComponentName(pkg, cls));
6267 }
6268 }
6269 } catch (FileNotFoundException e) {
6270 } catch (IOException e) {
6271 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6272 } finally {
6273 if (fis != null) {
6274 try {
6275 fis.close();
6276 } catch (IOException e) {
6277 }
6278 }
6279 }
6280 return lastDoneReceivers;
6281 }
6282
6283 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6284 File file = getCalledPreBootReceiversFile();
6285 FileOutputStream fos = null;
6286 DataOutputStream dos = null;
6287 try {
6288 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6289 fos = new FileOutputStream(file);
6290 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6291 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6292 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6293 dos.writeInt(list.size());
6294 for (int i=0; i<list.size(); i++) {
6295 dos.writeUTF(list.get(i).getPackageName());
6296 dos.writeUTF(list.get(i).getClassName());
6297 }
6298 } catch (IOException e) {
6299 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6300 file.delete();
6301 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006302 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006303 if (dos != null) {
6304 try {
6305 dos.close();
6306 } catch (IOException e) {
6307 // TODO Auto-generated catch block
6308 e.printStackTrace();
6309 }
6310 }
6311 }
6312 }
6313
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006314 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006315 // In the simulator, startRunning will never have been called, which
6316 // normally sets a few crucial variables. Do it here instead.
6317 if (!Process.supportsProcesses()) {
6318 mStartRunning = true;
6319 mTopAction = Intent.ACTION_MAIN;
6320 }
6321
6322 synchronized(this) {
6323 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006324 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 return;
6326 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006327
6328 // Check to see if there are any update receivers to run.
6329 if (!mDidUpdate) {
6330 if (mWaitingUpdate) {
6331 return;
6332 }
6333 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6334 List<ResolveInfo> ris = null;
6335 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006336 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006337 intent, null, 0);
6338 } catch (RemoteException e) {
6339 }
6340 if (ris != null) {
6341 for (int i=ris.size()-1; i>=0; i--) {
6342 if ((ris.get(i).activityInfo.applicationInfo.flags
6343 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6344 ris.remove(i);
6345 }
6346 }
6347 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006348
6349 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6350
6351 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006352 for (int i=0; i<ris.size(); i++) {
6353 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006354 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6355 if (lastDoneReceivers.contains(comp)) {
6356 ris.remove(i);
6357 i--;
6358 }
6359 }
6360
6361 for (int i=0; i<ris.size(); i++) {
6362 ActivityInfo ai = ris.get(i).activityInfo;
6363 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6364 doneReceivers.add(comp);
6365 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006366 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006367 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006368 finisher = new IIntentReceiver.Stub() {
6369 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006370 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006371 boolean sticky) {
6372 // The raw IIntentReceiver interface is called
6373 // with the AM lock held, so redispatch to
6374 // execute our code without the lock.
6375 mHandler.post(new Runnable() {
6376 public void run() {
6377 synchronized (ActivityManagerService.this) {
6378 mDidUpdate = true;
6379 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006380 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006381 systemReady(goingCallback);
6382 }
6383 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006384 }
6385 };
6386 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006387 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006388 broadcastIntentLocked(null, null, intent, null, finisher,
6389 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006390 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006391 mWaitingUpdate = true;
6392 }
6393 }
6394 }
6395 if (mWaitingUpdate) {
6396 return;
6397 }
6398 mDidUpdate = true;
6399 }
6400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 mSystemReady = true;
6402 if (!mStartRunning) {
6403 return;
6404 }
6405 }
6406
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006407 ArrayList<ProcessRecord> procsToKill = null;
6408 synchronized(mPidsSelfLocked) {
6409 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6410 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6411 if (!isAllowedWhileBooting(proc.info)){
6412 if (procsToKill == null) {
6413 procsToKill = new ArrayList<ProcessRecord>();
6414 }
6415 procsToKill.add(proc);
6416 }
6417 }
6418 }
6419
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006420 synchronized(this) {
6421 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006422 for (int i=procsToKill.size()-1; i>=0; i--) {
6423 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006424 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006425 removeProcessLocked(proc, true);
6426 }
6427 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006428
6429 // Now that we have cleaned up any update processes, we
6430 // are ready to start launching real processes and know that
6431 // we won't trample on them any more.
6432 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006433 }
6434
Joe Onorato8a9b2202010-02-26 18:56:32 -08006435 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006436 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006437 SystemClock.uptimeMillis());
6438
6439 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006440 // Make sure we have no pre-ready processes sitting around.
6441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6443 ResolveInfo ri = mContext.getPackageManager()
6444 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006445 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 CharSequence errorMsg = null;
6447 if (ri != null) {
6448 ActivityInfo ai = ri.activityInfo;
6449 ApplicationInfo app = ai.applicationInfo;
6450 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6451 mTopAction = Intent.ACTION_FACTORY_TEST;
6452 mTopData = null;
6453 mTopComponent = new ComponentName(app.packageName,
6454 ai.name);
6455 } else {
6456 errorMsg = mContext.getResources().getText(
6457 com.android.internal.R.string.factorytest_not_system);
6458 }
6459 } else {
6460 errorMsg = mContext.getResources().getText(
6461 com.android.internal.R.string.factorytest_no_action);
6462 }
6463 if (errorMsg != null) {
6464 mTopAction = null;
6465 mTopData = null;
6466 mTopComponent = null;
6467 Message msg = Message.obtain();
6468 msg.what = SHOW_FACTORY_ERROR_MSG;
6469 msg.getData().putCharSequence("msg", errorMsg);
6470 mHandler.sendMessage(msg);
6471 }
6472 }
6473 }
6474
6475 retrieveSettings();
6476
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006477 if (goingCallback != null) goingCallback.run();
6478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006479 synchronized (this) {
6480 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6481 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006482 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006483 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 if (apps != null) {
6485 int N = apps.size();
6486 int i;
6487 for (i=0; i<N; i++) {
6488 ApplicationInfo info
6489 = (ApplicationInfo)apps.get(i);
6490 if (info != null &&
6491 !info.packageName.equals("android")) {
6492 addAppLocked(info);
6493 }
6494 }
6495 }
6496 } catch (RemoteException ex) {
6497 // pm is in same process, this will never happen.
6498 }
6499 }
6500
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006501 // Start up initial activity.
6502 mBooting = true;
6503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006505 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 Message msg = Message.obtain();
6507 msg.what = SHOW_UID_ERROR_MSG;
6508 mHandler.sendMessage(msg);
6509 }
6510 } catch (RemoteException e) {
6511 }
6512
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006513 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 }
6515 }
6516
Dan Egnorb7f03672009-12-09 16:22:32 -08006517 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006518 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006520 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006521 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 startAppProblemLocked(app);
6523 app.stopFreezingAllLocked();
6524 return handleAppCrashLocked(app);
6525 }
6526
Dan Egnorb7f03672009-12-09 16:22:32 -08006527 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006528 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006530 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006531 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6532 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533 startAppProblemLocked(app);
6534 app.stopFreezingAllLocked();
6535 }
6536
6537 /**
6538 * Generate a process error record, suitable for attachment to a ProcessRecord.
6539 *
6540 * @param app The ProcessRecord in which the error occurred.
6541 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6542 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006543 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 * @param shortMsg Short message describing the crash.
6545 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006546 * @param stackTrace Full crash stack trace, may be null.
6547 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006548 * @return Returns a fully-formed AppErrorStateInfo record.
6549 */
6550 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006551 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006552 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006554 report.condition = condition;
6555 report.processName = app.processName;
6556 report.pid = app.pid;
6557 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006558 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006559 report.shortMsg = shortMsg;
6560 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006561 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562
6563 return report;
6564 }
6565
Dan Egnor42471dd2010-01-07 17:25:22 -08006566 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006567 synchronized (this) {
6568 app.crashing = false;
6569 app.crashingReport = null;
6570 app.notResponding = false;
6571 app.notRespondingReport = null;
6572 if (app.anrDialog == fromDialog) {
6573 app.anrDialog = null;
6574 }
6575 if (app.waitDialog == fromDialog) {
6576 app.waitDialog = null;
6577 }
6578 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006579 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006580 Slog.i(ActivityManagerService.TAG, "Killing "
6581 + app.processName + " (pid=" + app.pid + "): user's request");
6582 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6583 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 Process.killProcess(app.pid);
6585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006586 }
6587 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006588
Dan Egnorb7f03672009-12-09 16:22:32 -08006589 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006590 long now = SystemClock.uptimeMillis();
6591
6592 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6593 app.info.uid);
6594 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6595 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006596 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006597 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006598 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006600 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6601 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006602 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006603 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006605 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 }
6607 }
6608 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006609 // Don't let services in this process be restarted and potentially
6610 // annoy the user repeatedly. Unless it is persistent, since those
6611 // processes run critical code.
6612 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 // We don't want to start this process again until the user
6614 // explicitly does so... but for persistent process, we really
6615 // need to keep it running. If a persistent process is actually
6616 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006617 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006618 app.info.processName);
6619 mBadProcesses.put(app.info.processName, app.info.uid, now);
6620 app.bad = true;
6621 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6622 app.removed = true;
6623 removeProcessLocked(app, false);
6624 return false;
6625 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006626 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006627 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006628 if (r.app == app) {
6629 // If the top running activity is from this crashing
6630 // process, then terminate it to avoid getting in a loop.
6631 Slog.w(TAG, " Force finishing activity "
6632 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006633 int index = mMainStack.indexOfTokenLocked(r);
6634 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006635 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006636 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006637 // stopped, to avoid a situation where one will get
6638 // re-start our crashing activity once it gets resumed again.
6639 index--;
6640 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006641 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006642 if (r.state == ActivityState.RESUMED
6643 || r.state == ActivityState.PAUSING
6644 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006645 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006646 Slog.w(TAG, " Force finishing activity "
6647 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006648 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006649 Activity.RESULT_CANCELED, null, "crashed");
6650 }
6651 }
6652 }
6653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006654 }
6655
6656 // Bump up the crash count of any services currently running in the proc.
6657 if (app.services.size() != 0) {
6658 // Any services running in the application need to be placed
6659 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006660 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006662 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 sr.crashCount++;
6664 }
6665 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006666
6667 // If the crashing process is what we consider to be the "home process" and it has been
6668 // replaced by a third-party app, clear the package preferred activities from packages
6669 // with a home activity running in the process to prevent a repeatedly crashing app
6670 // from blocking the user to manually clear the list.
6671 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6672 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6673 Iterator it = mHomeProcess.activities.iterator();
6674 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006675 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006676 if (r.isHomeActivity) {
6677 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6678 try {
6679 ActivityThread.getPackageManager()
6680 .clearPackagePreferredActivities(r.packageName);
6681 } catch (RemoteException c) {
6682 // pm is in same process, this will never happen.
6683 }
6684 }
6685 }
6686 }
6687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6689 return true;
6690 }
6691
6692 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006693 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6694 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 skipCurrentReceiverLocked(app);
6696 }
6697
6698 void skipCurrentReceiverLocked(ProcessRecord app) {
6699 boolean reschedule = false;
6700 BroadcastRecord r = app.curReceiver;
6701 if (r != null) {
6702 // The current broadcast is waiting for this app's receiver
6703 // to be finished. Looks like that's not going to happen, so
6704 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006705 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006706 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6707 r.resultExtras, r.resultAbort, true);
6708 reschedule = true;
6709 }
6710 r = mPendingBroadcast;
6711 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006712 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006714 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6716 r.resultExtras, r.resultAbort, true);
6717 reschedule = true;
6718 }
6719 if (reschedule) {
6720 scheduleBroadcastsLocked();
6721 }
6722 }
6723
Dan Egnor60d87622009-12-16 16:32:58 -08006724 /**
6725 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6726 * The application process will exit immediately after this call returns.
6727 * @param app object of the crashing app, null for the system server
6728 * @param crashInfo describing the exception
6729 */
6730 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6731 ProcessRecord r = findAppProcess(app);
6732
6733 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6734 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006735 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006736 crashInfo.exceptionClassName,
6737 crashInfo.exceptionMessage,
6738 crashInfo.throwFileName,
6739 crashInfo.throwLineNumber);
6740
Dan Egnor42471dd2010-01-07 17:25:22 -08006741 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006742
6743 crashApplication(r, crashInfo);
6744 }
6745
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006746 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006747 IBinder app,
6748 int violationMask,
6749 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006750 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006751
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006752 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006753 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006754 boolean logIt = true;
6755 synchronized (mAlreadyLoggedViolatedStacks) {
6756 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6757 logIt = false;
6758 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006759 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006760 // the relative pain numbers, without logging all
6761 // the stack traces repeatedly. We'd want to do
6762 // likewise in the client code, which also does
6763 // dup suppression, before the Binder call.
6764 } else {
6765 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6766 mAlreadyLoggedViolatedStacks.clear();
6767 }
6768 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6769 }
6770 }
6771 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006772 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006773 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006774 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006775
6776 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6777 AppErrorResult result = new AppErrorResult();
6778 synchronized (this) {
6779 final long origId = Binder.clearCallingIdentity();
6780
6781 Message msg = Message.obtain();
6782 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6783 HashMap<String, Object> data = new HashMap<String, Object>();
6784 data.put("result", result);
6785 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006786 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006787 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006788 msg.obj = data;
6789 mHandler.sendMessage(msg);
6790
6791 Binder.restoreCallingIdentity(origId);
6792 }
6793 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006794 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006795 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006796 }
6797
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006798 // Depending on the policy in effect, there could be a bunch of
6799 // these in quick succession so we try to batch these together to
6800 // minimize disk writes, number of dropbox entries, and maximize
6801 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006802 private void logStrictModeViolationToDropBox(
6803 ProcessRecord process,
6804 StrictMode.ViolationInfo info) {
6805 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006806 return;
6807 }
6808 final boolean isSystemApp = process == null ||
6809 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6810 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6811 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6812 final DropBoxManager dbox = (DropBoxManager)
6813 mContext.getSystemService(Context.DROPBOX_SERVICE);
6814
6815 // Exit early if the dropbox isn't configured to accept this report type.
6816 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6817
6818 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006819 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006820 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6821 synchronized (sb) {
6822 bufferWasEmpty = sb.length() == 0;
6823 appendDropBoxProcessHeaders(process, sb);
6824 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6825 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006826 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6827 if (info.violationNumThisLoop != 0) {
6828 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6829 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006830 if (info.numAnimationsRunning != 0) {
6831 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6832 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006833 if (info.broadcastIntentAction != null) {
6834 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6835 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006836 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006837 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006838 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006839 if (info.numInstances != -1) {
6840 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6841 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006842 if (info.tags != null) {
6843 for (String tag : info.tags) {
6844 sb.append("Span-Tag: ").append(tag).append("\n");
6845 }
6846 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006847 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006848 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6849 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006850 }
6851 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006852
6853 // Only buffer up to ~64k. Various logging bits truncate
6854 // things at 128k.
6855 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006856 }
6857
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006858 // Flush immediately if the buffer's grown too large, or this
6859 // is a non-system app. Non-system apps are isolated with a
6860 // different tag & policy and not batched.
6861 //
6862 // Batching is useful during internal testing with
6863 // StrictMode settings turned up high. Without batching,
6864 // thousands of separate files could be created on boot.
6865 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006866 new Thread("Error dump: " + dropboxTag) {
6867 @Override
6868 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006869 String report;
6870 synchronized (sb) {
6871 report = sb.toString();
6872 sb.delete(0, sb.length());
6873 sb.trimToSize();
6874 }
6875 if (report.length() != 0) {
6876 dbox.addText(dropboxTag, report);
6877 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006878 }
6879 }.start();
6880 return;
6881 }
6882
6883 // System app batching:
6884 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006885 // An existing dropbox-writing thread is outstanding, so
6886 // we don't need to start it up. The existing thread will
6887 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006888 return;
6889 }
6890
6891 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6892 // (After this point, we shouldn't access AMS internal data structures.)
6893 new Thread("Error dump: " + dropboxTag) {
6894 @Override
6895 public void run() {
6896 // 5 second sleep to let stacks arrive and be batched together
6897 try {
6898 Thread.sleep(5000); // 5 seconds
6899 } catch (InterruptedException e) {}
6900
6901 String errorReport;
6902 synchronized (mStrictModeBuffer) {
6903 errorReport = mStrictModeBuffer.toString();
6904 if (errorReport.length() == 0) {
6905 return;
6906 }
6907 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6908 mStrictModeBuffer.trimToSize();
6909 }
6910 dbox.addText(dropboxTag, errorReport);
6911 }
6912 }.start();
6913 }
6914
Dan Egnor60d87622009-12-16 16:32:58 -08006915 /**
6916 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6917 * @param app object of the crashing app, null for the system server
6918 * @param tag reported by the caller
6919 * @param crashInfo describing the context of the error
6920 * @return true if the process should exit immediately (WTF is fatal)
6921 */
6922 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006923 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006924 ProcessRecord r = findAppProcess(app);
6925
6926 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6927 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006928 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006929 tag, crashInfo.exceptionMessage);
6930
Dan Egnor42471dd2010-01-07 17:25:22 -08006931 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006932
Doug Zongker43866e02010-01-07 12:09:54 -08006933 if (Settings.Secure.getInt(mContext.getContentResolver(),
6934 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006935 crashApplication(r, crashInfo);
6936 return true;
6937 } else {
6938 return false;
6939 }
6940 }
6941
6942 /**
6943 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6944 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6945 */
6946 private ProcessRecord findAppProcess(IBinder app) {
6947 if (app == null) {
6948 return null;
6949 }
6950
6951 synchronized (this) {
6952 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6953 final int NA = apps.size();
6954 for (int ia=0; ia<NA; ia++) {
6955 ProcessRecord p = apps.valueAt(ia);
6956 if (p.thread != null && p.thread.asBinder() == app) {
6957 return p;
6958 }
6959 }
6960 }
6961
Joe Onorato8a9b2202010-02-26 18:56:32 -08006962 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006963 return null;
6964 }
6965 }
6966
6967 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006968 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6969 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006970 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006971 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6972 // Note: ProcessRecord 'process' is guarded by the service
6973 // instance. (notably process.pkgList, which could otherwise change
6974 // concurrently during execution of this method)
6975 synchronized (this) {
6976 if (process == null || process.pid == MY_PID) {
6977 sb.append("Process: system_server\n");
6978 } else {
6979 sb.append("Process: ").append(process.processName).append("\n");
6980 }
6981 if (process == null) {
6982 return;
6983 }
Dan Egnora455d192010-03-12 08:52:28 -08006984 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006985 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006986 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6987 for (String pkg : process.pkgList) {
6988 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006989 try {
Dan Egnora455d192010-03-12 08:52:28 -08006990 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6991 if (pi != null) {
6992 sb.append(" v").append(pi.versionCode);
6993 if (pi.versionName != null) {
6994 sb.append(" (").append(pi.versionName).append(")");
6995 }
6996 }
6997 } catch (RemoteException e) {
6998 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006999 }
Dan Egnora455d192010-03-12 08:52:28 -08007000 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007001 }
Dan Egnora455d192010-03-12 08:52:28 -08007002 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007003 }
7004
7005 private static String processClass(ProcessRecord process) {
7006 if (process == null || process.pid == MY_PID) {
7007 return "system_server";
7008 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7009 return "system_app";
7010 } else {
7011 return "data_app";
7012 }
7013 }
7014
7015 /**
7016 * Write a description of an error (crash, WTF, ANR) to the drop box.
7017 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7018 * @param process which caused the error, null means the system server
7019 * @param activity which triggered the error, null if unknown
7020 * @param parent activity related to the error, null if unknown
7021 * @param subject line related to the error, null if absent
7022 * @param report in long form describing the error, null if absent
7023 * @param logFile to include in the report, null if none
7024 * @param crashInfo giving an application stack trace, null if absent
7025 */
7026 public void addErrorToDropBox(String eventType,
7027 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7028 final String report, final File logFile,
7029 final ApplicationErrorReport.CrashInfo crashInfo) {
7030 // NOTE -- this must never acquire the ActivityManagerService lock,
7031 // otherwise the watchdog may be prevented from resetting the system.
7032
7033 final String dropboxTag = processClass(process) + "_" + eventType;
7034 final DropBoxManager dbox = (DropBoxManager)
7035 mContext.getSystemService(Context.DROPBOX_SERVICE);
7036
7037 // Exit early if the dropbox isn't configured to accept this report type.
7038 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7039
7040 final StringBuilder sb = new StringBuilder(1024);
7041 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007042 if (activity != null) {
7043 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7044 }
7045 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7046 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7047 }
7048 if (parent != null && parent != activity) {
7049 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7050 }
7051 if (subject != null) {
7052 sb.append("Subject: ").append(subject).append("\n");
7053 }
7054 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007055 if (Debug.isDebuggerConnected()) {
7056 sb.append("Debugger: Connected\n");
7057 }
Dan Egnora455d192010-03-12 08:52:28 -08007058 sb.append("\n");
7059
7060 // Do the rest in a worker thread to avoid blocking the caller on I/O
7061 // (After this point, we shouldn't access AMS internal data structures.)
7062 Thread worker = new Thread("Error dump: " + dropboxTag) {
7063 @Override
7064 public void run() {
7065 if (report != null) {
7066 sb.append(report);
7067 }
7068 if (logFile != null) {
7069 try {
7070 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7071 } catch (IOException e) {
7072 Slog.e(TAG, "Error reading " + logFile, e);
7073 }
7074 }
7075 if (crashInfo != null && crashInfo.stackTrace != null) {
7076 sb.append(crashInfo.stackTrace);
7077 }
7078
7079 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7080 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7081 if (lines > 0) {
7082 sb.append("\n");
7083
7084 // Merge several logcat streams, and take the last N lines
7085 InputStreamReader input = null;
7086 try {
7087 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7088 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7089 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7090
7091 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7092 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7093 input = new InputStreamReader(logcat.getInputStream());
7094
7095 int num;
7096 char[] buf = new char[8192];
7097 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7098 } catch (IOException e) {
7099 Slog.e(TAG, "Error running logcat", e);
7100 } finally {
7101 if (input != null) try { input.close(); } catch (IOException e) {}
7102 }
7103 }
7104
7105 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007106 }
Dan Egnora455d192010-03-12 08:52:28 -08007107 };
7108
7109 if (process == null || process.pid == MY_PID) {
7110 worker.run(); // We may be about to die -- need to run this synchronously
7111 } else {
7112 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007113 }
7114 }
7115
7116 /**
7117 * Bring up the "unexpected error" dialog box for a crashing app.
7118 * Deal with edge cases (intercepts from instrumented applications,
7119 * ActivityController, error intent receivers, that sort of thing).
7120 * @param r the application crashing
7121 * @param crashInfo describing the failure
7122 */
7123 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007124 long timeMillis = System.currentTimeMillis();
7125 String shortMsg = crashInfo.exceptionClassName;
7126 String longMsg = crashInfo.exceptionMessage;
7127 String stackTrace = crashInfo.stackTrace;
7128 if (shortMsg != null && longMsg != null) {
7129 longMsg = shortMsg + ": " + longMsg;
7130 } else if (shortMsg != null) {
7131 longMsg = shortMsg;
7132 }
7133
Dan Egnor60d87622009-12-16 16:32:58 -08007134 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007136 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 try {
7138 String name = r != null ? r.processName : null;
7139 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007140 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007141 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007142 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 + " at watcher's request");
7144 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007145 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 }
7147 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007148 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 }
7150 }
7151
7152 final long origId = Binder.clearCallingIdentity();
7153
7154 // If this process is running instrumentation, finish it.
7155 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007156 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007158 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7159 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 Bundle info = new Bundle();
7161 info.putString("shortMsg", shortMsg);
7162 info.putString("longMsg", longMsg);
7163 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7164 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007165 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007166 }
7167
Dan Egnor60d87622009-12-16 16:32:58 -08007168 // If we can't identify the process or it's already exceeded its crash quota,
7169 // quit right away without showing a crash dialog.
7170 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007172 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173 }
7174
7175 Message msg = Message.obtain();
7176 msg.what = SHOW_ERROR_MSG;
7177 HashMap data = new HashMap();
7178 data.put("result", result);
7179 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 msg.obj = data;
7181 mHandler.sendMessage(msg);
7182
7183 Binder.restoreCallingIdentity(origId);
7184 }
7185
7186 int res = result.get();
7187
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007188 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007189 synchronized (this) {
7190 if (r != null) {
7191 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7192 SystemClock.uptimeMillis());
7193 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007194 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007195 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007196 }
7197 }
7198
7199 if (appErrorIntent != null) {
7200 try {
7201 mContext.startActivity(appErrorIntent);
7202 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007203 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007207
7208 Intent createAppErrorIntentLocked(ProcessRecord r,
7209 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7210 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007211 if (report == null) {
7212 return null;
7213 }
7214 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7215 result.setComponent(r.errorReportReceiver);
7216 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7217 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7218 return result;
7219 }
7220
Dan Egnorb7f03672009-12-09 16:22:32 -08007221 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7222 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007223 if (r.errorReportReceiver == null) {
7224 return null;
7225 }
7226
7227 if (!r.crashing && !r.notResponding) {
7228 return null;
7229 }
7230
Dan Egnorb7f03672009-12-09 16:22:32 -08007231 ApplicationErrorReport report = new ApplicationErrorReport();
7232 report.packageName = r.info.packageName;
7233 report.installerPackageName = r.errorReportReceiver.getPackageName();
7234 report.processName = r.processName;
7235 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007236 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007237
Dan Egnorb7f03672009-12-09 16:22:32 -08007238 if (r.crashing) {
7239 report.type = ApplicationErrorReport.TYPE_CRASH;
7240 report.crashInfo = crashInfo;
7241 } else if (r.notResponding) {
7242 report.type = ApplicationErrorReport.TYPE_ANR;
7243 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007244
Dan Egnorb7f03672009-12-09 16:22:32 -08007245 report.anrInfo.activity = r.notRespondingReport.tag;
7246 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7247 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007248 }
7249
Dan Egnorb7f03672009-12-09 16:22:32 -08007250 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007251 }
7252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7254 // assume our apps are happy - lazy create the list
7255 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7256
7257 synchronized (this) {
7258
7259 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007260 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7261 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7263 // This one's in trouble, so we'll generate a report for it
7264 // crashes are higher priority (in case there's a crash *and* an anr)
7265 ActivityManager.ProcessErrorStateInfo report = null;
7266 if (app.crashing) {
7267 report = app.crashingReport;
7268 } else if (app.notResponding) {
7269 report = app.notRespondingReport;
7270 }
7271
7272 if (report != null) {
7273 if (errList == null) {
7274 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7275 }
7276 errList.add(report);
7277 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007278 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 " crashing = " + app.crashing +
7280 " notResponding = " + app.notResponding);
7281 }
7282 }
7283 }
7284 }
7285
7286 return errList;
7287 }
7288
7289 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7290 // Lazy instantiation of list
7291 List<ActivityManager.RunningAppProcessInfo> runList = null;
7292 synchronized (this) {
7293 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007294 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7295 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7297 // Generate process state info for running application
7298 ActivityManager.RunningAppProcessInfo currApp =
7299 new ActivityManager.RunningAppProcessInfo(app.processName,
7300 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007301 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007302 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007303 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007304 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007305 if (app.persistent) {
7306 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007309 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7311 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7312 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007313 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7314 } else if (adj >= HOME_APP_ADJ) {
7315 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7316 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 } else if (adj >= SECONDARY_SERVER_ADJ) {
7318 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007319 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007320 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007321 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7322 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007323 } else if (adj >= VISIBLE_APP_ADJ) {
7324 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7325 } else {
7326 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7327 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007328 currApp.importanceReasonCode = app.adjTypeCode;
7329 if (app.adjSource instanceof ProcessRecord) {
7330 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007331 } else if (app.adjSource instanceof ActivityRecord) {
7332 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007333 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7334 }
7335 if (app.adjTarget instanceof ComponentName) {
7336 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7337 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007338 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 // + " lru=" + currApp.lru);
7340 if (runList == null) {
7341 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7342 }
7343 runList.add(currApp);
7344 }
7345 }
7346 }
7347 return runList;
7348 }
7349
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007350 public List<ApplicationInfo> getRunningExternalApplications() {
7351 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7352 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7353 if (runningApps != null && runningApps.size() > 0) {
7354 Set<String> extList = new HashSet<String>();
7355 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7356 if (app.pkgList != null) {
7357 for (String pkg : app.pkgList) {
7358 extList.add(pkg);
7359 }
7360 }
7361 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007362 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007363 for (String pkg : extList) {
7364 try {
7365 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7366 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7367 retList.add(info);
7368 }
7369 } catch (RemoteException e) {
7370 }
7371 }
7372 }
7373 return retList;
7374 }
7375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 @Override
7377 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007378 if (checkCallingPermission(android.Manifest.permission.DUMP)
7379 != PackageManager.PERMISSION_GRANTED) {
7380 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7381 + Binder.getCallingPid()
7382 + ", uid=" + Binder.getCallingUid()
7383 + " without permission "
7384 + android.Manifest.permission.DUMP);
7385 return;
7386 }
7387
7388 boolean dumpAll = false;
7389
7390 int opti = 0;
7391 while (opti < args.length) {
7392 String opt = args[opti];
7393 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7394 break;
7395 }
7396 opti++;
7397 if ("-a".equals(opt)) {
7398 dumpAll = true;
7399 } else if ("-h".equals(opt)) {
7400 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007401 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007403 pw.println(" a[ctivities]: activity stack state");
7404 pw.println(" b[roadcasts]: broadcast state");
7405 pw.println(" i[ntents]: pending intent state");
7406 pw.println(" p[rocesses]: process state");
7407 pw.println(" o[om]: out of memory management");
7408 pw.println(" prov[iders]: content provider state");
7409 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007410 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007411 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7412 pw.println(" a partial substring in a component name, or an");
7413 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007415 } else {
7416 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007418 }
7419
7420 // Is the caller requesting to dump a particular piece of data?
7421 if (opti < args.length) {
7422 String cmd = args[opti];
7423 opti++;
7424 if ("activities".equals(cmd) || "a".equals(cmd)) {
7425 synchronized (this) {
7426 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007428 return;
7429 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7430 synchronized (this) {
7431 dumpBroadcastsLocked(fd, pw, args, opti, true);
7432 }
7433 return;
7434 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7435 synchronized (this) {
7436 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7437 }
7438 return;
7439 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7440 synchronized (this) {
7441 dumpProcessesLocked(fd, pw, args, opti, true);
7442 }
7443 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007444 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7445 synchronized (this) {
7446 dumpOomLocked(fd, pw, args, opti, true);
7447 }
7448 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007449 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7450 synchronized (this) {
7451 dumpProvidersLocked(fd, pw, args, opti, true);
7452 }
7453 return;
7454 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007455 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007456 return;
7457 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7458 synchronized (this) {
7459 dumpServicesLocked(fd, pw, args, opti, true);
7460 }
7461 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007462 } else {
7463 // Dumping a single activity?
7464 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7465 return;
7466 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007467 pw.println("Bad activity command, or no activities match: " + cmd);
7468 pw.println("Use -h for help.");
7469 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007471 }
7472
7473 // No piece of data specified, dump everything.
7474 synchronized (this) {
7475 boolean needSep;
7476 if (dumpAll) {
7477 pw.println("Providers in Current Activity Manager State:");
7478 }
7479 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7480 if (needSep) {
7481 pw.println(" ");
7482 }
7483 if (dumpAll) {
7484 pw.println("-------------------------------------------------------------------------------");
7485 pw.println("Broadcasts in Current Activity Manager State:");
7486 }
7487 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7488 if (needSep) {
7489 pw.println(" ");
7490 }
7491 if (dumpAll) {
7492 pw.println("-------------------------------------------------------------------------------");
7493 pw.println("Services in Current Activity Manager State:");
7494 }
7495 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7496 if (needSep) {
7497 pw.println(" ");
7498 }
7499 if (dumpAll) {
7500 pw.println("-------------------------------------------------------------------------------");
7501 pw.println("PendingIntents in Current Activity Manager State:");
7502 }
7503 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7504 if (needSep) {
7505 pw.println(" ");
7506 }
7507 if (dumpAll) {
7508 pw.println("-------------------------------------------------------------------------------");
7509 pw.println("Activities in Current Activity Manager State:");
7510 }
7511 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7512 if (needSep) {
7513 pw.println(" ");
7514 }
7515 if (dumpAll) {
7516 pw.println("-------------------------------------------------------------------------------");
7517 pw.println("Processes in Current Activity Manager State:");
7518 }
7519 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7520 }
7521 }
7522
7523 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7524 int opti, boolean dumpAll, boolean needHeader) {
7525 if (needHeader) {
7526 pw.println(" Activity stack:");
7527 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007528 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007529 pw.println(" ");
7530 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007531 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7532 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007534 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007535 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007536 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007537 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007539 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007540 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007541 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007542 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7543 pw.println(" ");
7544 pw.println(" Activities waiting to sleep:");
7545 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7546 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007547 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 pw.println(" ");
7549 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007550 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007553 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007554 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7555 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007556 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007557 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007558 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007560 if (dumpAll && mRecentTasks.size() > 0) {
7561 pw.println(" ");
7562 pw.println("Recent tasks in Current Activity Manager State:");
7563
7564 final int N = mRecentTasks.size();
7565 for (int i=0; i<N; i++) {
7566 TaskRecord tr = mRecentTasks.get(i);
7567 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7568 pw.println(tr);
7569 mRecentTasks.get(i).dump(pw, " ");
7570 }
7571 }
7572
7573 pw.println(" ");
7574 pw.println(" mCurTask: " + mCurTask);
7575
7576 return true;
7577 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007578
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007579 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7580 int opti, boolean dumpAll) {
7581 boolean needSep = false;
7582 int numPers = 0;
7583
7584 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7586 final int NA = procs.size();
7587 for (int ia=0; ia<NA; ia++) {
7588 if (!needSep) {
7589 pw.println(" All known processes:");
7590 needSep = true;
7591 }
7592 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007593 pw.print(r.persistent ? " *PERS*" : " *APP*");
7594 pw.print(" UID "); pw.print(procs.keyAt(ia));
7595 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 r.dump(pw, " ");
7597 if (r.persistent) {
7598 numPers++;
7599 }
7600 }
7601 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007602 }
7603
7604 if (mLruProcesses.size() > 0) {
7605 if (needSep) pw.println(" ");
7606 needSep = true;
7607 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007608 dumpProcessOomList(pw, this, mLruProcesses, " ",
7609 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007610 needSep = true;
7611 }
7612
7613 synchronized (mPidsSelfLocked) {
7614 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 if (needSep) pw.println(" ");
7616 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007617 pw.println(" PID mappings:");
7618 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7619 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7620 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007621 }
7622 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007623 }
7624
7625 if (mForegroundProcesses.size() > 0) {
7626 if (needSep) pw.println(" ");
7627 needSep = true;
7628 pw.println(" Foreground Processes:");
7629 for (int i=0; i<mForegroundProcesses.size(); i++) {
7630 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7631 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007633 }
7634
7635 if (mPersistentStartingProcesses.size() > 0) {
7636 if (needSep) pw.println(" ");
7637 needSep = true;
7638 pw.println(" Persisent processes that are starting:");
7639 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007640 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007643 if (mStartingProcesses.size() > 0) {
7644 if (needSep) pw.println(" ");
7645 needSep = true;
7646 pw.println(" Processes that are starting:");
7647 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007648 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007651 if (mRemovedProcesses.size() > 0) {
7652 if (needSep) pw.println(" ");
7653 needSep = true;
7654 pw.println(" Processes that are being removed:");
7655 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007656 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007657 }
7658
7659 if (mProcessesOnHold.size() > 0) {
7660 if (needSep) pw.println(" ");
7661 needSep = true;
7662 pw.println(" Processes that are on old until the system is ready:");
7663 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007664 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666
Dianne Hackborn287952c2010-09-22 22:34:31 -07007667 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668
7669 if (mProcessCrashTimes.getMap().size() > 0) {
7670 if (needSep) pw.println(" ");
7671 needSep = true;
7672 pw.println(" Time since processes crashed:");
7673 long now = SystemClock.uptimeMillis();
7674 for (Map.Entry<String, SparseArray<Long>> procs
7675 : mProcessCrashTimes.getMap().entrySet()) {
7676 SparseArray<Long> uids = procs.getValue();
7677 final int N = uids.size();
7678 for (int i=0; i<N; i++) {
7679 pw.print(" Process "); pw.print(procs.getKey());
7680 pw.print(" uid "); pw.print(uids.keyAt(i));
7681 pw.print(": last crashed ");
7682 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007683 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007684 }
7685 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 if (mBadProcesses.getMap().size() > 0) {
7689 if (needSep) pw.println(" ");
7690 needSep = true;
7691 pw.println(" Bad processes:");
7692 for (Map.Entry<String, SparseArray<Long>> procs
7693 : mBadProcesses.getMap().entrySet()) {
7694 SparseArray<Long> uids = procs.getValue();
7695 final int N = uids.size();
7696 for (int i=0; i<N; i++) {
7697 pw.print(" Bad process "); pw.print(procs.getKey());
7698 pw.print(" uid "); pw.print(uids.keyAt(i));
7699 pw.print(": crashed at time ");
7700 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 }
7702 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007705 pw.println(" ");
7706 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007707 if (mHeavyWeightProcess != null) {
7708 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7709 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007710 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007711 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007712 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7713 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7714 || mOrigWaitForDebugger) {
7715 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7716 + " mDebugTransient=" + mDebugTransient
7717 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7718 }
7719 if (mAlwaysFinishActivities || mController != null) {
7720 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7721 + " mController=" + mController);
7722 }
7723 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007724 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007726 + " mProcessesReady=" + mProcessesReady
7727 + " mSystemReady=" + mSystemReady);
7728 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 + " mBooted=" + mBooted
7730 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007731 pw.print(" mLastPowerCheckRealtime=");
7732 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7733 pw.println("");
7734 pw.print(" mLastPowerCheckUptime=");
7735 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7736 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007737 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7738 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007739 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007741
7742 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007743 }
7744
Dianne Hackborn287952c2010-09-22 22:34:31 -07007745 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7746 int opti, boolean needSep, boolean dumpAll) {
7747 if (mProcessesToGc.size() > 0) {
7748 if (needSep) pw.println(" ");
7749 needSep = true;
7750 pw.println(" Processes that are waiting to GC:");
7751 long now = SystemClock.uptimeMillis();
7752 for (int i=0; i<mProcessesToGc.size(); i++) {
7753 ProcessRecord proc = mProcessesToGc.get(i);
7754 pw.print(" Process "); pw.println(proc);
7755 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7756 pw.print(", last gced=");
7757 pw.print(now-proc.lastRequestedGc);
7758 pw.print(" ms ago, last lowMem=");
7759 pw.print(now-proc.lastLowMemory);
7760 pw.println(" ms ago");
7761
7762 }
7763 }
7764 return needSep;
7765 }
7766
7767 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7768 int opti, boolean dumpAll) {
7769 boolean needSep = false;
7770
7771 if (mLruProcesses.size() > 0) {
7772 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7773
7774 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7775 @Override
7776 public int compare(ProcessRecord object1, ProcessRecord object2) {
7777 if (object1.setAdj != object2.setAdj) {
7778 return object1.setAdj > object2.setAdj ? -1 : 1;
7779 }
7780 if (object1.setSchedGroup != object2.setSchedGroup) {
7781 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7782 }
7783 if (object1.keeping != object2.keeping) {
7784 return object1.keeping ? -1 : 1;
7785 }
7786 if (object1.pid != object2.pid) {
7787 return object1.pid > object2.pid ? -1 : 1;
7788 }
7789 return 0;
7790 }
7791 };
7792
7793 Collections.sort(procs, comparator);
7794
7795 if (needSep) pw.println(" ");
7796 needSep = true;
7797 pw.println(" Process OOM control:");
7798 dumpProcessOomList(pw, this, procs, " ",
7799 "Proc", "PERS", true);
7800 needSep = true;
7801 }
7802
7803 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7804
7805 pw.println(" ");
7806 pw.println(" mHomeProcess: " + mHomeProcess);
7807 if (mHeavyWeightProcess != null) {
7808 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7809 }
7810
7811 return true;
7812 }
7813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 /**
7815 * There are three ways to call this:
7816 * - no service specified: dump all the services
7817 * - a flattened component name that matched an existing service was specified as the
7818 * first arg: dump that one service
7819 * - the first arg isn't the flattened component name of an existing service:
7820 * dump all services whose component contains the first arg as a substring
7821 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007822 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 String[] newArgs;
7824 String componentNameString;
7825 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007826 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 componentNameString = null;
7828 newArgs = EMPTY_STRING_ARRAY;
7829 r = null;
7830 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007831 componentNameString = args[opti];
7832 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007834 synchronized (this) {
7835 r = componentName != null ? mServices.get(componentName) : null;
7836 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007837 newArgs = new String[args.length - opti];
7838 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 }
7840
7841 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007842 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007844 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7845 synchronized (this) {
7846 for (ServiceRecord r1 : mServices.values()) {
7847 if (componentNameString == null
7848 || r1.name.flattenToString().contains(componentNameString)) {
7849 services.add(r1);
7850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 }
7852 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007853 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007854 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 }
7857 }
7858
7859 /**
7860 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7861 * there is a thread associated with the service.
7862 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007863 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7864 pw.println("------------------------------------------------------------"
7865 + "-------------------");
7866 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 if (r.app != null && r.app.thread != null) {
7868 try {
7869 // flush anything that is already in the PrintWriter since the thread is going
7870 // to write to the file descriptor directly
7871 pw.flush();
7872 r.app.thread.dumpService(fd, r, args);
7873 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007874 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007875 } catch (RemoteException e) {
7876 pw.println("got a RemoteException while dumping the service");
7877 }
7878 }
7879 }
7880
Dianne Hackborn625ac272010-09-17 18:29:22 -07007881 /**
7882 * There are three things that cmd can be:
7883 * - a flattened component name that matched an existing activity
7884 * - the cmd arg isn't the flattened component name of an existing activity:
7885 * dump all activity whose component contains the cmd as a substring
7886 * - A hex number of the ActivityRecord object instance.
7887 */
7888 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7889 int opti, boolean dumpAll) {
7890 String[] newArgs;
7891 ComponentName componentName = ComponentName.unflattenFromString(name);
7892 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007893 if (componentName == null) {
7894 // Not a '/' separated full component name; maybe an object ID?
7895 try {
7896 objectId = Integer.parseInt(name, 16);
7897 name = null;
7898 componentName = null;
7899 } catch (RuntimeException e) {
7900 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007901 }
7902 newArgs = new String[args.length - opti];
7903 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7904
7905 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7906 synchronized (this) {
7907 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7908 if (componentName != null) {
7909 if (r1.intent.getComponent().equals(componentName)) {
7910 activities.add(r1);
7911 }
7912 } else if (name != null) {
7913 if (r1.intent.getComponent().flattenToString().contains(name)) {
7914 activities.add(r1);
7915 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007916 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007917 activities.add(r1);
7918 }
7919 }
7920 }
7921
7922 if (activities.size() <= 0) {
7923 return false;
7924 }
7925
Dianne Hackborn30d71892010-12-11 10:37:55 -08007926 TaskRecord lastTask = null;
7927 for (int i=activities.size()-1; i>=0; i--) {
7928 ActivityRecord r = (ActivityRecord)activities.get(i);
7929 if (lastTask != r.task) {
7930 lastTask = r.task;
7931 pw.print("* Task "); pw.print(lastTask.affinity);
7932 pw.print(" id="); pw.println(lastTask.taskId);
7933 if (dumpAll) {
7934 lastTask.dump(pw, " ");
7935 }
7936 }
7937 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007938 }
7939 return true;
7940 }
7941
7942 /**
7943 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7944 * there is a thread associated with the activity.
7945 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007946 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7947 ActivityRecord r, String[] args, boolean dumpAll) {
7948 synchronized (this) {
7949 pw.print(prefix); pw.print("* Activity ");
7950 pw.print(Integer.toHexString(System.identityHashCode(r)));
7951 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7952 if (r.app != null) pw.println(r.app.pid);
7953 else pw.println("(not running)");
7954 if (dumpAll) {
7955 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007956 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007957 }
7958 if (r.app != null && r.app.thread != null) {
7959 try {
7960 // flush anything that is already in the PrintWriter since the thread is going
7961 // to write to the file descriptor directly
7962 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08007963 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007964 pw.flush();
7965 } catch (RemoteException e) {
7966 pw.println("got a RemoteException while dumping the activity");
7967 }
7968 }
7969 }
7970
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007971 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7972 int opti, boolean dumpAll) {
7973 boolean needSep = false;
7974
7975 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 if (mRegisteredReceivers.size() > 0) {
7977 pw.println(" ");
7978 pw.println(" Registered Receivers:");
7979 Iterator it = mRegisteredReceivers.values().iterator();
7980 while (it.hasNext()) {
7981 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007982 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007983 r.dump(pw, " ");
7984 }
7985 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 pw.println(" ");
7988 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007989 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007990 needSep = true;
7991 }
7992
7993 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7994 || mPendingBroadcast != null) {
7995 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007997 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007999 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8000 pw.println(" Broadcast #" + i + ":");
8001 mParallelBroadcasts.get(i).dump(pw, " ");
8002 }
8003 if (mOrderedBroadcasts.size() > 0) {
8004 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008005 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008006 }
8007 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8008 pw.println(" Serialized Broadcast #" + i + ":");
8009 mOrderedBroadcasts.get(i).dump(pw, " ");
8010 }
8011 pw.println(" ");
8012 pw.println(" Pending broadcast:");
8013 if (mPendingBroadcast != null) {
8014 mPendingBroadcast.dump(pw, " ");
8015 } else {
8016 pw.println(" (null)");
8017 }
8018 needSep = true;
8019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008021 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008023 pw.println(" Historical broadcasts:");
8024 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8025 BroadcastRecord r = mBroadcastHistory[i];
8026 if (r == null) {
8027 break;
8028 }
8029 pw.println(" Historical Broadcast #" + i + ":");
8030 r.dump(pw, " ");
8031 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008032 needSep = true;
8033 }
8034
8035 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008036 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008037 pw.println(" Sticky broadcasts:");
8038 StringBuilder sb = new StringBuilder(128);
8039 for (Map.Entry<String, ArrayList<Intent>> ent
8040 : mStickyBroadcasts.entrySet()) {
8041 pw.print(" * Sticky action "); pw.print(ent.getKey());
8042 pw.println(":");
8043 ArrayList<Intent> intents = ent.getValue();
8044 final int N = intents.size();
8045 for (int i=0; i<N; i++) {
8046 sb.setLength(0);
8047 sb.append(" Intent: ");
8048 intents.get(i).toShortString(sb, true, false);
8049 pw.println(sb.toString());
8050 Bundle bundle = intents.get(i).getExtras();
8051 if (bundle != null) {
8052 pw.print(" ");
8053 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 }
8055 }
8056 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008057 needSep = true;
8058 }
8059
8060 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008062 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 pw.println(" mHandler:");
8064 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008065 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008067
8068 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 }
8070
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008071 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8072 int opti, boolean dumpAll) {
8073 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008074
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008075 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 if (mServices.size() > 0) {
8077 pw.println(" Active services:");
8078 Iterator<ServiceRecord> it = mServices.values().iterator();
8079 while (it.hasNext()) {
8080 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008081 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 r.dump(pw, " ");
8083 }
8084 needSep = true;
8085 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008087
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008088 if (mPendingServices.size() > 0) {
8089 if (needSep) pw.println(" ");
8090 pw.println(" Pending services:");
8091 for (int i=0; i<mPendingServices.size(); i++) {
8092 ServiceRecord r = mPendingServices.get(i);
8093 pw.print(" * Pending "); pw.println(r);
8094 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008095 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008096 needSep = true;
8097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008099 if (mRestartingServices.size() > 0) {
8100 if (needSep) pw.println(" ");
8101 pw.println(" Restarting services:");
8102 for (int i=0; i<mRestartingServices.size(); i++) {
8103 ServiceRecord r = mRestartingServices.get(i);
8104 pw.print(" * Restarting "); pw.println(r);
8105 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008107 needSep = true;
8108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008110 if (mStoppingServices.size() > 0) {
8111 if (needSep) pw.println(" ");
8112 pw.println(" Stopping services:");
8113 for (int i=0; i<mStoppingServices.size(); i++) {
8114 ServiceRecord r = mStoppingServices.get(i);
8115 pw.print(" * Stopping "); pw.println(r);
8116 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008118 needSep = true;
8119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008120
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008121 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122 if (mServiceConnections.size() > 0) {
8123 if (needSep) pw.println(" ");
8124 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008125 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008126 = mServiceConnections.values().iterator();
8127 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008128 ArrayList<ConnectionRecord> r = it.next();
8129 for (int i=0; i<r.size(); i++) {
8130 pw.print(" * "); pw.println(r.get(i));
8131 r.get(i).dump(pw, " ");
8132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008134 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 }
8136 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008137
8138 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 }
8140
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008141 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8142 int opti, boolean dumpAll) {
8143 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008145 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008146 if (mProvidersByClass.size() > 0) {
8147 if (needSep) pw.println(" ");
8148 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008149 Iterator<Map.Entry<String, ContentProviderRecord>> it
8150 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008152 Map.Entry<String, ContentProviderRecord> e = it.next();
8153 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008154 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 r.dump(pw, " ");
8156 }
8157 needSep = true;
8158 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008159
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008160 if (mProvidersByName.size() > 0) {
8161 pw.println(" ");
8162 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008163 Iterator<Map.Entry<String, ContentProviderRecord>> it
8164 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008165 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008166 Map.Entry<String, ContentProviderRecord> e = it.next();
8167 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008168 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8169 pw.println(r);
8170 }
8171 needSep = true;
8172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008174
8175 if (mLaunchingProviders.size() > 0) {
8176 if (needSep) pw.println(" ");
8177 pw.println(" Launching content providers:");
8178 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8179 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8180 pw.println(mLaunchingProviders.get(i));
8181 }
8182 needSep = true;
8183 }
8184
8185 if (mGrantedUriPermissions.size() > 0) {
8186 pw.println();
8187 pw.println("Granted Uri Permissions:");
8188 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8189 int uid = mGrantedUriPermissions.keyAt(i);
8190 HashMap<Uri, UriPermission> perms
8191 = mGrantedUriPermissions.valueAt(i);
8192 pw.print(" * UID "); pw.print(uid);
8193 pw.println(" holds:");
8194 for (UriPermission perm : perms.values()) {
8195 pw.print(" "); pw.println(perm);
8196 perm.dump(pw, " ");
8197 }
8198 }
8199 needSep = true;
8200 }
8201
8202 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008203 }
8204
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008205 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8206 int opti, boolean dumpAll) {
8207 boolean needSep = false;
8208
8209 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008210 if (this.mIntentSenderRecords.size() > 0) {
8211 Iterator<WeakReference<PendingIntentRecord>> it
8212 = mIntentSenderRecords.values().iterator();
8213 while (it.hasNext()) {
8214 WeakReference<PendingIntentRecord> ref = it.next();
8215 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008216 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008218 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 rec.dump(pw, " ");
8220 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008221 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222 }
8223 }
8224 }
8225 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008226
8227 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 }
8229
8230 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008231 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008232 TaskRecord lastTask = null;
8233 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008234 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008235 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 if (lastTask != r.task) {
8237 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008238 pw.print(prefix);
8239 pw.print(full ? "* " : " ");
8240 pw.println(lastTask);
8241 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008242 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008244 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008245 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8246 pw.print(" #"); pw.print(i); pw.print(": ");
8247 pw.println(r);
8248 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008249 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008251 }
8252 }
8253
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008254 private static String buildOomTag(String prefix, String space, int val, int base) {
8255 if (val == base) {
8256 if (space == null) return prefix;
8257 return prefix + " ";
8258 }
8259 return prefix + "+" + Integer.toString(val-base);
8260 }
8261
8262 private static final int dumpProcessList(PrintWriter pw,
8263 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008264 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008266 final int N = list.size()-1;
8267 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008269 pw.println(String.format("%s%s #%2d: %s",
8270 prefix, (r.persistent ? persistentLabel : normalLabel),
8271 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 if (r.persistent) {
8273 numPers++;
8274 }
8275 }
8276 return numPers;
8277 }
8278
Dianne Hackborn287952c2010-09-22 22:34:31 -07008279 private static final void dumpProcessOomList(PrintWriter pw,
8280 ActivityManagerService service, List<ProcessRecord> list,
8281 String prefix, String normalLabel, String persistentLabel,
8282 boolean inclDetails) {
8283
8284 final long curRealtime = SystemClock.elapsedRealtime();
8285 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8286 final long curUptime = SystemClock.uptimeMillis();
8287 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8288
8289 final int N = list.size()-1;
8290 for (int i=N; i>=0; i--) {
8291 ProcessRecord r = list.get(i);
8292 String oomAdj;
8293 if (r.setAdj >= EMPTY_APP_ADJ) {
8294 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8295 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8296 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8297 } else if (r.setAdj >= HOME_APP_ADJ) {
8298 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8299 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8300 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8301 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8302 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8303 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8304 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8305 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8306 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8307 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8308 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8309 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8310 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8311 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8312 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8313 } else if (r.setAdj >= SYSTEM_ADJ) {
8314 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8315 } else {
8316 oomAdj = Integer.toString(r.setAdj);
8317 }
8318 String schedGroup;
8319 switch (r.setSchedGroup) {
8320 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8321 schedGroup = "B";
8322 break;
8323 case Process.THREAD_GROUP_DEFAULT:
8324 schedGroup = "F";
8325 break;
8326 default:
8327 schedGroup = Integer.toString(r.setSchedGroup);
8328 break;
8329 }
8330 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8331 prefix, (r.persistent ? persistentLabel : normalLabel),
8332 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8333 if (r.adjSource != null || r.adjTarget != null) {
8334 pw.print(prefix);
8335 pw.print(" ");
8336 if (r.adjTarget instanceof ComponentName) {
8337 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8338 } else if (r.adjTarget != null) {
8339 pw.print(r.adjTarget.toString());
8340 } else {
8341 pw.print("{null}");
8342 }
8343 pw.print("<=");
8344 if (r.adjSource instanceof ProcessRecord) {
8345 pw.print("Proc{");
8346 pw.print(((ProcessRecord)r.adjSource).toShortString());
8347 pw.println("}");
8348 } else if (r.adjSource != null) {
8349 pw.println(r.adjSource.toString());
8350 } else {
8351 pw.println("{null}");
8352 }
8353 }
8354 if (inclDetails) {
8355 pw.print(prefix);
8356 pw.print(" ");
8357 pw.print("oom: max="); pw.print(r.maxAdj);
8358 pw.print(" hidden="); pw.print(r.hiddenAdj);
8359 pw.print(" curRaw="); pw.print(r.curRawAdj);
8360 pw.print(" setRaw="); pw.print(r.setRawAdj);
8361 pw.print(" cur="); pw.print(r.curAdj);
8362 pw.print(" set="); pw.println(r.setAdj);
8363 pw.print(prefix);
8364 pw.print(" ");
8365 pw.print("keeping="); pw.print(r.keeping);
8366 pw.print(" hidden="); pw.print(r.hidden);
8367 pw.print(" empty="); pw.println(r.empty);
8368
8369 if (!r.keeping) {
8370 if (r.lastWakeTime != 0) {
8371 long wtime;
8372 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8373 synchronized (stats) {
8374 wtime = stats.getProcessWakeTime(r.info.uid,
8375 r.pid, curRealtime);
8376 }
8377 long timeUsed = wtime - r.lastWakeTime;
8378 pw.print(prefix);
8379 pw.print(" ");
8380 pw.print("keep awake over ");
8381 TimeUtils.formatDuration(realtimeSince, pw);
8382 pw.print(" used ");
8383 TimeUtils.formatDuration(timeUsed, pw);
8384 pw.print(" (");
8385 pw.print((timeUsed*100)/realtimeSince);
8386 pw.println("%)");
8387 }
8388 if (r.lastCpuTime != 0) {
8389 long timeUsed = r.curCpuTime - r.lastCpuTime;
8390 pw.print(prefix);
8391 pw.print(" ");
8392 pw.print("run cpu over ");
8393 TimeUtils.formatDuration(uptimeSince, pw);
8394 pw.print(" used ");
8395 TimeUtils.formatDuration(timeUsed, pw);
8396 pw.print(" (");
8397 pw.print((timeUsed*100)/uptimeSince);
8398 pw.println("%)");
8399 }
8400 }
8401 }
8402 }
8403 }
8404
Dianne Hackborn472ad872010-04-07 17:31:48 -07008405 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008406 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008407 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 long uptime = SystemClock.uptimeMillis();
8409 long realtime = SystemClock.elapsedRealtime();
8410
8411 if (isCheckinRequest) {
8412 // short checkin version
8413 pw.println(uptime + "," + realtime);
8414 pw.flush();
8415 } else {
8416 pw.println("Applications Memory Usage (kB):");
8417 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8418 }
8419 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8420 ProcessRecord r = (ProcessRecord)list.get(i);
8421 if (r.thread != null) {
8422 if (!isCheckinRequest) {
8423 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8424 pw.flush();
8425 }
8426 try {
8427 r.thread.asBinder().dump(fd, args);
8428 } catch (RemoteException e) {
8429 if (!isCheckinRequest) {
8430 pw.println("Got RemoteException!");
8431 pw.flush();
8432 }
8433 }
8434 }
8435 }
8436 }
8437
8438 /**
8439 * Searches array of arguments for the specified string
8440 * @param args array of argument strings
8441 * @param value value to search for
8442 * @return true if the value is contained in the array
8443 */
8444 private static boolean scanArgs(String[] args, String value) {
8445 if (args != null) {
8446 for (String arg : args) {
8447 if (value.equals(arg)) {
8448 return true;
8449 }
8450 }
8451 }
8452 return false;
8453 }
8454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 private final void killServicesLocked(ProcessRecord app,
8456 boolean allowRestart) {
8457 // Report disconnected services.
8458 if (false) {
8459 // XXX we are letting the client link to the service for
8460 // death notifications.
8461 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008462 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008464 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008466 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 = r.connections.values().iterator();
8468 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008469 ArrayList<ConnectionRecord> cl = jt.next();
8470 for (int i=0; i<cl.size(); i++) {
8471 ConnectionRecord c = cl.get(i);
8472 if (c.binding.client != app) {
8473 try {
8474 //c.conn.connected(r.className, null);
8475 } catch (Exception e) {
8476 // todo: this should be asynchronous!
8477 Slog.w(TAG, "Exception thrown disconnected servce "
8478 + r.shortName
8479 + " from app " + app.processName, e);
8480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008481 }
8482 }
8483 }
8484 }
8485 }
8486 }
8487 }
8488
8489 // Clean up any connections this application has to other services.
8490 if (app.connections.size() > 0) {
8491 Iterator<ConnectionRecord> it = app.connections.iterator();
8492 while (it.hasNext()) {
8493 ConnectionRecord r = it.next();
8494 removeConnectionLocked(r, app, null);
8495 }
8496 }
8497 app.connections.clear();
8498
8499 if (app.services.size() != 0) {
8500 // Any services running in the application need to be placed
8501 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008502 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008503 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008504 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 synchronized (sr.stats.getBatteryStats()) {
8506 sr.stats.stopLaunchedLocked();
8507 }
8508 sr.app = null;
8509 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008510 if (mStoppingServices.remove(sr)) {
8511 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8512 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008513
8514 boolean hasClients = sr.bindings.size() > 0;
8515 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 Iterator<IntentBindRecord> bindings
8517 = sr.bindings.values().iterator();
8518 while (bindings.hasNext()) {
8519 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008520 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 + ": shouldUnbind=" + b.hasBound);
8522 b.binder = null;
8523 b.requested = b.received = b.hasBound = false;
8524 }
8525 }
8526
Dianne Hackborn070783f2010-12-29 16:46:28 -08008527 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8528 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008529 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008531 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 sr.crashCount, sr.shortName, app.pid);
8533 bringDownServiceLocked(sr, true);
8534 } else if (!allowRestart) {
8535 bringDownServiceLocked(sr, true);
8536 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008537 boolean canceled = scheduleServiceRestartLocked(sr, true);
8538
8539 // Should the service remain running? Note that in the
8540 // extreme case of so many attempts to deliver a command
8541 // that it failed, that we also will stop it here.
8542 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8543 if (sr.pendingStarts.size() == 0) {
8544 sr.startRequested = false;
8545 if (!hasClients) {
8546 // Whoops, no reason to restart!
8547 bringDownServiceLocked(sr, true);
8548 }
8549 }
8550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 }
8552 }
8553
8554 if (!allowRestart) {
8555 app.services.clear();
8556 }
8557 }
8558
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008559 // Make sure we have no more records on the stopping list.
8560 int i = mStoppingServices.size();
8561 while (i > 0) {
8562 i--;
8563 ServiceRecord sr = mStoppingServices.get(i);
8564 if (sr.app == app) {
8565 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008566 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008567 }
8568 }
8569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 app.executingServices.clear();
8571 }
8572
8573 private final void removeDyingProviderLocked(ProcessRecord proc,
8574 ContentProviderRecord cpr) {
8575 synchronized (cpr) {
8576 cpr.launchingApp = null;
8577 cpr.notifyAll();
8578 }
8579
8580 mProvidersByClass.remove(cpr.info.name);
8581 String names[] = cpr.info.authority.split(";");
8582 for (int j = 0; j < names.length; j++) {
8583 mProvidersByName.remove(names[j]);
8584 }
8585
8586 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8587 while (cit.hasNext()) {
8588 ProcessRecord capp = cit.next();
8589 if (!capp.persistent && capp.thread != null
8590 && capp.pid != 0
8591 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008592 Slog.i(TAG, "Kill " + capp.processName
8593 + " (pid " + capp.pid + "): provider " + cpr.info.name
8594 + " in dying process " + proc.processName);
8595 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8596 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 Process.killProcess(capp.pid);
8598 }
8599 }
8600
8601 mLaunchingProviders.remove(cpr);
8602 }
8603
8604 /**
8605 * Main code for cleaning up a process when it has gone away. This is
8606 * called both as a result of the process dying, or directly when stopping
8607 * a process when running in single process mode.
8608 */
8609 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8610 boolean restarting, int index) {
8611 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008612 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 }
8614
Dianne Hackborn36124872009-10-08 16:22:03 -07008615 mProcessesToGc.remove(app);
8616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 // Dismiss any open dialogs.
8618 if (app.crashDialog != null) {
8619 app.crashDialog.dismiss();
8620 app.crashDialog = null;
8621 }
8622 if (app.anrDialog != null) {
8623 app.anrDialog.dismiss();
8624 app.anrDialog = null;
8625 }
8626 if (app.waitDialog != null) {
8627 app.waitDialog.dismiss();
8628 app.waitDialog = null;
8629 }
8630
8631 app.crashing = false;
8632 app.notResponding = false;
8633
8634 app.resetPackageList();
8635 app.thread = null;
8636 app.forcingToForeground = null;
8637 app.foregroundServices = false;
8638
8639 killServicesLocked(app, true);
8640
8641 boolean restart = false;
8642
8643 int NL = mLaunchingProviders.size();
8644
8645 // Remove published content providers.
8646 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008647 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008649 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 cpr.provider = null;
8651 cpr.app = null;
8652
8653 // See if someone is waiting for this provider... in which
8654 // case we don't remove it, but just let it restart.
8655 int i = 0;
8656 if (!app.bad) {
8657 for (; i<NL; i++) {
8658 if (mLaunchingProviders.get(i) == cpr) {
8659 restart = true;
8660 break;
8661 }
8662 }
8663 } else {
8664 i = NL;
8665 }
8666
8667 if (i >= NL) {
8668 removeDyingProviderLocked(app, cpr);
8669 NL = mLaunchingProviders.size();
8670 }
8671 }
8672 app.pubProviders.clear();
8673 }
8674
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008675 // Take care of any launching providers waiting for this process.
8676 if (checkAppInLaunchingProvidersLocked(app, false)) {
8677 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 // Unregister from connected content providers.
8681 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008682 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 while (it.hasNext()) {
8684 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8685 cpr.clients.remove(app);
8686 }
8687 app.conProviders.clear();
8688 }
8689
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008690 // At this point there may be remaining entries in mLaunchingProviders
8691 // where we were the only one waiting, so they are no longer of use.
8692 // Look for these and clean up if found.
8693 // XXX Commented out for now. Trying to figure out a way to reproduce
8694 // the actual situation to identify what is actually going on.
8695 if (false) {
8696 for (int i=0; i<NL; i++) {
8697 ContentProviderRecord cpr = (ContentProviderRecord)
8698 mLaunchingProviders.get(i);
8699 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8700 synchronized (cpr) {
8701 cpr.launchingApp = null;
8702 cpr.notifyAll();
8703 }
8704 }
8705 }
8706 }
8707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 skipCurrentReceiverLocked(app);
8709
8710 // Unregister any receivers.
8711 if (app.receivers.size() > 0) {
8712 Iterator<ReceiverList> it = app.receivers.iterator();
8713 while (it.hasNext()) {
8714 removeReceiverLocked(it.next());
8715 }
8716 app.receivers.clear();
8717 }
8718
Christopher Tate181fafa2009-05-14 11:12:14 -07008719 // If the app is undergoing backup, tell the backup manager about it
8720 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008721 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008722 try {
8723 IBackupManager bm = IBackupManager.Stub.asInterface(
8724 ServiceManager.getService(Context.BACKUP_SERVICE));
8725 bm.agentDisconnected(app.info.packageName);
8726 } catch (RemoteException e) {
8727 // can't happen; backup manager is local
8728 }
8729 }
8730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 // If the caller is restarting this app, then leave it in its
8732 // current lists and let the caller take care of it.
8733 if (restarting) {
8734 return;
8735 }
8736
8737 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008738 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008739 "Removing non-persistent process during cleanup: " + app);
8740 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008741 if (mHeavyWeightProcess == app) {
8742 mHeavyWeightProcess = null;
8743 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 } else if (!app.removed) {
8746 // This app is persistent, so we need to keep its record around.
8747 // If it is not already on the pending app list, add it there
8748 // and start a new process for it.
8749 app.thread = null;
8750 app.forcingToForeground = null;
8751 app.foregroundServices = false;
8752 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8753 mPersistentStartingProcesses.add(app);
8754 restart = true;
8755 }
8756 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008757 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8758 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 mProcessesOnHold.remove(app);
8760
The Android Open Source Project4df24232009-03-05 14:34:35 -08008761 if (app == mHomeProcess) {
8762 mHomeProcess = null;
8763 }
8764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 if (restart) {
8766 // We have components that still need to be running in the
8767 // process, so re-launch it.
8768 mProcessNames.put(app.processName, app.info.uid, app);
8769 startProcessLocked(app, "restart", app.processName);
8770 } else if (app.pid > 0 && app.pid != MY_PID) {
8771 // Goodbye!
8772 synchronized (mPidsSelfLocked) {
8773 mPidsSelfLocked.remove(app.pid);
8774 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8775 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008776 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 }
8778 }
8779
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008780 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8781 // Look through the content providers we are waiting to have launched,
8782 // and if any run in this process then either schedule a restart of
8783 // the process or kill the client waiting for it if this process has
8784 // gone bad.
8785 int NL = mLaunchingProviders.size();
8786 boolean restart = false;
8787 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008788 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008789 if (cpr.launchingApp == app) {
8790 if (!alwaysBad && !app.bad) {
8791 restart = true;
8792 } else {
8793 removeDyingProviderLocked(app, cpr);
8794 NL = mLaunchingProviders.size();
8795 }
8796 }
8797 }
8798 return restart;
8799 }
8800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 // =========================================================
8802 // SERVICES
8803 // =========================================================
8804
8805 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8806 ActivityManager.RunningServiceInfo info =
8807 new ActivityManager.RunningServiceInfo();
8808 info.service = r.name;
8809 if (r.app != null) {
8810 info.pid = r.app.pid;
8811 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008812 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 info.process = r.processName;
8814 info.foreground = r.isForeground;
8815 info.activeSince = r.createTime;
8816 info.started = r.startRequested;
8817 info.clientCount = r.connections.size();
8818 info.crashCount = r.crashCount;
8819 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008820 if (r.isForeground) {
8821 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8822 }
8823 if (r.startRequested) {
8824 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8825 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008826 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008827 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8828 }
8829 if (r.app != null && r.app.persistent) {
8830 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8831 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008832
8833 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8834 for (int i=0; i<connl.size(); i++) {
8835 ConnectionRecord conn = connl.get(i);
8836 if (conn.clientLabel != 0) {
8837 info.clientPackage = conn.binding.client.info.packageName;
8838 info.clientLabel = conn.clientLabel;
8839 return info;
8840 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008841 }
8842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 return info;
8844 }
8845
8846 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8847 int flags) {
8848 synchronized (this) {
8849 ArrayList<ActivityManager.RunningServiceInfo> res
8850 = new ArrayList<ActivityManager.RunningServiceInfo>();
8851
8852 if (mServices.size() > 0) {
8853 Iterator<ServiceRecord> it = mServices.values().iterator();
8854 while (it.hasNext() && res.size() < maxNum) {
8855 res.add(makeRunningServiceInfoLocked(it.next()));
8856 }
8857 }
8858
8859 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8860 ServiceRecord r = mRestartingServices.get(i);
8861 ActivityManager.RunningServiceInfo info =
8862 makeRunningServiceInfoLocked(r);
8863 info.restarting = r.nextRestartTime;
8864 res.add(info);
8865 }
8866
8867 return res;
8868 }
8869 }
8870
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008871 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8872 synchronized (this) {
8873 ServiceRecord r = mServices.get(name);
8874 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008875 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8876 for (int i=0; i<conn.size(); i++) {
8877 if (conn.get(i).clientIntent != null) {
8878 return conn.get(i).clientIntent;
8879 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008880 }
8881 }
8882 }
8883 }
8884 return null;
8885 }
8886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 private final ServiceRecord findServiceLocked(ComponentName name,
8888 IBinder token) {
8889 ServiceRecord r = mServices.get(name);
8890 return r == token ? r : null;
8891 }
8892
8893 private final class ServiceLookupResult {
8894 final ServiceRecord record;
8895 final String permission;
8896
8897 ServiceLookupResult(ServiceRecord _record, String _permission) {
8898 record = _record;
8899 permission = _permission;
8900 }
8901 };
8902
8903 private ServiceLookupResult findServiceLocked(Intent service,
8904 String resolvedType) {
8905 ServiceRecord r = null;
8906 if (service.getComponent() != null) {
8907 r = mServices.get(service.getComponent());
8908 }
8909 if (r == null) {
8910 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8911 r = mServicesByIntent.get(filter);
8912 }
8913
8914 if (r == null) {
8915 try {
8916 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008917 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008918 service, resolvedType, 0);
8919 ServiceInfo sInfo =
8920 rInfo != null ? rInfo.serviceInfo : null;
8921 if (sInfo == null) {
8922 return null;
8923 }
8924
8925 ComponentName name = new ComponentName(
8926 sInfo.applicationInfo.packageName, sInfo.name);
8927 r = mServices.get(name);
8928 } catch (RemoteException ex) {
8929 // pm is in same process, this will never happen.
8930 }
8931 }
8932 if (r != null) {
8933 int callingPid = Binder.getCallingPid();
8934 int callingUid = Binder.getCallingUid();
8935 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008936 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008938 if (!r.exported) {
8939 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
8940 + " from pid=" + callingPid
8941 + ", uid=" + callingUid
8942 + " that is not exported from uid " + r.appInfo.uid);
8943 return new ServiceLookupResult(null, "not exported from uid "
8944 + r.appInfo.uid);
8945 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008946 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 + " from pid=" + callingPid
8948 + ", uid=" + callingUid
8949 + " requires " + r.permission);
8950 return new ServiceLookupResult(null, r.permission);
8951 }
8952 return new ServiceLookupResult(r, null);
8953 }
8954 return null;
8955 }
8956
8957 private class ServiceRestarter implements Runnable {
8958 private ServiceRecord mService;
8959
8960 void setService(ServiceRecord service) {
8961 mService = service;
8962 }
8963
8964 public void run() {
8965 synchronized(ActivityManagerService.this) {
8966 performServiceRestartLocked(mService);
8967 }
8968 }
8969 }
8970
8971 private ServiceLookupResult retrieveServiceLocked(Intent service,
8972 String resolvedType, int callingPid, int callingUid) {
8973 ServiceRecord r = null;
8974 if (service.getComponent() != null) {
8975 r = mServices.get(service.getComponent());
8976 }
8977 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8978 r = mServicesByIntent.get(filter);
8979 if (r == null) {
8980 try {
8981 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008982 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008983 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 ServiceInfo sInfo =
8985 rInfo != null ? rInfo.serviceInfo : null;
8986 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008987 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008988 ": not found");
8989 return null;
8990 }
8991
8992 ComponentName name = new ComponentName(
8993 sInfo.applicationInfo.packageName, sInfo.name);
8994 r = mServices.get(name);
8995 if (r == null) {
8996 filter = new Intent.FilterComparison(service.cloneFilter());
8997 ServiceRestarter res = new ServiceRestarter();
8998 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8999 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9000 synchronized (stats) {
9001 ss = stats.getServiceStatsLocked(
9002 sInfo.applicationInfo.uid, sInfo.packageName,
9003 sInfo.name);
9004 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009005 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 res.setService(r);
9007 mServices.put(name, r);
9008 mServicesByIntent.put(filter, r);
9009
9010 // Make sure this component isn't in the pending list.
9011 int N = mPendingServices.size();
9012 for (int i=0; i<N; i++) {
9013 ServiceRecord pr = mPendingServices.get(i);
9014 if (pr.name.equals(name)) {
9015 mPendingServices.remove(i);
9016 i--;
9017 N--;
9018 }
9019 }
9020 }
9021 } catch (RemoteException ex) {
9022 // pm is in same process, this will never happen.
9023 }
9024 }
9025 if (r != null) {
9026 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009027 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009028 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009029 if (!r.exported) {
9030 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9031 + " from pid=" + callingPid
9032 + ", uid=" + callingUid
9033 + " that is not exported from uid " + r.appInfo.uid);
9034 return new ServiceLookupResult(null, "not exported from uid "
9035 + r.appInfo.uid);
9036 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009037 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009038 + " from pid=" + callingPid
9039 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 + " requires " + r.permission);
9041 return new ServiceLookupResult(null, r.permission);
9042 }
9043 return new ServiceLookupResult(r, null);
9044 }
9045 return null;
9046 }
9047
Dianne Hackborn287952c2010-09-22 22:34:31 -07009048 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9049 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9050 + why + " of " + r + " in app " + r.app);
9051 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9052 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 long now = SystemClock.uptimeMillis();
9054 if (r.executeNesting == 0 && r.app != null) {
9055 if (r.app.executingServices.size() == 0) {
9056 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9057 msg.obj = r.app;
9058 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9059 }
9060 r.app.executingServices.add(r);
9061 }
9062 r.executeNesting++;
9063 r.executingStart = now;
9064 }
9065
9066 private final void sendServiceArgsLocked(ServiceRecord r,
9067 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009068 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 if (N == 0) {
9070 return;
9071 }
9072
Dianne Hackborn39792d22010-08-19 18:01:52 -07009073 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009075 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009076 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9077 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009078 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009079 // If somehow we got a dummy start at the front, then
9080 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009081 continue;
9082 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009083 si.deliveredTime = SystemClock.uptimeMillis();
9084 r.deliveredStarts.add(si);
9085 si.deliveryCount++;
9086 if (si.targetPermissionUid >= 0) {
9087 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009088 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009089 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009090 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 if (!oomAdjusted) {
9092 oomAdjusted = true;
9093 updateOomAdjLocked(r.app);
9094 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009095 int flags = 0;
9096 if (si.deliveryCount > 0) {
9097 flags |= Service.START_FLAG_RETRY;
9098 }
9099 if (si.doneExecutingCount > 0) {
9100 flags |= Service.START_FLAG_REDELIVERY;
9101 }
9102 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009103 } catch (RemoteException e) {
9104 // Remote process gone... we'll let the normal cleanup take
9105 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009106 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009107 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009109 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009110 break;
9111 }
9112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 }
9114
9115 private final boolean requestServiceBindingLocked(ServiceRecord r,
9116 IntentBindRecord i, boolean rebind) {
9117 if (r.app == null || r.app.thread == null) {
9118 // If service is not currently running, can't yet bind.
9119 return false;
9120 }
9121 if ((!i.requested || rebind) && i.apps.size() > 0) {
9122 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009123 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9125 if (!rebind) {
9126 i.requested = true;
9127 }
9128 i.hasBound = true;
9129 i.doRebind = false;
9130 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009131 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 return false;
9133 }
9134 }
9135 return true;
9136 }
9137
9138 private final void requestServiceBindingsLocked(ServiceRecord r) {
9139 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9140 while (bindings.hasNext()) {
9141 IntentBindRecord i = bindings.next();
9142 if (!requestServiceBindingLocked(r, i, false)) {
9143 break;
9144 }
9145 }
9146 }
9147
9148 private final void realStartServiceLocked(ServiceRecord r,
9149 ProcessRecord app) throws RemoteException {
9150 if (app.thread == null) {
9151 throw new RemoteException();
9152 }
9153
9154 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009155 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156
9157 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009158 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009159 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160
9161 boolean created = false;
9162 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009163 mStringBuilder.setLength(0);
9164 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009165 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009166 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009167 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168 synchronized (r.stats.getBatteryStats()) {
9169 r.stats.startLaunchedLocked();
9170 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009171 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009173 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 created = true;
9175 } finally {
9176 if (!created) {
9177 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009178 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 }
9180 }
9181
9182 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009183
9184 // If the service is in the started state, and there are no
9185 // pending arguments, then fake up one so its onStartCommand() will
9186 // be called.
9187 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9188 r.lastStartId++;
9189 if (r.lastStartId < 1) {
9190 r.lastStartId = 1;
9191 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009192 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009193 }
9194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 sendServiceArgsLocked(r, true);
9196 }
9197
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009198 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9199 boolean allowCancel) {
9200 boolean canceled = false;
9201
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009202 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009203 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009204 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009205
Dianne Hackborn070783f2010-12-29 16:46:28 -08009206 if ((r.serviceInfo.applicationInfo.flags
9207 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9208 minDuration /= 4;
9209 }
9210
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009211 // Any delivered but not yet finished starts should be put back
9212 // on the pending list.
9213 final int N = r.deliveredStarts.size();
9214 if (N > 0) {
9215 for (int i=N-1; i>=0; i--) {
9216 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009217 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009218 if (si.intent == null) {
9219 // We'll generate this again if needed.
9220 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9221 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9222 r.pendingStarts.add(0, si);
9223 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9224 dur *= 2;
9225 if (minDuration < dur) minDuration = dur;
9226 if (resetTime < dur) resetTime = dur;
9227 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009228 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009229 + r.name);
9230 canceled = true;
9231 }
9232 }
9233 r.deliveredStarts.clear();
9234 }
9235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 r.totalRestartCount++;
9237 if (r.restartDelay == 0) {
9238 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009239 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 } else {
9241 // If it has been a "reasonably long time" since the service
9242 // was started, then reset our restart duration back to
9243 // the beginning, so we don't infinitely increase the duration
9244 // on a service that just occasionally gets killed (which is
9245 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009246 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009247 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009248 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009250 if ((r.serviceInfo.applicationInfo.flags
9251 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9252 // Services in peristent processes will restart much more
9253 // quickly, since they are pretty important. (Think SystemUI).
9254 r.restartDelay += minDuration/2;
9255 } else {
9256 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9257 if (r.restartDelay < minDuration) {
9258 r.restartDelay = minDuration;
9259 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 }
9262 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009263
9264 r.nextRestartTime = now + r.restartDelay;
9265
9266 // Make sure that we don't end up restarting a bunch of services
9267 // all at the same time.
9268 boolean repeat;
9269 do {
9270 repeat = false;
9271 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9272 ServiceRecord r2 = mRestartingServices.get(i);
9273 if (r2 != r && r.nextRestartTime
9274 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9275 && r.nextRestartTime
9276 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9277 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9278 r.restartDelay = r.nextRestartTime - now;
9279 repeat = true;
9280 break;
9281 }
9282 }
9283 } while (repeat);
9284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 if (!mRestartingServices.contains(r)) {
9286 mRestartingServices.add(r);
9287 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009288
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009289 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009292 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009294 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009296 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 r.shortName, r.restartDelay);
9298
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009299 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 }
9301
9302 final void performServiceRestartLocked(ServiceRecord r) {
9303 if (!mRestartingServices.contains(r)) {
9304 return;
9305 }
9306 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9307 }
9308
9309 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9310 if (r.restartDelay == 0) {
9311 return false;
9312 }
9313 r.resetRestartCounter();
9314 mRestartingServices.remove(r);
9315 mHandler.removeCallbacks(r.restarter);
9316 return true;
9317 }
9318
9319 private final boolean bringUpServiceLocked(ServiceRecord r,
9320 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009321 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009322 //r.dump(" ");
9323
Dianne Hackborn36124872009-10-08 16:22:03 -07009324 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 sendServiceArgsLocked(r, false);
9326 return true;
9327 }
9328
9329 if (!whileRestarting && r.restartDelay > 0) {
9330 // If waiting for a restart, then do nothing.
9331 return true;
9332 }
9333
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009334 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009336 // We are now bringing the service up, so no longer in the
9337 // restarting state.
9338 mRestartingServices.remove(r);
9339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 final String appName = r.processName;
9341 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9342 if (app != null && app.thread != null) {
9343 try {
9344 realStartServiceLocked(r, app);
9345 return true;
9346 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009347 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009348 }
9349
9350 // If a dead object exception was thrown -- fall through to
9351 // restart the application.
9352 }
9353
Dianne Hackborn36124872009-10-08 16:22:03 -07009354 // Not running -- get it started, and enqueue this service record
9355 // to be executed when the app comes up.
9356 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9357 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009358 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009359 + r.appInfo.packageName + "/"
9360 + r.appInfo.uid + " for service "
9361 + r.intent.getIntent() + ": process is bad");
9362 bringDownServiceLocked(r, true);
9363 return false;
9364 }
9365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009367 mPendingServices.add(r);
9368 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009370 return true;
9371 }
9372
9373 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009374 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 //r.dump(" ");
9376
9377 // Does it still need to run?
9378 if (!force && r.startRequested) {
9379 return;
9380 }
9381 if (r.connections.size() > 0) {
9382 if (!force) {
9383 // XXX should probably keep a count of the number of auto-create
9384 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009385 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009387 ArrayList<ConnectionRecord> cr = it.next();
9388 for (int i=0; i<cr.size(); i++) {
9389 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9390 return;
9391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 }
9393 }
9394 }
9395
9396 // Report to all of the connections that the service is no longer
9397 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009398 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009400 ArrayList<ConnectionRecord> c = it.next();
9401 for (int i=0; i<c.size(); i++) {
9402 try {
9403 c.get(i).conn.connected(r.name, null);
9404 } catch (Exception e) {
9405 Slog.w(TAG, "Failure disconnecting service " + r.name +
9406 " to connection " + c.get(i).conn.asBinder() +
9407 " (in " + c.get(i).binding.client.processName + ")", e);
9408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409 }
9410 }
9411 }
9412
9413 // Tell the service that it has been unbound.
9414 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9415 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9416 while (it.hasNext()) {
9417 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009418 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419 + ": hasBound=" + ibr.hasBound);
9420 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9421 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009422 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009423 updateOomAdjLocked(r.app);
9424 ibr.hasBound = false;
9425 r.app.thread.scheduleUnbindService(r,
9426 ibr.intent.getIntent());
9427 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009428 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 + r.shortName, e);
9430 serviceDoneExecutingLocked(r, true);
9431 }
9432 }
9433 }
9434 }
9435
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009436 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009437 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438 System.identityHashCode(r), r.shortName,
9439 (r.app != null) ? r.app.pid : -1);
9440
9441 mServices.remove(r.name);
9442 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 r.totalRestartCount = 0;
9444 unscheduleServiceRestartLocked(r);
9445
9446 // Also make sure it is not on the pending list.
9447 int N = mPendingServices.size();
9448 for (int i=0; i<N; i++) {
9449 if (mPendingServices.get(i) == r) {
9450 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009451 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 i--;
9453 N--;
9454 }
9455 }
9456
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009457 r.cancelNotification();
9458 r.isForeground = false;
9459 r.foregroundId = 0;
9460 r.foregroundNoti = null;
9461
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009462 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009463 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009464 r.pendingStarts.clear();
9465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009466 if (r.app != null) {
9467 synchronized (r.stats.getBatteryStats()) {
9468 r.stats.stopLaunchedLocked();
9469 }
9470 r.app.services.remove(r);
9471 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009472 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009473 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009474 mStoppingServices.add(r);
9475 updateOomAdjLocked(r.app);
9476 r.app.thread.scheduleStopService(r);
9477 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009478 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 + r.shortName, e);
9480 serviceDoneExecutingLocked(r, true);
9481 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009482 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009484 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009485 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009486 }
9487 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009488 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009489 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009491
9492 if (r.bindings.size() > 0) {
9493 r.bindings.clear();
9494 }
9495
9496 if (r.restarter instanceof ServiceRestarter) {
9497 ((ServiceRestarter)r.restarter).setService(null);
9498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 }
9500
9501 ComponentName startServiceLocked(IApplicationThread caller,
9502 Intent service, String resolvedType,
9503 int callingPid, int callingUid) {
9504 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009505 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506 + " type=" + resolvedType + " args=" + service.getExtras());
9507
9508 if (caller != null) {
9509 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9510 if (callerApp == null) {
9511 throw new SecurityException(
9512 "Unable to find app for caller " + caller
9513 + " (pid=" + Binder.getCallingPid()
9514 + ") when starting service " + service);
9515 }
9516 }
9517
9518 ServiceLookupResult res =
9519 retrieveServiceLocked(service, resolvedType,
9520 callingPid, callingUid);
9521 if (res == null) {
9522 return null;
9523 }
9524 if (res.record == null) {
9525 return new ComponentName("!", res.permission != null
9526 ? res.permission : "private to package");
9527 }
9528 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009529 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9530 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009531 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009532 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009533 }
9534 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009535 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009536 r.lastStartId++;
9537 if (r.lastStartId < 1) {
9538 r.lastStartId = 1;
9539 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009540 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9541 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009542 r.lastActivity = SystemClock.uptimeMillis();
9543 synchronized (r.stats.getBatteryStats()) {
9544 r.stats.startRunningLocked();
9545 }
9546 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9547 return new ComponentName("!", "Service process is bad");
9548 }
9549 return r.name;
9550 }
9551 }
9552
9553 public ComponentName startService(IApplicationThread caller, Intent service,
9554 String resolvedType) {
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) {
9561 final int callingPid = Binder.getCallingPid();
9562 final int callingUid = Binder.getCallingUid();
9563 final long origId = Binder.clearCallingIdentity();
9564 ComponentName res = startServiceLocked(caller, service,
9565 resolvedType, callingPid, callingUid);
9566 Binder.restoreCallingIdentity(origId);
9567 return res;
9568 }
9569 }
9570
9571 ComponentName startServiceInPackage(int uid,
9572 Intent service, String resolvedType) {
9573 synchronized(this) {
9574 final long origId = Binder.clearCallingIdentity();
9575 ComponentName res = startServiceLocked(null, service,
9576 resolvedType, -1, uid);
9577 Binder.restoreCallingIdentity(origId);
9578 return res;
9579 }
9580 }
9581
9582 public int stopService(IApplicationThread caller, Intent service,
9583 String resolvedType) {
9584 // Refuse possible leaked file descriptors
9585 if (service != null && service.hasFileDescriptors() == true) {
9586 throw new IllegalArgumentException("File descriptors passed in Intent");
9587 }
9588
9589 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009590 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 + " type=" + resolvedType);
9592
9593 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9594 if (caller != null && callerApp == null) {
9595 throw new SecurityException(
9596 "Unable to find app for caller " + caller
9597 + " (pid=" + Binder.getCallingPid()
9598 + ") when stopping service " + service);
9599 }
9600
9601 // If this service is active, make sure it is stopped.
9602 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9603 if (r != null) {
9604 if (r.record != null) {
9605 synchronized (r.record.stats.getBatteryStats()) {
9606 r.record.stats.stopRunningLocked();
9607 }
9608 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009609 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610 final long origId = Binder.clearCallingIdentity();
9611 bringDownServiceLocked(r.record, false);
9612 Binder.restoreCallingIdentity(origId);
9613 return 1;
9614 }
9615 return -1;
9616 }
9617 }
9618
9619 return 0;
9620 }
9621
9622 public IBinder peekService(Intent service, String resolvedType) {
9623 // Refuse possible leaked file descriptors
9624 if (service != null && service.hasFileDescriptors() == true) {
9625 throw new IllegalArgumentException("File descriptors passed in Intent");
9626 }
9627
9628 IBinder ret = null;
9629
9630 synchronized(this) {
9631 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9632
9633 if (r != null) {
9634 // r.record is null if findServiceLocked() failed the caller permission check
9635 if (r.record == null) {
9636 throw new SecurityException(
lge-aospea278a92011-01-07 13:45:37 +09009637 "Permission Denial: Accessing service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 + " from pid=" + Binder.getCallingPid()
9639 + ", uid=" + Binder.getCallingUid()
9640 + " requires " + r.permission);
9641 }
9642 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9643 if (ib != null) {
9644 ret = ib.binder;
9645 }
9646 }
9647 }
9648
9649 return ret;
9650 }
9651
9652 public boolean stopServiceToken(ComponentName className, IBinder token,
9653 int startId) {
9654 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009655 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656 + " " + token + " startId=" + startId);
9657 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009658 if (r != null) {
9659 if (startId >= 0) {
9660 // Asked to only stop if done with all work. Note that
9661 // to avoid leaks, we will take this as dropping all
9662 // start items up to and including this one.
9663 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9664 if (si != null) {
9665 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009666 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9667 cur.removeUriPermissionsLocked();
9668 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009669 break;
9670 }
9671 }
9672 }
9673
9674 if (r.lastStartId != startId) {
9675 return false;
9676 }
9677
9678 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009679 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009680 + " is last, but have " + r.deliveredStarts.size()
9681 + " remaining args");
9682 }
9683 }
9684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009685 synchronized (r.stats.getBatteryStats()) {
9686 r.stats.stopRunningLocked();
9687 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009688 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 }
9690 final long origId = Binder.clearCallingIdentity();
9691 bringDownServiceLocked(r, false);
9692 Binder.restoreCallingIdentity(origId);
9693 return true;
9694 }
9695 }
9696 return false;
9697 }
9698
9699 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009700 int id, Notification notification, boolean removeNotification) {
9701 final long origId = Binder.clearCallingIdentity();
9702 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 synchronized(this) {
9704 ServiceRecord r = findServiceLocked(className, token);
9705 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009706 if (id != 0) {
9707 if (notification == null) {
9708 throw new IllegalArgumentException("null notification");
9709 }
9710 if (r.foregroundId != id) {
9711 r.cancelNotification();
9712 r.foregroundId = id;
9713 }
9714 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9715 r.foregroundNoti = notification;
9716 r.isForeground = true;
9717 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009718 if (r.app != null) {
9719 updateServiceForegroundLocked(r.app, true);
9720 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009721 } else {
9722 if (r.isForeground) {
9723 r.isForeground = false;
9724 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009725 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009726 updateServiceForegroundLocked(r.app, true);
9727 }
9728 }
9729 if (removeNotification) {
9730 r.cancelNotification();
9731 r.foregroundId = 0;
9732 r.foregroundNoti = null;
9733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009734 }
9735 }
9736 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009737 } finally {
9738 Binder.restoreCallingIdentity(origId);
9739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 }
9741
9742 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9743 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009744 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 if (sr.isForeground) {
9746 anyForeground = true;
9747 break;
9748 }
9749 }
9750 if (anyForeground != proc.foregroundServices) {
9751 proc.foregroundServices = anyForeground;
9752 if (oomAdj) {
9753 updateOomAdjLocked();
9754 }
9755 }
9756 }
9757
9758 public int bindService(IApplicationThread caller, IBinder token,
9759 Intent service, String resolvedType,
9760 IServiceConnection connection, int flags) {
9761 // Refuse possible leaked file descriptors
9762 if (service != null && service.hasFileDescriptors() == true) {
9763 throw new IllegalArgumentException("File descriptors passed in Intent");
9764 }
9765
9766 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009767 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 + " type=" + resolvedType + " conn=" + connection.asBinder()
9769 + " flags=0x" + Integer.toHexString(flags));
9770 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9771 if (callerApp == null) {
9772 throw new SecurityException(
9773 "Unable to find app for caller " + caller
9774 + " (pid=" + Binder.getCallingPid()
9775 + ") when binding service " + service);
9776 }
9777
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009778 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009779 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009780 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009782 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783 return 0;
9784 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009785 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 }
9787
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009788 int clientLabel = 0;
9789 PendingIntent clientIntent = null;
9790
9791 if (callerApp.info.uid == Process.SYSTEM_UID) {
9792 // Hacky kind of thing -- allow system stuff to tell us
9793 // what they are, so we can report this elsewhere for
9794 // others to know why certain services are running.
9795 try {
9796 clientIntent = (PendingIntent)service.getParcelableExtra(
9797 Intent.EXTRA_CLIENT_INTENT);
9798 } catch (RuntimeException e) {
9799 }
9800 if (clientIntent != null) {
9801 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9802 if (clientLabel != 0) {
9803 // There are no useful extras in the intent, trash them.
9804 // System code calling with this stuff just needs to know
9805 // this will happen.
9806 service = service.cloneFilter();
9807 }
9808 }
9809 }
9810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811 ServiceLookupResult res =
9812 retrieveServiceLocked(service, resolvedType,
9813 Binder.getCallingPid(), Binder.getCallingUid());
9814 if (res == null) {
9815 return 0;
9816 }
9817 if (res.record == null) {
9818 return -1;
9819 }
9820 ServiceRecord s = res.record;
9821
9822 final long origId = Binder.clearCallingIdentity();
9823
9824 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009825 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009826 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 }
9828
9829 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9830 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009831 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832
9833 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009834 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9835 if (clist == null) {
9836 clist = new ArrayList<ConnectionRecord>();
9837 s.connections.put(binder, clist);
9838 }
9839 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009840 b.connections.add(c);
9841 if (activity != null) {
9842 if (activity.connections == null) {
9843 activity.connections = new HashSet<ConnectionRecord>();
9844 }
9845 activity.connections.add(c);
9846 }
9847 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009848 clist = mServiceConnections.get(binder);
9849 if (clist == null) {
9850 clist = new ArrayList<ConnectionRecord>();
9851 mServiceConnections.put(binder, clist);
9852 }
9853 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854
9855 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9856 s.lastActivity = SystemClock.uptimeMillis();
9857 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9858 return 0;
9859 }
9860 }
9861
9862 if (s.app != null) {
9863 // This could have made the service more important.
9864 updateOomAdjLocked(s.app);
9865 }
9866
Joe Onorato8a9b2202010-02-26 18:56:32 -08009867 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 + ": received=" + b.intent.received
9869 + " apps=" + b.intent.apps.size()
9870 + " doRebind=" + b.intent.doRebind);
9871
9872 if (s.app != null && b.intent.received) {
9873 // Service is already running, so we can immediately
9874 // publish the connection.
9875 try {
9876 c.conn.connected(s.name, b.intent.binder);
9877 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009878 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879 + " to connection " + c.conn.asBinder()
9880 + " (in " + c.binding.client.processName + ")", e);
9881 }
9882
9883 // If this is the first app connected back to this binding,
9884 // and the service had previously asked to be told when
9885 // rebound, then do so.
9886 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9887 requestServiceBindingLocked(s, b.intent, true);
9888 }
9889 } else if (!b.intent.requested) {
9890 requestServiceBindingLocked(s, b.intent, false);
9891 }
9892
9893 Binder.restoreCallingIdentity(origId);
9894 }
9895
9896 return 1;
9897 }
9898
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009899 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009900 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 IBinder binder = c.conn.asBinder();
9902 AppBindRecord b = c.binding;
9903 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009904 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9905 if (clist != null) {
9906 clist.remove(c);
9907 if (clist.size() == 0) {
9908 s.connections.remove(binder);
9909 }
9910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 b.connections.remove(c);
9912 if (c.activity != null && c.activity != skipAct) {
9913 if (c.activity.connections != null) {
9914 c.activity.connections.remove(c);
9915 }
9916 }
9917 if (b.client != skipApp) {
9918 b.client.connections.remove(c);
9919 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009920 clist = mServiceConnections.get(binder);
9921 if (clist != null) {
9922 clist.remove(c);
9923 if (clist.size() == 0) {
9924 mServiceConnections.remove(binder);
9925 }
9926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009927
9928 if (b.connections.size() == 0) {
9929 b.intent.apps.remove(b.client);
9930 }
9931
Joe Onorato8a9b2202010-02-26 18:56:32 -08009932 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 + ": shouldUnbind=" + b.intent.hasBound);
9934 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9935 && b.intent.hasBound) {
9936 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009937 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938 updateOomAdjLocked(s.app);
9939 b.intent.hasBound = false;
9940 // Assume the client doesn't want to know about a rebind;
9941 // we will deal with that later if it asks for one.
9942 b.intent.doRebind = false;
9943 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9944 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009945 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 serviceDoneExecutingLocked(s, true);
9947 }
9948 }
9949
9950 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9951 bringDownServiceLocked(s, false);
9952 }
9953 }
9954
9955 public boolean unbindService(IServiceConnection connection) {
9956 synchronized (this) {
9957 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009958 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009959 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9960 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009961 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 + connection.asBinder());
9963 return false;
9964 }
9965
9966 final long origId = Binder.clearCallingIdentity();
9967
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009968 while (clist.size() > 0) {
9969 ConnectionRecord r = clist.get(0);
9970 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009972 if (r.binding.service.app != null) {
9973 // This could have made the service less important.
9974 updateOomAdjLocked(r.binding.service.app);
9975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 }
9977
9978 Binder.restoreCallingIdentity(origId);
9979 }
9980
9981 return true;
9982 }
9983
9984 public void publishService(IBinder token, Intent intent, IBinder service) {
9985 // Refuse possible leaked file descriptors
9986 if (intent != null && intent.hasFileDescriptors() == true) {
9987 throw new IllegalArgumentException("File descriptors passed in Intent");
9988 }
9989
9990 synchronized(this) {
9991 if (!(token instanceof ServiceRecord)) {
9992 throw new IllegalArgumentException("Invalid service token");
9993 }
9994 ServiceRecord r = (ServiceRecord)token;
9995
9996 final long origId = Binder.clearCallingIdentity();
9997
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009998 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009999 + " " + intent + ": " + service);
10000 if (r != null) {
10001 Intent.FilterComparison filter
10002 = new Intent.FilterComparison(intent);
10003 IntentBindRecord b = r.bindings.get(filter);
10004 if (b != null && !b.received) {
10005 b.binder = service;
10006 b.requested = true;
10007 b.received = true;
10008 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010009 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 = r.connections.values().iterator();
10011 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010012 ArrayList<ConnectionRecord> clist = it.next();
10013 for (int i=0; i<clist.size(); i++) {
10014 ConnectionRecord c = clist.get(i);
10015 if (!filter.equals(c.binding.intent.intent)) {
10016 if (DEBUG_SERVICE) Slog.v(
10017 TAG, "Not publishing to: " + c);
10018 if (DEBUG_SERVICE) Slog.v(
10019 TAG, "Bound intent: " + c.binding.intent.intent);
10020 if (DEBUG_SERVICE) Slog.v(
10021 TAG, "Published intent: " + intent);
10022 continue;
10023 }
10024 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10025 try {
10026 c.conn.connected(r.name, service);
10027 } catch (Exception e) {
10028 Slog.w(TAG, "Failure sending service " + r.name +
10029 " to connection " + c.conn.asBinder() +
10030 " (in " + c.binding.client.processName + ")", e);
10031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 }
10033 }
10034 }
10035 }
10036
10037 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10038
10039 Binder.restoreCallingIdentity(origId);
10040 }
10041 }
10042 }
10043
10044 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10045 // Refuse possible leaked file descriptors
10046 if (intent != null && intent.hasFileDescriptors() == true) {
10047 throw new IllegalArgumentException("File descriptors passed in Intent");
10048 }
10049
10050 synchronized(this) {
10051 if (!(token instanceof ServiceRecord)) {
10052 throw new IllegalArgumentException("Invalid service token");
10053 }
10054 ServiceRecord r = (ServiceRecord)token;
10055
10056 final long origId = Binder.clearCallingIdentity();
10057
10058 if (r != null) {
10059 Intent.FilterComparison filter
10060 = new Intent.FilterComparison(intent);
10061 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010062 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010063 + " at " + b + ": apps="
10064 + (b != null ? b.apps.size() : 0));
10065 if (b != null) {
10066 if (b.apps.size() > 0) {
10067 // Applications have already bound since the last
10068 // unbind, so just rebind right here.
10069 requestServiceBindingLocked(r, b, true);
10070 } else {
10071 // Note to tell the service the next time there is
10072 // a new client.
10073 b.doRebind = true;
10074 }
10075 }
10076
10077 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10078
10079 Binder.restoreCallingIdentity(origId);
10080 }
10081 }
10082 }
10083
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010084 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010085 synchronized(this) {
10086 if (!(token instanceof ServiceRecord)) {
10087 throw new IllegalArgumentException("Invalid service token");
10088 }
10089 ServiceRecord r = (ServiceRecord)token;
10090 boolean inStopping = mStoppingServices.contains(token);
10091 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010092 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010093 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094 + " with incorrect token: given " + token
10095 + ", expected " + r);
10096 return;
10097 }
10098
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010099 if (type == 1) {
10100 // This is a call from a service start... take care of
10101 // book-keeping.
10102 r.callStart = true;
10103 switch (res) {
10104 case Service.START_STICKY_COMPATIBILITY:
10105 case Service.START_STICKY: {
10106 // We are done with the associated start arguments.
10107 r.findDeliveredStart(startId, true);
10108 // Don't stop if killed.
10109 r.stopIfKilled = false;
10110 break;
10111 }
10112 case Service.START_NOT_STICKY: {
10113 // We are done with the associated start arguments.
10114 r.findDeliveredStart(startId, true);
10115 if (r.lastStartId == startId) {
10116 // There is no more work, and this service
10117 // doesn't want to hang around if killed.
10118 r.stopIfKilled = true;
10119 }
10120 break;
10121 }
10122 case Service.START_REDELIVER_INTENT: {
10123 // We'll keep this item until they explicitly
10124 // call stop for it, but keep track of the fact
10125 // that it was delivered.
10126 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10127 if (si != null) {
10128 si.deliveryCount = 0;
10129 si.doneExecutingCount++;
10130 // Don't stop if killed.
10131 r.stopIfKilled = true;
10132 }
10133 break;
10134 }
10135 default:
10136 throw new IllegalArgumentException(
10137 "Unknown service start result: " + res);
10138 }
10139 if (res == Service.START_STICKY_COMPATIBILITY) {
10140 r.callStart = false;
10141 }
10142 }
10143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010144 final long origId = Binder.clearCallingIdentity();
10145 serviceDoneExecutingLocked(r, inStopping);
10146 Binder.restoreCallingIdentity(origId);
10147 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010148 Slog.w(TAG, "Done executing unknown service from pid "
10149 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 }
10151 }
10152 }
10153
10154 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010155 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10156 + ": nesting=" + r.executeNesting
10157 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010158 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010159 r.executeNesting--;
10160 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010161 if (DEBUG_SERVICE) Slog.v(TAG,
10162 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 r.app.executingServices.remove(r);
10164 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010165 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10166 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10168 }
10169 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010170 if (DEBUG_SERVICE) Slog.v(TAG,
10171 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010173 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 }
10175 updateOomAdjLocked(r.app);
10176 }
10177 }
10178
10179 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010180 String anrMessage = null;
10181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 synchronized(this) {
10183 if (proc.executingServices.size() == 0 || proc.thread == null) {
10184 return;
10185 }
10186 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10187 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10188 ServiceRecord timeout = null;
10189 long nextTime = 0;
10190 while (it.hasNext()) {
10191 ServiceRecord sr = it.next();
10192 if (sr.executingStart < maxTime) {
10193 timeout = sr;
10194 break;
10195 }
10196 if (sr.executingStart > nextTime) {
10197 nextTime = sr.executingStart;
10198 }
10199 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010200 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010201 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010202 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 } else {
10204 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10205 msg.obj = proc;
10206 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10207 }
10208 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010209
10210 if (anrMessage != null) {
10211 appNotResponding(proc, null, null, anrMessage);
10212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 }
10214
10215 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010216 // BACKUP AND RESTORE
10217 // =========================================================
10218
10219 // Cause the target app to be launched if necessary and its backup agent
10220 // instantiated. The backup agent will invoke backupAgentCreated() on the
10221 // activity manager to announce its creation.
10222 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010223 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010224 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10225
10226 synchronized(this) {
10227 // !!! TODO: currently no check here that we're already bound
10228 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10229 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10230 synchronized (stats) {
10231 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10232 }
10233
10234 BackupRecord r = new BackupRecord(ss, app, backupMode);
10235 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10236 // startProcessLocked() returns existing proc's record if it's already running
10237 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010238 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010239 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010240 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010241 return false;
10242 }
10243
10244 r.app = proc;
10245 mBackupTarget = r;
10246 mBackupAppName = app.packageName;
10247
Christopher Tate6fa95972009-06-05 18:43:55 -070010248 // Try not to kill the process during backup
10249 updateOomAdjLocked(proc);
10250
Christopher Tate181fafa2009-05-14 11:12:14 -070010251 // If the process is already attached, schedule the creation of the backup agent now.
10252 // If it is not yet live, this will be done when it attaches to the framework.
10253 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010254 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010255 try {
10256 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10257 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010258 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010259 }
10260 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010261 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010262 }
10263 // Invariants: at this point, the target app process exists and the application
10264 // is either already running or in the process of coming up. mBackupTarget and
10265 // mBackupAppName describe the app, so that when it binds back to the AM we
10266 // know that it's scheduled for a backup-agent operation.
10267 }
10268
10269 return true;
10270 }
10271
10272 // A backup agent has just come up
10273 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010274 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010275 + " = " + agent);
10276
10277 synchronized(this) {
10278 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010279 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010280 return;
10281 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010282 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010283
Dianne Hackborn06740692010-09-22 22:46:21 -070010284 long oldIdent = Binder.clearCallingIdentity();
10285 try {
10286 IBackupManager bm = IBackupManager.Stub.asInterface(
10287 ServiceManager.getService(Context.BACKUP_SERVICE));
10288 bm.agentConnected(agentPackageName, agent);
10289 } catch (RemoteException e) {
10290 // can't happen; the backup manager service is local
10291 } catch (Exception e) {
10292 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10293 e.printStackTrace();
10294 } finally {
10295 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010296 }
10297 }
10298
10299 // done with this agent
10300 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010301 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010302 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010304 return;
10305 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010306
10307 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010308 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010309 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010310 return;
10311 }
10312
Christopher Tate181fafa2009-05-14 11:12:14 -070010313 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010314 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010315 return;
10316 }
10317
Christopher Tate6fa95972009-06-05 18:43:55 -070010318 ProcessRecord proc = mBackupTarget.app;
10319 mBackupTarget = null;
10320 mBackupAppName = null;
10321
10322 // Not backing this app up any more; reset its OOM adjustment
10323 updateOomAdjLocked(proc);
10324
Christopher Tatec7b31e32009-06-10 15:49:30 -070010325 // If the app crashed during backup, 'thread' will be null here
10326 if (proc.thread != null) {
10327 try {
10328 proc.thread.scheduleDestroyBackupAgent(appInfo);
10329 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010330 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010331 e.printStackTrace();
10332 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010333 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010334 }
10335 }
10336 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010337 // BROADCASTS
10338 // =========================================================
10339
Josh Bartel7f208742010-02-25 11:01:44 -060010340 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 List cur) {
10342 final ContentResolver resolver = mContext.getContentResolver();
10343 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10344 if (list == null) {
10345 return cur;
10346 }
10347 int N = list.size();
10348 for (int i=0; i<N; i++) {
10349 Intent intent = list.get(i);
10350 if (filter.match(resolver, intent, true, TAG) >= 0) {
10351 if (cur == null) {
10352 cur = new ArrayList<Intent>();
10353 }
10354 cur.add(intent);
10355 }
10356 }
10357 return cur;
10358 }
10359
10360 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010361 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362 + mBroadcastsScheduled);
10363
10364 if (mBroadcastsScheduled) {
10365 return;
10366 }
10367 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10368 mBroadcastsScheduled = true;
10369 }
10370
10371 public Intent registerReceiver(IApplicationThread caller,
10372 IIntentReceiver receiver, IntentFilter filter, String permission) {
10373 synchronized(this) {
10374 ProcessRecord callerApp = null;
10375 if (caller != null) {
10376 callerApp = getRecordForAppLocked(caller);
10377 if (callerApp == null) {
10378 throw new SecurityException(
10379 "Unable to find app for caller " + caller
10380 + " (pid=" + Binder.getCallingPid()
10381 + ") when registering receiver " + receiver);
10382 }
10383 }
10384
10385 List allSticky = null;
10386
10387 // Look for any matching sticky broadcasts...
10388 Iterator actions = filter.actionsIterator();
10389 if (actions != null) {
10390 while (actions.hasNext()) {
10391 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010392 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010393 }
10394 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010395 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010396 }
10397
10398 // The first sticky in the list is returned directly back to
10399 // the client.
10400 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10401
Joe Onorato8a9b2202010-02-26 18:56:32 -080010402 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 + ": " + sticky);
10404
10405 if (receiver == null) {
10406 return sticky;
10407 }
10408
10409 ReceiverList rl
10410 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10411 if (rl == null) {
10412 rl = new ReceiverList(this, callerApp,
10413 Binder.getCallingPid(),
10414 Binder.getCallingUid(), receiver);
10415 if (rl.app != null) {
10416 rl.app.receivers.add(rl);
10417 } else {
10418 try {
10419 receiver.asBinder().linkToDeath(rl, 0);
10420 } catch (RemoteException e) {
10421 return sticky;
10422 }
10423 rl.linkedToDeath = true;
10424 }
10425 mRegisteredReceivers.put(receiver.asBinder(), rl);
10426 }
10427 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10428 rl.add(bf);
10429 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010430 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010431 }
10432 mReceiverResolver.addFilter(bf);
10433
10434 // Enqueue broadcasts for all existing stickies that match
10435 // this filter.
10436 if (allSticky != null) {
10437 ArrayList receivers = new ArrayList();
10438 receivers.add(bf);
10439
10440 int N = allSticky.size();
10441 for (int i=0; i<N; i++) {
10442 Intent intent = (Intent)allSticky.get(i);
10443 BroadcastRecord r = new BroadcastRecord(intent, null,
10444 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010445 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 if (mParallelBroadcasts.size() == 0) {
10447 scheduleBroadcastsLocked();
10448 }
10449 mParallelBroadcasts.add(r);
10450 }
10451 }
10452
10453 return sticky;
10454 }
10455 }
10456
10457 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010458 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459
10460 boolean doNext = false;
10461
10462 synchronized(this) {
10463 ReceiverList rl
10464 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10465 if (rl != null) {
10466 if (rl.curBroadcast != null) {
10467 BroadcastRecord r = rl.curBroadcast;
10468 doNext = finishReceiverLocked(
10469 receiver.asBinder(), r.resultCode, r.resultData,
10470 r.resultExtras, r.resultAbort, true);
10471 }
10472
10473 if (rl.app != null) {
10474 rl.app.receivers.remove(rl);
10475 }
10476 removeReceiverLocked(rl);
10477 if (rl.linkedToDeath) {
10478 rl.linkedToDeath = false;
10479 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10480 }
10481 }
10482 }
10483
10484 if (!doNext) {
10485 return;
10486 }
10487
10488 final long origId = Binder.clearCallingIdentity();
10489 processNextBroadcast(false);
10490 trimApplications();
10491 Binder.restoreCallingIdentity(origId);
10492 }
10493
10494 void removeReceiverLocked(ReceiverList rl) {
10495 mRegisteredReceivers.remove(rl.receiver.asBinder());
10496 int N = rl.size();
10497 for (int i=0; i<N; i++) {
10498 mReceiverResolver.removeFilter(rl.get(i));
10499 }
10500 }
10501
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010502 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10503 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10504 ProcessRecord r = mLruProcesses.get(i);
10505 if (r.thread != null) {
10506 try {
10507 r.thread.dispatchPackageBroadcast(cmd, packages);
10508 } catch (RemoteException ex) {
10509 }
10510 }
10511 }
10512 }
10513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 private final int broadcastIntentLocked(ProcessRecord callerApp,
10515 String callerPackage, Intent intent, String resolvedType,
10516 IIntentReceiver resultTo, int resultCode, String resultData,
10517 Bundle map, String requiredPermission,
10518 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10519 intent = new Intent(intent);
10520
Joe Onorato8a9b2202010-02-26 18:56:32 -080010521 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10523 + " ordered=" + ordered);
10524 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010525 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010526 }
10527
10528 // Handle special intents: if this broadcast is from the package
10529 // manager about a package being removed, we need to remove all of
10530 // its activities from the history stack.
10531 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10532 intent.getAction());
10533 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10534 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010535 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 || uidRemoved) {
10537 if (checkComponentPermission(
10538 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010539 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010540 == PackageManager.PERMISSION_GRANTED) {
10541 if (uidRemoved) {
10542 final Bundle intentExtras = intent.getExtras();
10543 final int uid = intentExtras != null
10544 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10545 if (uid >= 0) {
10546 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10547 synchronized (bs) {
10548 bs.removeUidStatsLocked(uid);
10549 }
10550 }
10551 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010552 // If resources are unvailble just force stop all
10553 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010554 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010555 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10556 if (list != null && (list.length > 0)) {
10557 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010558 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010559 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010560 sendPackageBroadcastLocked(
10561 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010562 }
10563 } else {
10564 Uri data = intent.getData();
10565 String ssp;
10566 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10567 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10568 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010569 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010570 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010571 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10572 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10573 new String[] {ssp});
10574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 }
10576 }
10577 }
10578 } else {
10579 String msg = "Permission Denial: " + intent.getAction()
10580 + " broadcast from " + callerPackage + " (pid=" + callingPid
10581 + ", uid=" + callingUid + ")"
10582 + " requires "
10583 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010584 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 throw new SecurityException(msg);
10586 }
10587 }
10588
10589 /*
10590 * If this is the time zone changed action, queue up a message that will reset the timezone
10591 * of all currently running processes. This message will get queued up before the broadcast
10592 * happens.
10593 */
10594 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10595 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10596 }
10597
Robert Greenwalt03595d02010-11-02 14:08:23 -070010598 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10599 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10600 }
10601
Robert Greenwalt434203a2010-10-11 16:00:27 -070010602 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10603 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10604 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10605 }
10606
Dianne Hackborn854060af2009-07-09 18:14:31 -070010607 /*
10608 * Prevent non-system code (defined here to be non-persistent
10609 * processes) from sending protected broadcasts.
10610 */
10611 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10612 || callingUid == Process.SHELL_UID || callingUid == 0) {
10613 // Always okay.
10614 } else if (callerApp == null || !callerApp.persistent) {
10615 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010616 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010617 intent.getAction())) {
10618 String msg = "Permission Denial: not allowed to send broadcast "
10619 + intent.getAction() + " from pid="
10620 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010621 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010622 throw new SecurityException(msg);
10623 }
10624 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010625 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010626 return BROADCAST_SUCCESS;
10627 }
10628 }
10629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010630 // Add to the sticky list if requested.
10631 if (sticky) {
10632 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10633 callingPid, callingUid)
10634 != PackageManager.PERMISSION_GRANTED) {
10635 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10636 + callingPid + ", uid=" + callingUid
10637 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010638 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 throw new SecurityException(msg);
10640 }
10641 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010642 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010643 + " and enforce permission " + requiredPermission);
10644 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10645 }
10646 if (intent.getComponent() != null) {
10647 throw new SecurityException(
10648 "Sticky broadcasts can't target a specific component");
10649 }
10650 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10651 if (list == null) {
10652 list = new ArrayList<Intent>();
10653 mStickyBroadcasts.put(intent.getAction(), list);
10654 }
10655 int N = list.size();
10656 int i;
10657 for (i=0; i<N; i++) {
10658 if (intent.filterEquals(list.get(i))) {
10659 // This sticky already exists, replace it.
10660 list.set(i, new Intent(intent));
10661 break;
10662 }
10663 }
10664 if (i >= N) {
10665 list.add(new Intent(intent));
10666 }
10667 }
10668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010669 // Figure out who all will receive this broadcast.
10670 List receivers = null;
10671 List<BroadcastFilter> registeredReceivers = null;
10672 try {
10673 if (intent.getComponent() != null) {
10674 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010675 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010676 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010677 if (ai != null) {
10678 receivers = new ArrayList();
10679 ResolveInfo ri = new ResolveInfo();
10680 ri.activityInfo = ai;
10681 receivers.add(ri);
10682 }
10683 } else {
10684 // Need to resolve the intent to interested receivers...
10685 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10686 == 0) {
10687 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010688 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010689 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010690 }
Mihai Preda074edef2009-05-18 17:13:31 +020010691 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010692 }
10693 } catch (RemoteException ex) {
10694 // pm is in same process, this will never happen.
10695 }
10696
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010697 final boolean replacePending =
10698 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10699
Joe Onorato8a9b2202010-02-26 18:56:32 -080010700 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010701 + " replacePending=" + replacePending);
10702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10704 if (!ordered && NR > 0) {
10705 // If we are not serializing this broadcast, then send the
10706 // registered receivers separately so they don't wait for the
10707 // components to be launched.
10708 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10709 callerPackage, callingPid, callingUid, requiredPermission,
10710 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010711 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010712 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 TAG, "Enqueueing parallel broadcast " + r
10714 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010715 boolean replaced = false;
10716 if (replacePending) {
10717 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10718 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010719 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010720 "***** DROPPING PARALLEL: " + intent);
10721 mParallelBroadcasts.set(i, r);
10722 replaced = true;
10723 break;
10724 }
10725 }
10726 }
10727 if (!replaced) {
10728 mParallelBroadcasts.add(r);
10729 scheduleBroadcastsLocked();
10730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010731 registeredReceivers = null;
10732 NR = 0;
10733 }
10734
10735 // Merge into one list.
10736 int ir = 0;
10737 if (receivers != null) {
10738 // A special case for PACKAGE_ADDED: do not allow the package
10739 // being added to see this broadcast. This prevents them from
10740 // using this as a back door to get run as soon as they are
10741 // installed. Maybe in the future we want to have a special install
10742 // broadcast or such for apps, but we'd like to deliberately make
10743 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010744 String skipPackages[] = null;
10745 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10746 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10747 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10748 Uri data = intent.getData();
10749 if (data != null) {
10750 String pkgName = data.getSchemeSpecificPart();
10751 if (pkgName != null) {
10752 skipPackages = new String[] { pkgName };
10753 }
10754 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010755 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010756 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010757 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010758 if (skipPackages != null && (skipPackages.length > 0)) {
10759 for (String skipPackage : skipPackages) {
10760 if (skipPackage != null) {
10761 int NT = receivers.size();
10762 for (int it=0; it<NT; it++) {
10763 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10764 if (curt.activityInfo.packageName.equals(skipPackage)) {
10765 receivers.remove(it);
10766 it--;
10767 NT--;
10768 }
10769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 }
10771 }
10772 }
10773
10774 int NT = receivers != null ? receivers.size() : 0;
10775 int it = 0;
10776 ResolveInfo curt = null;
10777 BroadcastFilter curr = null;
10778 while (it < NT && ir < NR) {
10779 if (curt == null) {
10780 curt = (ResolveInfo)receivers.get(it);
10781 }
10782 if (curr == null) {
10783 curr = registeredReceivers.get(ir);
10784 }
10785 if (curr.getPriority() >= curt.priority) {
10786 // Insert this broadcast record into the final list.
10787 receivers.add(it, curr);
10788 ir++;
10789 curr = null;
10790 it++;
10791 NT++;
10792 } else {
10793 // Skip to the next ResolveInfo in the final list.
10794 it++;
10795 curt = null;
10796 }
10797 }
10798 }
10799 while (ir < NR) {
10800 if (receivers == null) {
10801 receivers = new ArrayList();
10802 }
10803 receivers.add(registeredReceivers.get(ir));
10804 ir++;
10805 }
10806
10807 if ((receivers != null && receivers.size() > 0)
10808 || resultTo != null) {
10809 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10810 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010811 receivers, resultTo, resultCode, resultData, map, ordered,
10812 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010813 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010814 TAG, "Enqueueing ordered broadcast " + r
10815 + ": prev had " + mOrderedBroadcasts.size());
10816 if (DEBUG_BROADCAST) {
10817 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010818 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010820 boolean replaced = false;
10821 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010822 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010823 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010824 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010825 "***** DROPPING ORDERED: " + intent);
10826 mOrderedBroadcasts.set(i, r);
10827 replaced = true;
10828 break;
10829 }
10830 }
10831 }
10832 if (!replaced) {
10833 mOrderedBroadcasts.add(r);
10834 scheduleBroadcastsLocked();
10835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 }
10837
10838 return BROADCAST_SUCCESS;
10839 }
10840
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010841 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010842 // Refuse possible leaked file descriptors
10843 if (intent != null && intent.hasFileDescriptors() == true) {
10844 throw new IllegalArgumentException("File descriptors passed in Intent");
10845 }
10846
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010847 int flags = intent.getFlags();
10848
10849 if (!mProcessesReady) {
10850 // if the caller really truly claims to know what they're doing, go
10851 // ahead and allow the broadcast without launching any receivers
10852 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10853 intent = new Intent(intent);
10854 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10855 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10856 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10857 + " before boot completion");
10858 throw new IllegalStateException("Cannot broadcast before boot completed");
10859 }
10860 }
10861
10862 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10863 throw new IllegalArgumentException(
10864 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10865 }
10866
10867 return intent;
10868 }
10869
10870 public final int broadcastIntent(IApplicationThread caller,
10871 Intent intent, String resolvedType, IIntentReceiver resultTo,
10872 int resultCode, String resultData, Bundle map,
10873 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010875 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10878 final int callingPid = Binder.getCallingPid();
10879 final int callingUid = Binder.getCallingUid();
10880 final long origId = Binder.clearCallingIdentity();
10881 int res = broadcastIntentLocked(callerApp,
10882 callerApp != null ? callerApp.info.packageName : null,
10883 intent, resolvedType, resultTo,
10884 resultCode, resultData, map, requiredPermission, serialized,
10885 sticky, callingPid, callingUid);
10886 Binder.restoreCallingIdentity(origId);
10887 return res;
10888 }
10889 }
10890
10891 int broadcastIntentInPackage(String packageName, int uid,
10892 Intent intent, String resolvedType, IIntentReceiver resultTo,
10893 int resultCode, String resultData, Bundle map,
10894 String requiredPermission, boolean serialized, boolean sticky) {
10895 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010896 intent = verifyBroadcastLocked(intent);
10897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 final long origId = Binder.clearCallingIdentity();
10899 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10900 resultTo, resultCode, resultData, map, requiredPermission,
10901 serialized, sticky, -1, uid);
10902 Binder.restoreCallingIdentity(origId);
10903 return res;
10904 }
10905 }
10906
10907 public final void unbroadcastIntent(IApplicationThread caller,
10908 Intent intent) {
10909 // Refuse possible leaked file descriptors
10910 if (intent != null && intent.hasFileDescriptors() == true) {
10911 throw new IllegalArgumentException("File descriptors passed in Intent");
10912 }
10913
10914 synchronized(this) {
10915 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10916 != PackageManager.PERMISSION_GRANTED) {
10917 String msg = "Permission Denial: unbroadcastIntent() from pid="
10918 + Binder.getCallingPid()
10919 + ", uid=" + Binder.getCallingUid()
10920 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010921 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 throw new SecurityException(msg);
10923 }
10924 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10925 if (list != null) {
10926 int N = list.size();
10927 int i;
10928 for (i=0; i<N; i++) {
10929 if (intent.filterEquals(list.get(i))) {
10930 list.remove(i);
10931 break;
10932 }
10933 }
10934 }
10935 }
10936 }
10937
10938 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10939 String resultData, Bundle resultExtras, boolean resultAbort,
10940 boolean explicit) {
10941 if (mOrderedBroadcasts.size() == 0) {
10942 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010943 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 }
10945 return false;
10946 }
10947 BroadcastRecord r = mOrderedBroadcasts.get(0);
10948 if (r.receiver == null) {
10949 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010950 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 }
10952 return false;
10953 }
10954 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010955 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 return false;
10957 }
10958 int state = r.state;
10959 r.state = r.IDLE;
10960 if (state == r.IDLE) {
10961 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010962 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 }
10964 }
10965 r.receiver = null;
10966 r.intent.setComponent(null);
10967 if (r.curApp != null) {
10968 r.curApp.curReceiver = null;
10969 }
10970 if (r.curFilter != null) {
10971 r.curFilter.receiverList.curBroadcast = null;
10972 }
10973 r.curFilter = null;
10974 r.curApp = null;
10975 r.curComponent = null;
10976 r.curReceiver = null;
10977 mPendingBroadcast = null;
10978
10979 r.resultCode = resultCode;
10980 r.resultData = resultData;
10981 r.resultExtras = resultExtras;
10982 r.resultAbort = resultAbort;
10983
10984 // We will process the next receiver right now if this is finishing
10985 // an app receiver (which is always asynchronous) or after we have
10986 // come back from calling a receiver.
10987 return state == BroadcastRecord.APP_RECEIVE
10988 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10989 }
10990
10991 public void finishReceiver(IBinder who, int resultCode, String resultData,
10992 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010993 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994
10995 // Refuse possible leaked file descriptors
10996 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10997 throw new IllegalArgumentException("File descriptors passed in Bundle");
10998 }
10999
11000 boolean doNext;
11001
11002 final long origId = Binder.clearCallingIdentity();
11003
11004 synchronized(this) {
11005 doNext = finishReceiverLocked(
11006 who, resultCode, resultData, resultExtras, resultAbort, true);
11007 }
11008
11009 if (doNext) {
11010 processNextBroadcast(false);
11011 }
11012 trimApplications();
11013
11014 Binder.restoreCallingIdentity(origId);
11015 }
11016
Jeff Brown4d94a762010-09-23 11:33:28 -070011017 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 if (r.nextReceiver > 0) {
11019 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11020 if (curReceiver instanceof BroadcastFilter) {
11021 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011022 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 System.identityHashCode(r),
11024 r.intent.getAction(),
11025 r.nextReceiver - 1,
11026 System.identityHashCode(bf));
11027 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011028 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 System.identityHashCode(r),
11030 r.intent.getAction(),
11031 r.nextReceiver - 1,
11032 ((ResolveInfo)curReceiver).toString());
11033 }
11034 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011035 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011037 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011038 System.identityHashCode(r),
11039 r.intent.getAction(),
11040 r.nextReceiver,
11041 "NONE");
11042 }
11043 }
11044
Jeff Brown4d94a762010-09-23 11:33:28 -070011045 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11046 if (! mPendingBroadcastTimeoutMessage) {
11047 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11048 mHandler.sendMessageAtTime(msg, timeoutTime);
11049 mPendingBroadcastTimeoutMessage = true;
11050 }
11051 }
11052
11053 private final void cancelBroadcastTimeoutLocked() {
11054 if (mPendingBroadcastTimeoutMessage) {
11055 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11056 mPendingBroadcastTimeoutMessage = false;
11057 }
11058 }
11059
11060 private final void broadcastTimeoutLocked(boolean fromMsg) {
11061 if (fromMsg) {
11062 mPendingBroadcastTimeoutMessage = false;
11063 }
11064
11065 if (mOrderedBroadcasts.size() == 0) {
11066 return;
11067 }
11068
11069 long now = SystemClock.uptimeMillis();
11070 BroadcastRecord r = mOrderedBroadcasts.get(0);
11071 if (fromMsg) {
11072 if (mDidDexOpt) {
11073 // Delay timeouts until dexopt finishes.
11074 mDidDexOpt = false;
11075 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11076 setBroadcastTimeoutLocked(timeoutTime);
11077 return;
11078 }
11079 if (! mProcessesReady) {
11080 // Only process broadcast timeouts if the system is ready. That way
11081 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11082 // to do heavy lifting for system up.
11083 return;
11084 }
11085
11086 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11087 if (timeoutTime > now) {
11088 // We can observe premature timeouts because we do not cancel and reset the
11089 // broadcast timeout message after each receiver finishes. Instead, we set up
11090 // an initial timeout then kick it down the road a little further as needed
11091 // when it expires.
11092 if (DEBUG_BROADCAST) Slog.v(TAG,
11093 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11094 + timeoutTime);
11095 setBroadcastTimeoutLocked(timeoutTime);
11096 return;
11097 }
11098 }
11099
11100 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11101 + ", started " + (now - r.receiverTime) + "ms ago");
11102 r.receiverTime = now;
11103 r.anrCount++;
11104
11105 // Current receiver has passed its expiration date.
11106 if (r.nextReceiver <= 0) {
11107 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11108 return;
11109 }
11110
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011111 ProcessRecord app = null;
11112 String anrMessage = null;
11113
Jeff Brown4d94a762010-09-23 11:33:28 -070011114 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11115 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11116 logBroadcastReceiverDiscardLocked(r);
11117 if (curReceiver instanceof BroadcastFilter) {
11118 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11119 if (bf.receiverList.pid != 0
11120 && bf.receiverList.pid != MY_PID) {
11121 synchronized (this.mPidsSelfLocked) {
11122 app = this.mPidsSelfLocked.get(
11123 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011126 } else {
11127 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011129
Jeff Brown4d94a762010-09-23 11:33:28 -070011130 if (app != null) {
11131 anrMessage = "Broadcast of " + r.intent.toString();
11132 }
11133
11134 if (mPendingBroadcast == r) {
11135 mPendingBroadcast = null;
11136 }
11137
11138 // Move on to the next receiver.
11139 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11140 r.resultExtras, r.resultAbort, true);
11141 scheduleBroadcastsLocked();
11142
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011143 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011144 // Post the ANR to the handler since we do not want to process ANRs while
11145 // potentially holding our lock.
11146 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 }
11149
11150 private final void processCurBroadcastLocked(BroadcastRecord r,
11151 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011152 if (DEBUG_BROADCAST) Slog.v(TAG,
11153 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 if (app.thread == null) {
11155 throw new RemoteException();
11156 }
11157 r.receiver = app.thread.asBinder();
11158 r.curApp = app;
11159 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011160 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161
11162 // Tell the application to launch this receiver.
11163 r.intent.setComponent(r.curComponent);
11164
11165 boolean started = false;
11166 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011167 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 "Delivering to component " + r.curComponent
11169 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011170 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11172 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011173 if (DEBUG_BROADCAST) Slog.v(TAG,
11174 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 started = true;
11176 } finally {
11177 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011178 if (DEBUG_BROADCAST) Slog.v(TAG,
11179 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 r.receiver = null;
11181 r.curApp = null;
11182 app.curReceiver = null;
11183 }
11184 }
11185
11186 }
11187
Jeff Brown4d94a762010-09-23 11:33:28 -070011188 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011189 Intent intent, int resultCode, String data, Bundle extras,
11190 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011191 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 if (app != null && app.thread != null) {
11193 // If we have an app thread, do the call through that so it is
11194 // correctly ordered with other one-way calls.
11195 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011196 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011198 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 }
11200 }
11201
Jeff Brown4d94a762010-09-23 11:33:28 -070011202 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011203 BroadcastFilter filter, boolean ordered) {
11204 boolean skip = false;
11205 if (filter.requiredPermission != null) {
11206 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011207 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011209 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 + r.intent.toString()
11211 + " from " + r.callerPackage + " (pid="
11212 + r.callingPid + ", uid=" + r.callingUid + ")"
11213 + " requires " + filter.requiredPermission
11214 + " due to registered receiver " + filter);
11215 skip = true;
11216 }
11217 }
11218 if (r.requiredPermission != null) {
11219 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011220 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011222 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 + r.intent.toString()
11224 + " to " + filter.receiverList.app
11225 + " (pid=" + filter.receiverList.pid
11226 + ", uid=" + filter.receiverList.uid + ")"
11227 + " requires " + r.requiredPermission
11228 + " due to sender " + r.callerPackage
11229 + " (uid " + r.callingUid + ")");
11230 skip = true;
11231 }
11232 }
11233
11234 if (!skip) {
11235 // If this is not being sent as an ordered broadcast, then we
11236 // don't want to touch the fields that keep track of the current
11237 // state of ordered broadcasts.
11238 if (ordered) {
11239 r.receiver = filter.receiverList.receiver.asBinder();
11240 r.curFilter = filter;
11241 filter.receiverList.curBroadcast = r;
11242 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011243 if (filter.receiverList.app != null) {
11244 // Bump hosting application to no longer be in background
11245 // scheduling class. Note that we can't do that if there
11246 // isn't an app... but we can only be in that case for
11247 // things that directly call the IActivityManager API, which
11248 // are already core system stuff so don't matter for this.
11249 r.curApp = filter.receiverList.app;
11250 filter.receiverList.app.curReceiver = r;
11251 updateOomAdjLocked();
11252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253 }
11254 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011255 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011257 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011258 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011260 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011262 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 if (ordered) {
11264 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11265 }
11266 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011267 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 if (ordered) {
11269 r.receiver = null;
11270 r.curFilter = null;
11271 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011272 if (filter.receiverList.app != null) {
11273 filter.receiverList.app.curReceiver = null;
11274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011275 }
11276 }
11277 }
11278 }
11279
Dianne Hackborn12527f92009-11-11 17:39:50 -080011280 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11281 if (r.callingUid < 0) {
11282 // This was from a registerReceiver() call; ignore it.
11283 return;
11284 }
11285 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11286 MAX_BROADCAST_HISTORY-1);
11287 r.finishTime = SystemClock.uptimeMillis();
11288 mBroadcastHistory[0] = r;
11289 }
11290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 private final void processNextBroadcast(boolean fromMsg) {
11292 synchronized(this) {
11293 BroadcastRecord r;
11294
Joe Onorato8a9b2202010-02-26 18:56:32 -080011295 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011297 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298
11299 updateCpuStats();
11300
11301 if (fromMsg) {
11302 mBroadcastsScheduled = false;
11303 }
11304
11305 // First, deliver any non-serialized broadcasts right away.
11306 while (mParallelBroadcasts.size() > 0) {
11307 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011308 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011310 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011311 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 for (int i=0; i<N; i++) {
11313 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011314 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011315 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011317 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011319 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011320 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011321 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 }
11323
11324 // Now take care of the next serialized one...
11325
11326 // If we are waiting for a process to come up to handle the next
11327 // broadcast, then do nothing at this point. Just in case, we
11328 // check that the process we're waiting for still exists.
11329 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011330 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011331 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011332 + mPendingBroadcast.curApp);
11333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334
11335 boolean isDead;
11336 synchronized (mPidsSelfLocked) {
11337 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11338 }
11339 if (!isDead) {
11340 // It's still alive, so keep waiting
11341 return;
11342 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011343 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011345 mPendingBroadcast.state = BroadcastRecord.IDLE;
11346 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 mPendingBroadcast = null;
11348 }
11349 }
11350
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011351 boolean looped = false;
11352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 do {
11354 if (mOrderedBroadcasts.size() == 0) {
11355 // No more broadcasts pending, so all done!
11356 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011357 if (looped) {
11358 // If we had finished the last ordered broadcast, then
11359 // make sure all processes have correct oom and sched
11360 // adjustments.
11361 updateOomAdjLocked();
11362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 return;
11364 }
11365 r = mOrderedBroadcasts.get(0);
11366 boolean forceReceive = false;
11367
11368 // Ensure that even if something goes awry with the timeout
11369 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011370 // and continue to make progress.
11371 //
11372 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011373 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011374 // one time heavy lifting after system upgrades and can take
11375 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011377 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011378 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 if ((numReceivers > 0) &&
11380 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011381 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 + " now=" + now
11383 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011384 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 + " intent=" + r.intent
11386 + " numReceivers=" + numReceivers
11387 + " nextReceiver=" + r.nextReceiver
11388 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011389 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 forceReceive = true;
11391 r.state = BroadcastRecord.IDLE;
11392 }
11393 }
11394
11395 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011396 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 "processNextBroadcast() called when not idle (state="
11398 + r.state + ")");
11399 return;
11400 }
11401
11402 if (r.receivers == null || r.nextReceiver >= numReceivers
11403 || r.resultAbort || forceReceive) {
11404 // No more receivers for this broadcast! Send the final
11405 // result if requested...
11406 if (r.resultTo != null) {
11407 try {
11408 if (DEBUG_BROADCAST) {
11409 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011410 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411 + " seq=" + seq + " app=" + r.callerApp);
11412 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011413 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011415 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011416 // Set this to null so that the reference
11417 // (local and remote) isnt kept in the mBroadcastHistory.
11418 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011420 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 }
11422 }
11423
Joe Onorato8a9b2202010-02-26 18:56:32 -080011424 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011425 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426
Joe Onorato8a9b2202010-02-26 18:56:32 -080011427 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011428 + r);
11429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011431 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 mOrderedBroadcasts.remove(0);
11433 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011434 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011435 continue;
11436 }
11437 } while (r == null);
11438
11439 // Get the next receiver...
11440 int recIdx = r.nextReceiver++;
11441
11442 // Keep track of when this receiver started, and make sure there
11443 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011444 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011446 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011447
Joe Onorato8a9b2202010-02-26 18:56:32 -080011448 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011449 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011450 }
11451 if (! mPendingBroadcastTimeoutMessage) {
11452 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011453 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011454 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11455 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 }
11457
11458 Object nextReceiver = r.receivers.get(recIdx);
11459 if (nextReceiver instanceof BroadcastFilter) {
11460 // Simple case: this is a registered receiver who gets
11461 // a direct call.
11462 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011463 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011464 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011465 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011466 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 if (r.receiver == null || !r.ordered) {
11468 // The receiver has already finished, so schedule to
11469 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011470 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11471 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 r.state = BroadcastRecord.IDLE;
11473 scheduleBroadcastsLocked();
11474 }
11475 return;
11476 }
11477
11478 // Hard case: need to instantiate the receiver, possibly
11479 // starting its application process to host it.
11480
11481 ResolveInfo info =
11482 (ResolveInfo)nextReceiver;
11483
11484 boolean skip = false;
11485 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011486 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11487 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011489 if (!info.activityInfo.exported) {
11490 Slog.w(TAG, "Permission Denial: broadcasting "
11491 + r.intent.toString()
11492 + " from " + r.callerPackage + " (pid=" + r.callingPid
11493 + ", uid=" + r.callingUid + ")"
11494 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11495 + " due to receiver " + info.activityInfo.packageName
11496 + "/" + info.activityInfo.name);
11497 } else {
11498 Slog.w(TAG, "Permission Denial: broadcasting "
11499 + r.intent.toString()
11500 + " from " + r.callerPackage + " (pid=" + r.callingPid
11501 + ", uid=" + r.callingUid + ")"
11502 + " requires " + info.activityInfo.permission
11503 + " due to receiver " + info.activityInfo.packageName
11504 + "/" + info.activityInfo.name);
11505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 skip = true;
11507 }
11508 if (r.callingUid != Process.SYSTEM_UID &&
11509 r.requiredPermission != null) {
11510 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011511 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 checkPermission(r.requiredPermission,
11513 info.activityInfo.applicationInfo.packageName);
11514 } catch (RemoteException e) {
11515 perm = PackageManager.PERMISSION_DENIED;
11516 }
11517 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011518 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 + r.intent + " to "
11520 + info.activityInfo.applicationInfo.packageName
11521 + " requires " + r.requiredPermission
11522 + " due to sender " + r.callerPackage
11523 + " (uid " + r.callingUid + ")");
11524 skip = true;
11525 }
11526 }
11527 if (r.curApp != null && r.curApp.crashing) {
11528 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011529 if (DEBUG_BROADCAST) Slog.v(TAG,
11530 "Skipping deliver ordered " + r + " to " + r.curApp
11531 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 skip = true;
11533 }
11534
11535 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011536 if (DEBUG_BROADCAST) Slog.v(TAG,
11537 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 r.receiver = null;
11539 r.curFilter = null;
11540 r.state = BroadcastRecord.IDLE;
11541 scheduleBroadcastsLocked();
11542 return;
11543 }
11544
11545 r.state = BroadcastRecord.APP_RECEIVE;
11546 String targetProcess = info.activityInfo.processName;
11547 r.curComponent = new ComponentName(
11548 info.activityInfo.applicationInfo.packageName,
11549 info.activityInfo.name);
11550 r.curReceiver = info.activityInfo;
11551
11552 // Is this receiver's application already running?
11553 ProcessRecord app = getProcessRecordLocked(targetProcess,
11554 info.activityInfo.applicationInfo.uid);
11555 if (app != null && app.thread != null) {
11556 try {
11557 processCurBroadcastLocked(r, app);
11558 return;
11559 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011560 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011561 + r.curComponent, e);
11562 }
11563
11564 // If a dead object exception was thrown -- fall through to
11565 // restart the application.
11566 }
11567
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011568 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011569 if (DEBUG_BROADCAST) Slog.v(TAG,
11570 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 if ((r.curApp=startProcessLocked(targetProcess,
11572 info.activityInfo.applicationInfo, true,
11573 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011574 "broadcast", r.curComponent,
11575 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11576 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 // Ah, this recipient is unavailable. Finish it if necessary,
11578 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011579 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 + info.activityInfo.applicationInfo.packageName + "/"
11581 + info.activityInfo.applicationInfo.uid + " for broadcast "
11582 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011583 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11585 r.resultExtras, r.resultAbort, true);
11586 scheduleBroadcastsLocked();
11587 r.state = BroadcastRecord.IDLE;
11588 return;
11589 }
11590
11591 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011592 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011593 }
11594 }
11595
11596 // =========================================================
11597 // INSTRUMENTATION
11598 // =========================================================
11599
11600 public boolean startInstrumentation(ComponentName className,
11601 String profileFile, int flags, Bundle arguments,
11602 IInstrumentationWatcher watcher) {
11603 // Refuse possible leaked file descriptors
11604 if (arguments != null && arguments.hasFileDescriptors()) {
11605 throw new IllegalArgumentException("File descriptors passed in Bundle");
11606 }
11607
11608 synchronized(this) {
11609 InstrumentationInfo ii = null;
11610 ApplicationInfo ai = null;
11611 try {
11612 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011613 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011615 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 } catch (PackageManager.NameNotFoundException e) {
11617 }
11618 if (ii == null) {
11619 reportStartInstrumentationFailure(watcher, className,
11620 "Unable to find instrumentation info for: " + className);
11621 return false;
11622 }
11623 if (ai == null) {
11624 reportStartInstrumentationFailure(watcher, className,
11625 "Unable to find instrumentation target package: " + ii.targetPackage);
11626 return false;
11627 }
11628
11629 int match = mContext.getPackageManager().checkSignatures(
11630 ii.targetPackage, ii.packageName);
11631 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11632 String msg = "Permission Denial: starting instrumentation "
11633 + className + " from pid="
11634 + Binder.getCallingPid()
11635 + ", uid=" + Binder.getCallingPid()
11636 + " not allowed because package " + ii.packageName
11637 + " does not have a signature matching the target "
11638 + ii.targetPackage;
11639 reportStartInstrumentationFailure(watcher, className, msg);
11640 throw new SecurityException(msg);
11641 }
11642
11643 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011644 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 ProcessRecord app = addAppLocked(ai);
11646 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011647 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 app.instrumentationProfileFile = profileFile;
11649 app.instrumentationArguments = arguments;
11650 app.instrumentationWatcher = watcher;
11651 app.instrumentationResultClass = className;
11652 Binder.restoreCallingIdentity(origId);
11653 }
11654
11655 return true;
11656 }
11657
11658 /**
11659 * Report errors that occur while attempting to start Instrumentation. Always writes the
11660 * error to the logs, but if somebody is watching, send the report there too. This enables
11661 * the "am" command to report errors with more information.
11662 *
11663 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11664 * @param cn The component name of the instrumentation.
11665 * @param report The error report.
11666 */
11667 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11668 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011669 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 try {
11671 if (watcher != null) {
11672 Bundle results = new Bundle();
11673 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11674 results.putString("Error", report);
11675 watcher.instrumentationStatus(cn, -1, results);
11676 }
11677 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011678 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 }
11680 }
11681
11682 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11683 if (app.instrumentationWatcher != null) {
11684 try {
11685 // NOTE: IInstrumentationWatcher *must* be oneway here
11686 app.instrumentationWatcher.instrumentationFinished(
11687 app.instrumentationClass,
11688 resultCode,
11689 results);
11690 } catch (RemoteException e) {
11691 }
11692 }
11693 app.instrumentationWatcher = null;
11694 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011695 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 app.instrumentationProfileFile = null;
11697 app.instrumentationArguments = null;
11698
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011699 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 }
11701
11702 public void finishInstrumentation(IApplicationThread target,
11703 int resultCode, Bundle results) {
11704 // Refuse possible leaked file descriptors
11705 if (results != null && results.hasFileDescriptors()) {
11706 throw new IllegalArgumentException("File descriptors passed in Intent");
11707 }
11708
11709 synchronized(this) {
11710 ProcessRecord app = getRecordForAppLocked(target);
11711 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011712 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011713 return;
11714 }
11715 final long origId = Binder.clearCallingIdentity();
11716 finishInstrumentationLocked(app, resultCode, results);
11717 Binder.restoreCallingIdentity(origId);
11718 }
11719 }
11720
11721 // =========================================================
11722 // CONFIGURATION
11723 // =========================================================
11724
11725 public ConfigurationInfo getDeviceConfigurationInfo() {
11726 ConfigurationInfo config = new ConfigurationInfo();
11727 synchronized (this) {
11728 config.reqTouchScreen = mConfiguration.touchscreen;
11729 config.reqKeyboardType = mConfiguration.keyboard;
11730 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011731 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11732 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11734 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011735 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11736 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11738 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011739 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011740 }
11741 return config;
11742 }
11743
11744 public Configuration getConfiguration() {
11745 Configuration ci;
11746 synchronized(this) {
11747 ci = new Configuration(mConfiguration);
11748 }
11749 return ci;
11750 }
11751
11752 public void updateConfiguration(Configuration values) {
11753 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11754 "updateConfiguration()");
11755
11756 synchronized(this) {
11757 if (values == null && mWindowManager != null) {
11758 // sentinel: fetch the current configuration from the window manager
11759 values = mWindowManager.computeNewConfiguration();
11760 }
11761
11762 final long origId = Binder.clearCallingIdentity();
11763 updateConfigurationLocked(values, null);
11764 Binder.restoreCallingIdentity(origId);
11765 }
11766 }
11767
11768 /**
11769 * Do either or both things: (1) change the current configuration, and (2)
11770 * make sure the given activity is running with the (now) current
11771 * configuration. Returns true if the activity has been left running, or
11772 * false if <var>starting</var> is being destroyed to match the new
11773 * configuration.
11774 */
11775 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011776 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011777 int changes = 0;
11778
11779 boolean kept = true;
11780
11781 if (values != null) {
11782 Configuration newConfig = new Configuration(mConfiguration);
11783 changes = newConfig.updateFrom(values);
11784 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011785 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011786 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011787 }
11788
Doug Zongker2bec3d42009-12-04 12:52:44 -080011789 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790
11791 if (values.locale != null) {
11792 saveLocaleLocked(values.locale,
11793 !values.locale.equals(mConfiguration.locale),
11794 values.userSetLocale);
11795 }
11796
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011797 mConfigurationSeq++;
11798 if (mConfigurationSeq <= 0) {
11799 mConfigurationSeq = 1;
11800 }
11801 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011803 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011804
11805 AttributeCache ac = AttributeCache.instance();
11806 if (ac != null) {
11807 ac.updateConfiguration(mConfiguration);
11808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011810 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11811 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11812 msg.obj = new Configuration(mConfiguration);
11813 mHandler.sendMessage(msg);
11814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011816 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11817 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 try {
11819 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011820 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011821 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 app.thread.scheduleConfigurationChanged(mConfiguration);
11823 }
11824 } catch (Exception e) {
11825 }
11826 }
11827 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011828 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11829 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11831 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011832 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11833 broadcastIntentLocked(null, null,
11834 new Intent(Intent.ACTION_LOCALE_CHANGED),
11835 null, null, 0, null, null,
11836 null, false, false, MY_PID, Process.SYSTEM_UID);
11837 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 }
11839 }
11840
11841 if (changes != 0 && starting == null) {
11842 // If the configuration changed, and the caller is not already
11843 // in the process of starting an activity, then find the top
11844 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011845 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 }
11847
11848 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011849 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011850 // And we need to make sure at this point that all other activities
11851 // are made visible with the correct configuration.
11852 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 }
11854
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011855 if (values != null && mWindowManager != null) {
11856 mWindowManager.setNewConfiguration(mConfiguration);
11857 }
11858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 return kept;
11860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861
11862 /**
11863 * Save the locale. You must be inside a synchronized (this) block.
11864 */
11865 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11866 if(isDiff) {
11867 SystemProperties.set("user.language", l.getLanguage());
11868 SystemProperties.set("user.region", l.getCountry());
11869 }
11870
11871 if(isPersist) {
11872 SystemProperties.set("persist.sys.language", l.getLanguage());
11873 SystemProperties.set("persist.sys.country", l.getCountry());
11874 SystemProperties.set("persist.sys.localevar", l.getVariant());
11875 }
11876 }
11877
11878 // =========================================================
11879 // LIFETIME MANAGEMENT
11880 // =========================================================
11881
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011882 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11883 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011884 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011885 // This adjustment has already been computed. If we are calling
11886 // from the top, we may have already computed our adjustment with
11887 // an earlier hidden adjustment that isn't really for us... if
11888 // so, use the new hidden adjustment.
11889 if (!recursed && app.hidden) {
11890 app.curAdj = hiddenAdj;
11891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 return app.curAdj;
11893 }
11894
11895 if (app.thread == null) {
11896 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011897 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011898 return (app.curAdj=EMPTY_APP_ADJ);
11899 }
11900
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011901 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11902 // The max adjustment doesn't allow this app to be anything
11903 // below foreground, so it is not worth doing work for it.
11904 app.adjType = "fixed";
11905 app.adjSeq = mAdjSeq;
11906 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011907 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011908 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11909 return (app.curAdj=app.maxAdj);
11910 }
11911
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011912 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011913 app.adjSource = null;
11914 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011915 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011916 app.empty = false;
11917 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918
The Android Open Source Project4df24232009-03-05 14:34:35 -080011919 // Determine the importance of the process, starting with most
11920 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011922 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011924 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 // The last app on the list is the foreground app.
11926 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011927 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011928 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011929 } else if (app.instrumentationClass != null) {
11930 // Don't want to kill running instrumentation.
11931 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011932 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011933 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 } else if (app.curReceiver != null ||
11935 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11936 // An app that is currently receiving a broadcast also
11937 // counts as being in the foreground.
11938 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011939 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011940 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011941 } else if (app.executingServices.size() > 0) {
11942 // An app that is currently executing a service callback also
11943 // counts as being in the foreground.
11944 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011945 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011946 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 } else if ((N=app.activities.size()) != 0) {
11948 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011949 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011950 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011951 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011952 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011953 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011955 ActivityRecord r = app.activities.get(j);
11956 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011958 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011959 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011960 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011961 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011963 } else if (r.state == ActivityState.PAUSING
11964 || r.state == ActivityState.PAUSED
11965 || r.state == ActivityState.STOPPING) {
11966 adj = PERCEPTIBLE_APP_ADJ;
11967 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011968 }
11969 }
11970 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011971 // A very not-needed process. If this is lower in the lru list,
11972 // we will push it in to the empty bucket.
11973 app.hidden = true;
11974 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011975 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011976 adj = hiddenAdj;
11977 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080011979
11980 if (adj > PERCEPTIBLE_APP_ADJ) {
11981 if (app.foregroundServices) {
11982 // The user is aware of this app, so make it visible.
11983 adj = PERCEPTIBLE_APP_ADJ;
11984 schedGroup = Process.THREAD_GROUP_DEFAULT;
11985 app.adjType = "foreground-service";
11986 } else if (app.forcingToForeground != null) {
11987 // The user is aware of this app, so make it visible.
11988 adj = PERCEPTIBLE_APP_ADJ;
11989 schedGroup = Process.THREAD_GROUP_DEFAULT;
11990 app.adjType = "force-foreground";
11991 app.adjSource = app.forcingToForeground;
11992 }
11993 }
11994
11995 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
11996 // We don't want to kill the current heavy-weight process.
11997 adj = HEAVY_WEIGHT_APP_ADJ;
11998 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
11999 app.adjType = "heavy";
12000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012001
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012002 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12003 // This process is hosting what we currently consider to be the
12004 // home app, so we don't want to let it go into the background.
12005 adj = HOME_APP_ADJ;
12006 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12007 app.adjType = "home";
12008 }
12009
Joe Onorato8a9b2202010-02-26 18:56:32 -080012010 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012011
The Android Open Source Project4df24232009-03-05 14:34:35 -080012012 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013 // there are applications dependent on our services or providers, but
12014 // this gives us a baseline and makes sure we don't get into an
12015 // infinite recursion.
12016 app.adjSeq = mAdjSeq;
12017 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018
Christopher Tate6fa95972009-06-05 18:43:55 -070012019 if (mBackupTarget != null && app == mBackupTarget.app) {
12020 // If possible we want to avoid killing apps while they're being backed up
12021 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012022 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012023 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012024 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012025 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012026 }
12027 }
12028
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012029 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12030 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012031 final long now = SystemClock.uptimeMillis();
12032 // This process is more important if the top activity is
12033 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012034 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012036 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012037 if (s.startRequested) {
12038 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12039 // This service has seen some activity within
12040 // recent memory, so we will keep its process ahead
12041 // of the background processes.
12042 if (adj > SECONDARY_SERVER_ADJ) {
12043 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012044 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012045 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 }
12047 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012048 // If we have let the service slide into the background
12049 // state, still have some text describing what it is doing
12050 // even though the service no longer has an impact.
12051 if (adj > SECONDARY_SERVER_ADJ) {
12052 app.adjType = "started-bg-services";
12053 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012054 // Don't kill this process because it is doing work; it
12055 // has said it is doing work.
12056 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012057 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012058 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12059 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012060 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012061 = s.connections.values().iterator();
12062 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012063 ArrayList<ConnectionRecord> clist = kt.next();
12064 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12065 // XXX should compute this based on the max of
12066 // all connected clients.
12067 ConnectionRecord cr = clist.get(i);
12068 if (cr.binding.client == app) {
12069 // Binding to ourself is not interesting.
12070 continue;
12071 }
12072 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12073 ProcessRecord client = cr.binding.client;
12074 int myHiddenAdj = hiddenAdj;
12075 if (myHiddenAdj > client.hiddenAdj) {
12076 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12077 myHiddenAdj = client.hiddenAdj;
12078 } else {
12079 myHiddenAdj = VISIBLE_APP_ADJ;
12080 }
12081 }
12082 int clientAdj = computeOomAdjLocked(
12083 client, myHiddenAdj, TOP_APP, true);
12084 if (adj > clientAdj) {
12085 adj = clientAdj >= VISIBLE_APP_ADJ
12086 ? clientAdj : VISIBLE_APP_ADJ;
12087 if (!client.hidden) {
12088 app.hidden = false;
12089 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012090 if (client.keeping) {
12091 app.keeping = true;
12092 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012093 app.adjType = "service";
12094 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12095 .REASON_SERVICE_IN_USE;
12096 app.adjSource = cr.binding.client;
12097 app.adjTarget = s.name;
12098 }
12099 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12100 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12101 schedGroup = Process.THREAD_GROUP_DEFAULT;
12102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 }
12104 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012105 ActivityRecord a = cr.activity;
12106 //if (a != null) {
12107 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12108 //}
12109 if (a != null && adj > FOREGROUND_APP_ADJ &&
12110 (a.state == ActivityState.RESUMED
12111 || a.state == ActivityState.PAUSING)) {
12112 adj = FOREGROUND_APP_ADJ;
12113 schedGroup = Process.THREAD_GROUP_DEFAULT;
12114 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012115 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012116 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12117 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012118 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012119 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012121 }
12122 }
12123 }
12124 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012125
Dianne Hackborn287952c2010-09-22 22:34:31 -070012126 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012127 // would like to avoid killing it unless it would prevent the current
12128 // application from running. By default we put the process in
12129 // with the rest of the background processes; as we scan through
12130 // its services we may bump it up from there.
12131 if (adj > hiddenAdj) {
12132 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012133 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012134 app.adjType = "bg-services";
12135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012136 }
12137
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012138 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12139 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012140 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012141 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12142 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012143 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 if (cpr.clients.size() != 0) {
12145 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12146 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12147 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012148 if (client == app) {
12149 // Being our own client is not interesting.
12150 continue;
12151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152 int myHiddenAdj = hiddenAdj;
12153 if (myHiddenAdj > client.hiddenAdj) {
12154 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12155 myHiddenAdj = client.hiddenAdj;
12156 } else {
12157 myHiddenAdj = FOREGROUND_APP_ADJ;
12158 }
12159 }
12160 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012161 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012162 if (adj > clientAdj) {
12163 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012164 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012165 if (!client.hidden) {
12166 app.hidden = false;
12167 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012168 if (client.keeping) {
12169 app.keeping = true;
12170 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012171 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012172 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12173 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012174 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012175 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012177 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12178 schedGroup = Process.THREAD_GROUP_DEFAULT;
12179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012180 }
12181 }
12182 // If the provider has external (non-framework) process
12183 // dependencies, ensure that its adjustment is at least
12184 // FOREGROUND_APP_ADJ.
12185 if (cpr.externals != 0) {
12186 if (adj > FOREGROUND_APP_ADJ) {
12187 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012188 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012189 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012190 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012191 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012192 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012193 }
12194 }
12195 }
12196 }
12197
12198 app.curRawAdj = adj;
12199
Joe Onorato8a9b2202010-02-26 18:56:32 -080012200 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012201 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12202 if (adj > app.maxAdj) {
12203 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012204 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012205 schedGroup = Process.THREAD_GROUP_DEFAULT;
12206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012208 if (adj < HIDDEN_APP_MIN_ADJ) {
12209 app.keeping = true;
12210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012211
12212 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012213 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 return adj;
12216 }
12217
12218 /**
12219 * Ask a given process to GC right now.
12220 */
12221 final void performAppGcLocked(ProcessRecord app) {
12222 try {
12223 app.lastRequestedGc = SystemClock.uptimeMillis();
12224 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012225 if (app.reportLowMemory) {
12226 app.reportLowMemory = false;
12227 app.thread.scheduleLowMemory();
12228 } else {
12229 app.thread.processInBackground();
12230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012231 }
12232 } catch (Exception e) {
12233 // whatever.
12234 }
12235 }
12236
12237 /**
12238 * Returns true if things are idle enough to perform GCs.
12239 */
Josh Bartel7f208742010-02-25 11:01:44 -060012240 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012241 return mParallelBroadcasts.size() == 0
12242 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012243 && (mSleeping || (mMainStack.mResumedActivity != null &&
12244 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012245 }
12246
12247 /**
12248 * Perform GCs on all processes that are waiting for it, but only
12249 * if things are idle.
12250 */
12251 final void performAppGcsLocked() {
12252 final int N = mProcessesToGc.size();
12253 if (N <= 0) {
12254 return;
12255 }
Josh Bartel7f208742010-02-25 11:01:44 -060012256 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012257 while (mProcessesToGc.size() > 0) {
12258 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012259 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012260 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12261 <= SystemClock.uptimeMillis()) {
12262 // To avoid spamming the system, we will GC processes one
12263 // at a time, waiting a few seconds between each.
12264 performAppGcLocked(proc);
12265 scheduleAppGcsLocked();
12266 return;
12267 } else {
12268 // It hasn't been long enough since we last GCed this
12269 // process... put it in the list to wait for its time.
12270 addProcessToGcListLocked(proc);
12271 break;
12272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012273 }
12274 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012275
12276 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277 }
12278 }
12279
12280 /**
12281 * If all looks good, perform GCs on all processes waiting for them.
12282 */
12283 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012284 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012285 performAppGcsLocked();
12286 return;
12287 }
12288 // Still not idle, wait some more.
12289 scheduleAppGcsLocked();
12290 }
12291
12292 /**
12293 * Schedule the execution of all pending app GCs.
12294 */
12295 final void scheduleAppGcsLocked() {
12296 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012297
12298 if (mProcessesToGc.size() > 0) {
12299 // Schedule a GC for the time to the next process.
12300 ProcessRecord proc = mProcessesToGc.get(0);
12301 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12302
12303 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12304 long now = SystemClock.uptimeMillis();
12305 if (when < (now+GC_TIMEOUT)) {
12306 when = now + GC_TIMEOUT;
12307 }
12308 mHandler.sendMessageAtTime(msg, when);
12309 }
12310 }
12311
12312 /**
12313 * Add a process to the array of processes waiting to be GCed. Keeps the
12314 * list in sorted order by the last GC time. The process can't already be
12315 * on the list.
12316 */
12317 final void addProcessToGcListLocked(ProcessRecord proc) {
12318 boolean added = false;
12319 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12320 if (mProcessesToGc.get(i).lastRequestedGc <
12321 proc.lastRequestedGc) {
12322 added = true;
12323 mProcessesToGc.add(i+1, proc);
12324 break;
12325 }
12326 }
12327 if (!added) {
12328 mProcessesToGc.add(0, proc);
12329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 }
12331
12332 /**
12333 * Set up to ask a process to GC itself. This will either do it
12334 * immediately, or put it on the list of processes to gc the next
12335 * time things are idle.
12336 */
12337 final void scheduleAppGcLocked(ProcessRecord app) {
12338 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012339 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012340 return;
12341 }
12342 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012343 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012344 scheduleAppGcsLocked();
12345 }
12346 }
12347
Dianne Hackborn287952c2010-09-22 22:34:31 -070012348 final void checkExcessivePowerUsageLocked(boolean doKills) {
12349 updateCpuStatsNow();
12350
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012351 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012352 boolean doWakeKills = doKills;
12353 boolean doCpuKills = doKills;
12354 if (mLastPowerCheckRealtime == 0) {
12355 doWakeKills = false;
12356 }
12357 if (mLastPowerCheckUptime == 0) {
12358 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012359 }
12360 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012361 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012362 }
12363 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012364 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12365 final long curUptime = SystemClock.uptimeMillis();
12366 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12367 mLastPowerCheckRealtime = curRealtime;
12368 mLastPowerCheckUptime = curUptime;
12369 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12370 doWakeKills = false;
12371 }
12372 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12373 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012374 }
12375 int i = mLruProcesses.size();
12376 while (i > 0) {
12377 i--;
12378 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012379 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012380 long wtime;
12381 synchronized (stats) {
12382 wtime = stats.getProcessWakeTime(app.info.uid,
12383 app.pid, curRealtime);
12384 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012385 long wtimeUsed = wtime - app.lastWakeTime;
12386 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12387 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012388 StringBuilder sb = new StringBuilder(128);
12389 sb.append("Wake for ");
12390 app.toShortString(sb);
12391 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012392 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012393 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012394 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012395 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012396 sb.append((wtimeUsed*100)/realtimeSince);
12397 sb.append("%)");
12398 Slog.i(TAG, sb.toString());
12399 sb.setLength(0);
12400 sb.append("CPU for ");
12401 app.toShortString(sb);
12402 sb.append(": over ");
12403 TimeUtils.formatDuration(uptimeSince, sb);
12404 sb.append(" used ");
12405 TimeUtils.formatDuration(cputimeUsed, sb);
12406 sb.append(" (");
12407 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012408 sb.append("%)");
12409 Slog.i(TAG, sb.toString());
12410 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012411 // If a process has held a wake lock for more
12412 // than 50% of the time during this period,
12413 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012414 if (doWakeKills && realtimeSince > 0
12415 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12416 synchronized (stats) {
12417 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12418 realtimeSince, wtimeUsed);
12419 }
12420 Slog.w(TAG, "Excessive wake lock in " + app.processName
12421 + " (pid " + app.pid + "): held " + wtimeUsed
12422 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012423 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12424 app.processName, app.setAdj, "excessive wake lock");
12425 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012426 } else if (doCpuKills && uptimeSince > 0
12427 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12428 synchronized (stats) {
12429 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12430 uptimeSince, cputimeUsed);
12431 }
12432 Slog.w(TAG, "Excessive CPU in " + app.processName
12433 + " (pid " + app.pid + "): used " + cputimeUsed
12434 + " during " + uptimeSince);
12435 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12436 app.processName, app.setAdj, "excessive cpu");
12437 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012438 } else {
12439 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012440 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012441 }
12442 }
12443 }
12444 }
12445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 private final boolean updateOomAdjLocked(
12447 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12448 app.hiddenAdj = hiddenAdj;
12449
12450 if (app.thread == null) {
12451 return true;
12452 }
12453
Dianne Hackborn287952c2010-09-22 22:34:31 -070012454 final boolean wasKeeping = app.keeping;
12455
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012456 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012457
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012458 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 if (app.curRawAdj != app.setRawAdj) {
12460 if (app.curRawAdj > FOREGROUND_APP_ADJ
12461 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12462 // If this app is transitioning from foreground to
12463 // non-foreground, have it do a gc.
12464 scheduleAppGcLocked(app);
12465 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12466 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12467 // Likewise do a gc when an app is moving in to the
12468 // background (such as a service stopping).
12469 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012470 }
12471
12472 if (wasKeeping && !app.keeping) {
12473 // This app is no longer something we want to keep. Note
12474 // its current wake lock time to later know to kill it if
12475 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012476 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12477 synchronized (stats) {
12478 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12479 app.pid, SystemClock.elapsedRealtime());
12480 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012481 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012482 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484 app.setRawAdj = app.curRawAdj;
12485 }
12486 if (adj != app.setAdj) {
12487 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012488 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012489 TAG, "Set app " + app.processName +
12490 " oom adj to " + adj);
12491 app.setAdj = adj;
12492 } else {
12493 return false;
12494 }
12495 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012496 if (app.setSchedGroup != app.curSchedGroup) {
12497 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012498 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012499 "Setting process group of " + app.processName
12500 + " to " + app.curSchedGroup);
12501 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012502 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012503 try {
12504 Process.setProcessGroup(app.pid, app.curSchedGroup);
12505 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012506 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012507 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012508 e.printStackTrace();
12509 } finally {
12510 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012511 }
12512 }
12513 if (false) {
12514 if (app.thread != null) {
12515 try {
12516 app.thread.setSchedulingGroup(app.curSchedGroup);
12517 } catch (RemoteException e) {
12518 }
12519 }
12520 }
12521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 }
12523
12524 return true;
12525 }
12526
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012527 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012528 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012529 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012530 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012532 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533 }
12534 }
12535 return resumedActivity;
12536 }
12537
12538 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012539 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12541 int curAdj = app.curAdj;
12542 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12543 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12544
12545 mAdjSeq++;
12546
12547 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12548 if (res) {
12549 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12550 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12551 if (nowHidden != wasHidden) {
12552 // Changed to/from hidden state, so apps after it in the LRU
12553 // list may also be changed.
12554 updateOomAdjLocked();
12555 }
12556 }
12557 return res;
12558 }
12559
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012560 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012561 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012562 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012563 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12564
12565 if (false) {
12566 RuntimeException e = new RuntimeException();
12567 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012568 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012569 }
12570
12571 mAdjSeq++;
12572
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012573 // Let's determine how many processes we have running vs.
12574 // how many slots we have for background processes; we may want
12575 // to put multiple processes in a slot of there are enough of
12576 // them.
12577 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12578 int factor = (mLruProcesses.size()-4)/numSlots;
12579 if (factor < 1) factor = 1;
12580 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012581 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012583 // First try updating the OOM adjustment for each of the
12584 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012585 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012586 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12587 while (i > 0) {
12588 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012589 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012590 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012591 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012592 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012593 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012594 step++;
12595 if (step >= factor) {
12596 step = 0;
12597 curHiddenAdj++;
12598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012600 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012601 if (!app.killedBackground) {
12602 numHidden++;
12603 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012604 Slog.i(TAG, "No longer want " + app.processName
12605 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012606 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12607 app.processName, app.setAdj, "too many background");
12608 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012609 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012610 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012611 }
12612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012613 } else {
12614 didOomAdj = false;
12615 }
12616 }
12617
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012618 // If we return false, we will fall back on killing processes to
12619 // have a fixed limit. Do this if a limit has been requested; else
12620 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012621 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12622 }
12623
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012624 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012625 synchronized (this) {
12626 int i;
12627
12628 // First remove any unused application processes whose package
12629 // has been removed.
12630 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12631 final ProcessRecord app = mRemovedProcesses.get(i);
12632 if (app.activities.size() == 0
12633 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012634 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 TAG, "Exiting empty application process "
12636 + app.processName + " ("
12637 + (app.thread != null ? app.thread.asBinder() : null)
12638 + ")\n");
12639 if (app.pid > 0 && app.pid != MY_PID) {
12640 Process.killProcess(app.pid);
12641 } else {
12642 try {
12643 app.thread.scheduleExit();
12644 } catch (Exception e) {
12645 // Ignore exceptions.
12646 }
12647 }
12648 cleanUpApplicationRecordLocked(app, false, -1);
12649 mRemovedProcesses.remove(i);
12650
12651 if (app.persistent) {
12652 if (app.persistent) {
12653 addAppLocked(app.info);
12654 }
12655 }
12656 }
12657 }
12658
12659 // Now try updating the OOM adjustment for each of the
12660 // application processes based on their current state.
12661 // If the setOomAdj() API is not supported, then go with our
12662 // back-up plan...
12663 if (!updateOomAdjLocked()) {
12664
12665 // Count how many processes are running services.
12666 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012667 for (i=mLruProcesses.size()-1; i>=0; i--) {
12668 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669
12670 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012671 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 // Don't count processes holding services against our
12673 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012674 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012675 TAG, "Not trimming app " + app + " with services: "
12676 + app.services);
12677 numServiceProcs++;
12678 }
12679 }
12680
12681 int curMaxProcs = mProcessLimit;
12682 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12683 if (mAlwaysFinishActivities) {
12684 curMaxProcs = 1;
12685 }
12686 curMaxProcs += numServiceProcs;
12687
12688 // Quit as many processes as we can to get down to the desired
12689 // process count. First remove any processes that no longer
12690 // have activites running in them.
12691 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012692 i<mLruProcesses.size()
12693 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012694 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012695 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012696 // Quit an application only if it is not currently
12697 // running any activities.
12698 if (!app.persistent && app.activities.size() == 0
12699 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012700 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012701 TAG, "Exiting empty application process "
12702 + app.processName + " ("
12703 + (app.thread != null ? app.thread.asBinder() : null)
12704 + ")\n");
12705 if (app.pid > 0 && app.pid != MY_PID) {
12706 Process.killProcess(app.pid);
12707 } else {
12708 try {
12709 app.thread.scheduleExit();
12710 } catch (Exception e) {
12711 // Ignore exceptions.
12712 }
12713 }
12714 // todo: For now we assume the application is not buggy
12715 // or evil, and will quit as a result of our request.
12716 // Eventually we need to drive this off of the death
12717 // notification, and kill the process if it takes too long.
12718 cleanUpApplicationRecordLocked(app, false, i);
12719 i--;
12720 }
12721 }
12722
12723 // If we still have too many processes, now from the least
12724 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012725 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012726 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012727 " of " + curMaxProcs + " processes");
12728 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012729 i<mLruProcesses.size()
12730 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012731 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012732 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012733 // Quit the application only if we have a state saved for
12734 // all of its activities.
12735 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012736 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012737 int NUMA = app.activities.size();
12738 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012739 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740 TAG, "Looking to quit " + app.processName);
12741 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012742 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012743 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012744 TAG, " " + r.intent.getComponent().flattenToShortString()
12745 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12746 canQuit = (r.haveState || !r.stateNotNeeded)
12747 && !r.visible && r.stopped;
12748 }
12749 if (canQuit) {
12750 // Finish all of the activities, and then the app itself.
12751 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012752 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012753 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012754 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 }
12756 r.resultTo = null;
12757 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012758 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012759 + app.processName + " ("
12760 + (app.thread != null ? app.thread.asBinder() : null)
12761 + ")\n");
12762 if (app.pid > 0 && app.pid != MY_PID) {
12763 Process.killProcess(app.pid);
12764 } else {
12765 try {
12766 app.thread.scheduleExit();
12767 } catch (Exception e) {
12768 // Ignore exceptions.
12769 }
12770 }
12771 // todo: For now we assume the application is not buggy
12772 // or evil, and will quit as a result of our request.
12773 // Eventually we need to drive this off of the death
12774 // notification, and kill the process if it takes too long.
12775 cleanUpApplicationRecordLocked(app, false, i);
12776 i--;
12777 //dump();
12778 }
12779 }
12780
12781 }
12782
12783 int curMaxActivities = MAX_ACTIVITIES;
12784 if (mAlwaysFinishActivities) {
12785 curMaxActivities = 1;
12786 }
12787
12788 // Finally, if there are too many activities now running, try to
12789 // finish as many as we can to get back down to the limit.
12790 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012791 i<mMainStack.mLRUActivities.size()
12792 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012793 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012794 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012795 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012796
12797 // We can finish this one if we have its icicle saved and
12798 // it is not persistent.
12799 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012800 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012801 final int origSize = mMainStack.mLRUActivities.size();
12802 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012803
12804 // This will remove it from the LRU list, so keep
12805 // our index at the same value. Note that this check to
12806 // see if the size changes is just paranoia -- if
12807 // something unexpected happens, we don't want to end up
12808 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012809 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012810 i--;
12811 }
12812 }
12813 }
12814 }
12815 }
12816
12817 /** This method sends the specified signal to each of the persistent apps */
12818 public void signalPersistentProcesses(int sig) throws RemoteException {
12819 if (sig != Process.SIGNAL_USR1) {
12820 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12821 }
12822
12823 synchronized (this) {
12824 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12825 != PackageManager.PERMISSION_GRANTED) {
12826 throw new SecurityException("Requires permission "
12827 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12828 }
12829
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012830 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12831 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012832 if (r.thread != null && r.persistent) {
12833 Process.sendSignal(r.pid, sig);
12834 }
12835 }
12836 }
12837 }
12838
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012839 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012840 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012841
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012842 try {
12843 synchronized (this) {
12844 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12845 // its own permission.
12846 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12847 != PackageManager.PERMISSION_GRANTED) {
12848 throw new SecurityException("Requires permission "
12849 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012850 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012851
12852 if (start && fd == null) {
12853 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012854 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012855
12856 ProcessRecord proc = null;
12857 try {
12858 int pid = Integer.parseInt(process);
12859 synchronized (mPidsSelfLocked) {
12860 proc = mPidsSelfLocked.get(pid);
12861 }
12862 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012863 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012864
12865 if (proc == null) {
12866 HashMap<String, SparseArray<ProcessRecord>> all
12867 = mProcessNames.getMap();
12868 SparseArray<ProcessRecord> procs = all.get(process);
12869 if (procs != null && procs.size() > 0) {
12870 proc = procs.valueAt(0);
12871 }
12872 }
12873
12874 if (proc == null || proc.thread == null) {
12875 throw new IllegalArgumentException("Unknown process: " + process);
12876 }
12877
12878 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12879 if (isSecure) {
12880 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12881 throw new SecurityException("Process not debuggable: " + proc);
12882 }
12883 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012884
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012885 proc.thread.profilerControl(start, path, fd);
12886 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012887 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012888 }
12889 } catch (RemoteException e) {
12890 throw new IllegalStateException("Process disappeared");
12891 } finally {
12892 if (fd != null) {
12893 try {
12894 fd.close();
12895 } catch (IOException e) {
12896 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012897 }
12898 }
12899 }
Andy McFadden824c5102010-07-09 16:26:57 -070012900
12901 public boolean dumpHeap(String process, boolean managed,
12902 String path, ParcelFileDescriptor fd) throws RemoteException {
12903
12904 try {
12905 synchronized (this) {
12906 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12907 // its own permission (same as profileControl).
12908 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12909 != PackageManager.PERMISSION_GRANTED) {
12910 throw new SecurityException("Requires permission "
12911 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12912 }
12913
12914 if (fd == null) {
12915 throw new IllegalArgumentException("null fd");
12916 }
12917
12918 ProcessRecord proc = null;
12919 try {
12920 int pid = Integer.parseInt(process);
12921 synchronized (mPidsSelfLocked) {
12922 proc = mPidsSelfLocked.get(pid);
12923 }
12924 } catch (NumberFormatException e) {
12925 }
12926
12927 if (proc == null) {
12928 HashMap<String, SparseArray<ProcessRecord>> all
12929 = mProcessNames.getMap();
12930 SparseArray<ProcessRecord> procs = all.get(process);
12931 if (procs != null && procs.size() > 0) {
12932 proc = procs.valueAt(0);
12933 }
12934 }
12935
12936 if (proc == null || proc.thread == null) {
12937 throw new IllegalArgumentException("Unknown process: " + process);
12938 }
12939
12940 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12941 if (isSecure) {
12942 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12943 throw new SecurityException("Process not debuggable: " + proc);
12944 }
12945 }
12946
12947 proc.thread.dumpHeap(managed, path, fd);
12948 fd = null;
12949 return true;
12950 }
12951 } catch (RemoteException e) {
12952 throw new IllegalStateException("Process disappeared");
12953 } finally {
12954 if (fd != null) {
12955 try {
12956 fd.close();
12957 } catch (IOException e) {
12958 }
12959 }
12960 }
12961 }
12962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012963 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12964 public void monitor() {
12965 synchronized (this) { }
12966 }
12967}