blob: 8d30868c52482423d8a78d221a7973badc5f4e42 [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;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
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);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003148 try {
3149 pm.setPackageStoppedState(packageName, true);
3150 } catch (RemoteException e) {
3151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003152 }
3153 } finally {
3154 Binder.restoreCallingIdentity(callingId);
3155 }
3156 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003157
3158 /*
3159 * The pkg name and uid have to be specified.
3160 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3161 */
3162 public void killApplicationWithUid(String pkg, int uid) {
3163 if (pkg == null) {
3164 return;
3165 }
3166 // Make sure the uid is valid.
3167 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003168 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003169 return;
3170 }
3171 int callerUid = Binder.getCallingUid();
3172 // Only the system server can kill an application
3173 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003174 // Post an aysnc message to kill the application
3175 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3176 msg.arg1 = uid;
3177 msg.arg2 = 0;
3178 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003179 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003180 } else {
3181 throw new SecurityException(callerUid + " cannot kill pkg: " +
3182 pkg);
3183 }
3184 }
3185
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003186 public void closeSystemDialogs(String reason) {
3187 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003188 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003189 if (reason != null) {
3190 intent.putExtra("reason", reason);
3191 }
3192
3193 final int uid = Binder.getCallingUid();
3194 final long origId = Binder.clearCallingIdentity();
3195 synchronized (this) {
3196 int i = mWatchers.beginBroadcast();
3197 while (i > 0) {
3198 i--;
3199 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3200 if (w != null) {
3201 try {
3202 w.closingSystemDialogs(reason);
3203 } catch (RemoteException e) {
3204 }
3205 }
3206 }
3207 mWatchers.finishBroadcast();
3208
Dianne Hackbornffa42482009-09-23 22:20:11 -07003209 mWindowManager.closeSystemDialogs(reason);
3210
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003211 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3212 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003213 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003214 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003215 Activity.RESULT_CANCELED, null, "close-sys");
3216 }
3217 }
3218
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003219 broadcastIntentLocked(null, null, intent, null,
3220 null, 0, null, null, null, false, false, -1, uid);
3221 }
3222 Binder.restoreCallingIdentity(origId);
3223 }
3224
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003225 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003226 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003227 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3228 for (int i=pids.length-1; i>=0; i--) {
3229 infos[i] = new Debug.MemoryInfo();
3230 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003231 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003232 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003233 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003234
3235 public void killApplicationProcess(String processName, int uid) {
3236 if (processName == null) {
3237 return;
3238 }
3239
3240 int callerUid = Binder.getCallingUid();
3241 // Only the system server can kill an application
3242 if (callerUid == Process.SYSTEM_UID) {
3243 synchronized (this) {
3244 ProcessRecord app = getProcessRecordLocked(processName, uid);
3245 if (app != null) {
3246 try {
3247 app.thread.scheduleSuicide();
3248 } catch (RemoteException e) {
3249 // If the other end already died, then our work here is done.
3250 }
3251 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003252 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003253 + processName + " / " + uid);
3254 }
3255 }
3256 } else {
3257 throw new SecurityException(callerUid + " cannot kill app process: " +
3258 processName);
3259 }
3260 }
3261
Dianne Hackborn03abb812010-01-04 18:43:19 -08003262 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003263 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3265 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003266 if (!mProcessesReady) {
3267 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 intent.putExtra(Intent.EXTRA_UID, uid);
3270 broadcastIntentLocked(null, null, intent,
3271 null, null, 0, null, null, null,
3272 false, false, MY_PID, Process.SYSTEM_UID);
3273 }
3274
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003275 private final boolean killPackageProcessesLocked(String packageName, int uid,
3276 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003277 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278
Dianne Hackborn03abb812010-01-04 18:43:19 -08003279 // Remove all processes this package may have touched: all with the
3280 // same UID (except for the system or root user), and all whose name
3281 // matches the package name.
3282 final String procNamePrefix = packageName + ":";
3283 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3284 final int NA = apps.size();
3285 for (int ia=0; ia<NA; ia++) {
3286 ProcessRecord app = apps.valueAt(ia);
3287 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003288 if (doit) {
3289 procs.add(app);
3290 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003291 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3292 || app.processName.equals(packageName)
3293 || app.processName.startsWith(procNamePrefix)) {
3294 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003295 if (!doit) {
3296 return true;
3297 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003298 app.removed = true;
3299 procs.add(app);
3300 }
3301 }
3302 }
3303 }
3304
3305 int N = procs.size();
3306 for (int i=0; i<N; i++) {
3307 removeProcessLocked(procs.get(i), callerWillRestart);
3308 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003309 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003310 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003311
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003312 private final boolean forceStopPackageLocked(String name, int uid,
3313 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 int i, N;
3315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 if (uid < 0) {
3317 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003318 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 } catch (RemoteException e) {
3320 }
3321 }
3322
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003323 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003324 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003325
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003326 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3327 while (badApps.hasNext()) {
3328 SparseArray<Long> ba = badApps.next();
3329 if (ba.get(uid) != null) {
3330 badApps.remove();
3331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 }
3333 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003334
3335 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3336 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003338 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3339 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003341 if (!doit) {
3342 return true;
3343 }
3344 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003345 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 if (r.app != null) {
3347 r.app.removed = true;
3348 }
3349 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003350 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 }
3352 }
3353
3354 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3355 for (ServiceRecord service : mServices.values()) {
3356 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003357 if (!doit) {
3358 return true;
3359 }
3360 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003361 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 if (service.app != null) {
3363 service.app.removed = true;
3364 }
3365 service.app = null;
3366 services.add(service);
3367 }
3368 }
3369
3370 N = services.size();
3371 for (i=0; i<N; i++) {
3372 bringDownServiceLocked(services.get(i), true);
3373 }
3374
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003375 if (doit) {
3376 if (purgeCache) {
3377 AttributeCache ac = AttributeCache.instance();
3378 if (ac != null) {
3379 ac.removePackage(name);
3380 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003381 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003382 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003383 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003384
3385 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 }
3387
3388 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3389 final String name = app.processName;
3390 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003391 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 TAG, "Force removing process " + app + " (" + name
3393 + "/" + uid + ")");
3394
3395 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003396 if (mHeavyWeightProcess == app) {
3397 mHeavyWeightProcess = null;
3398 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 boolean needRestart = false;
3401 if (app.pid > 0 && app.pid != MY_PID) {
3402 int pid = app.pid;
3403 synchronized (mPidsSelfLocked) {
3404 mPidsSelfLocked.remove(pid);
3405 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3406 }
3407 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003408 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 Process.killProcess(pid);
3410
3411 if (app.persistent) {
3412 if (!callerWillRestart) {
3413 addAppLocked(app.info);
3414 } else {
3415 needRestart = true;
3416 }
3417 }
3418 } else {
3419 mRemovedProcesses.add(app);
3420 }
3421
3422 return needRestart;
3423 }
3424
3425 private final void processStartTimedOutLocked(ProcessRecord app) {
3426 final int pid = app.pid;
3427 boolean gone = false;
3428 synchronized (mPidsSelfLocked) {
3429 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3430 if (knownApp != null && knownApp.thread == null) {
3431 mPidsSelfLocked.remove(pid);
3432 gone = true;
3433 }
3434 }
3435
3436 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003437 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003438 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003439 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003441 if (mHeavyWeightProcess == app) {
3442 mHeavyWeightProcess = null;
3443 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3444 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003445 // Take care of any launching providers waiting for this process.
3446 checkAppInLaunchingProvidersLocked(app, true);
3447 // Take care of any services that are waiting for the process.
3448 for (int i=0; i<mPendingServices.size(); i++) {
3449 ServiceRecord sr = mPendingServices.get(i);
3450 if (app.info.uid == sr.appInfo.uid
3451 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003452 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003453 mPendingServices.remove(i);
3454 i--;
3455 bringDownServiceLocked(sr, true);
3456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003458 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003459 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003460 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003461 try {
3462 IBackupManager bm = IBackupManager.Stub.asInterface(
3463 ServiceManager.getService(Context.BACKUP_SERVICE));
3464 bm.agentDisconnected(app.info.packageName);
3465 } catch (RemoteException e) {
3466 // Can't happen; the backup manager is local
3467 }
3468 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003469 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003470 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003471 mPendingBroadcast.state = BroadcastRecord.IDLE;
3472 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003473 mPendingBroadcast = null;
3474 scheduleBroadcastsLocked();
3475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003477 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 }
3479 }
3480
3481 private final boolean attachApplicationLocked(IApplicationThread thread,
3482 int pid) {
3483
3484 // Find the application record that is being attached... either via
3485 // the pid if we are running in multiple processes, or just pull the
3486 // next app record if we are emulating process with anonymous threads.
3487 ProcessRecord app;
3488 if (pid != MY_PID && pid >= 0) {
3489 synchronized (mPidsSelfLocked) {
3490 app = mPidsSelfLocked.get(pid);
3491 }
3492 } else if (mStartingProcesses.size() > 0) {
3493 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003494 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 } else {
3496 app = null;
3497 }
3498
3499 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003500 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003502 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503 if (pid > 0 && pid != MY_PID) {
3504 Process.killProcess(pid);
3505 } else {
3506 try {
3507 thread.scheduleExit();
3508 } catch (Exception e) {
3509 // Ignore exceptions.
3510 }
3511 }
3512 return false;
3513 }
3514
3515 // If this application record is still attached to a previous
3516 // process, clean it up now.
3517 if (app.thread != null) {
3518 handleAppDiedLocked(app, true);
3519 }
3520
3521 // Tell the process all about itself.
3522
Joe Onorato8a9b2202010-02-26 18:56:32 -08003523 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 TAG, "Binding process pid " + pid + " to record " + app);
3525
3526 String processName = app.processName;
3527 try {
3528 thread.asBinder().linkToDeath(new AppDeathRecipient(
3529 app, pid, thread), 0);
3530 } catch (RemoteException e) {
3531 app.resetPackageList();
3532 startProcessLocked(app, "link fail", processName);
3533 return false;
3534 }
3535
Doug Zongker2bec3d42009-12-04 12:52:44 -08003536 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537
3538 app.thread = thread;
3539 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003540 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3541 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 app.forcingToForeground = null;
3543 app.foregroundServices = false;
3544 app.debugging = false;
3545
3546 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3547
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003548 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003549 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003551 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003552 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003553 }
3554
Joe Onorato8a9b2202010-02-26 18:56:32 -08003555 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 TAG, "New app record " + app
3557 + " thread=" + thread.asBinder() + " pid=" + pid);
3558 try {
3559 int testMode = IApplicationThread.DEBUG_OFF;
3560 if (mDebugApp != null && mDebugApp.equals(processName)) {
3561 testMode = mWaitForDebugger
3562 ? IApplicationThread.DEBUG_WAIT
3563 : IApplicationThread.DEBUG_ON;
3564 app.debugging = true;
3565 if (mDebugTransient) {
3566 mDebugApp = mOrigDebugApp;
3567 mWaitForDebugger = mOrigWaitForDebugger;
3568 }
3569 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003570
Christopher Tate181fafa2009-05-14 11:12:14 -07003571 // If the app is being launched for restore or full backup, set it up specially
3572 boolean isRestrictedBackupMode = false;
3573 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3574 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3575 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3576 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003577
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003578 ensurePackageDexOpt(app.instrumentationInfo != null
3579 ? app.instrumentationInfo.packageName
3580 : app.info.packageName);
3581 if (app.instrumentationClass != null) {
3582 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003583 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003584 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003585 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003586 thread.bindApplication(processName, app.instrumentationInfo != null
3587 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 app.instrumentationClass, app.instrumentationProfileFile,
3589 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003590 isRestrictedBackupMode || !normalMode,
3591 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003592 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003593 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 } catch (Exception e) {
3595 // todo: Yikes! What should we do? For now we will try to
3596 // start another process, but that could easily get us in
3597 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003598 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599
3600 app.resetPackageList();
3601 startProcessLocked(app, "bind fail", processName);
3602 return false;
3603 }
3604
3605 // Remove this record from the list of starting applications.
3606 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003607 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3608 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 mProcessesOnHold.remove(app);
3610
3611 boolean badApp = false;
3612 boolean didSomething = false;
3613
3614 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003615 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003616 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3618 && processName.equals(hr.processName)) {
3619 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003620 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 didSomething = true;
3622 }
3623 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003624 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 + hr.intent.getComponent().flattenToShortString(), e);
3626 badApp = true;
3627 }
3628 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003629 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 }
3631 }
3632
3633 // Find any services that should be running in this process...
3634 if (!badApp && mPendingServices.size() > 0) {
3635 ServiceRecord sr = null;
3636 try {
3637 for (int i=0; i<mPendingServices.size(); i++) {
3638 sr = mPendingServices.get(i);
3639 if (app.info.uid != sr.appInfo.uid
3640 || !processName.equals(sr.processName)) {
3641 continue;
3642 }
3643
3644 mPendingServices.remove(i);
3645 i--;
3646 realStartServiceLocked(sr, app);
3647 didSomething = true;
3648 }
3649 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003650 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 + sr.shortName, e);
3652 badApp = true;
3653 }
3654 }
3655
3656 // Check if the next broadcast receiver is in this process...
3657 BroadcastRecord br = mPendingBroadcast;
3658 if (!badApp && br != null && br.curApp == app) {
3659 try {
3660 mPendingBroadcast = null;
3661 processCurBroadcastLocked(br, app);
3662 didSomething = true;
3663 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003664 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 + br.curComponent.flattenToShortString(), e);
3666 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003667 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3669 br.resultExtras, br.resultAbort, true);
3670 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003671 // We need to reset the state if we fails to start the receiver.
3672 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 }
3674 }
3675
Christopher Tate181fafa2009-05-14 11:12:14 -07003676 // Check whether the next backup agent is in this process...
3677 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003678 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003679 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003680 try {
3681 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3682 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003683 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003684 e.printStackTrace();
3685 }
3686 }
3687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 if (badApp) {
3689 // todo: Also need to kill application to deal with all
3690 // kinds of exceptions.
3691 handleAppDiedLocked(app, false);
3692 return false;
3693 }
3694
3695 if (!didSomething) {
3696 updateOomAdjLocked();
3697 }
3698
3699 return true;
3700 }
3701
3702 public final void attachApplication(IApplicationThread thread) {
3703 synchronized (this) {
3704 int callingPid = Binder.getCallingPid();
3705 final long origId = Binder.clearCallingIdentity();
3706 attachApplicationLocked(thread, callingPid);
3707 Binder.restoreCallingIdentity(origId);
3708 }
3709 }
3710
Dianne Hackborne88846e2009-09-30 21:34:25 -07003711 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003713 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 Binder.restoreCallingIdentity(origId);
3715 }
3716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003718 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003719 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 mWindowManager.enableScreenAfterBoot();
3721 }
3722
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003723 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003724 IntentFilter pkgFilter = new IntentFilter();
3725 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3726 pkgFilter.addDataScheme("package");
3727 mContext.registerReceiver(new BroadcastReceiver() {
3728 @Override
3729 public void onReceive(Context context, Intent intent) {
3730 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3731 if (pkgs != null) {
3732 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003733 synchronized (ActivityManagerService.this) {
3734 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3735 setResultCode(Activity.RESULT_OK);
3736 return;
3737 }
3738 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003739 }
3740 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003741 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003742 }, pkgFilter);
3743
3744 synchronized (this) {
3745 // Ensure that any processes we had put on hold are now started
3746 // up.
3747 final int NP = mProcessesOnHold.size();
3748 if (NP > 0) {
3749 ArrayList<ProcessRecord> procs =
3750 new ArrayList<ProcessRecord>(mProcessesOnHold);
3751 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003752 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3753 + procs.get(ip));
3754 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003755 }
3756 }
3757
3758 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003759 // Start looking for apps that are abusing wake locks.
3760 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003761 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003762 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003763 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003764 broadcastIntentLocked(null, null,
3765 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3766 null, null, 0, null, null,
3767 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3768 false, false, MY_PID, Process.SYSTEM_UID);
3769 }
3770 }
3771 }
3772
3773 final void ensureBootCompleted() {
3774 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003775 boolean enableScreen;
3776 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003777 booting = mBooting;
3778 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003779 enableScreen = !mBooted;
3780 mBooted = true;
3781 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003782
3783 if (booting) {
3784 finishBooting();
3785 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003786
3787 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003788 enableScreenAfterBoot();
3789 }
3790 }
3791
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003792 public final void activityPaused(IBinder token) {
3793 final long origId = Binder.clearCallingIdentity();
3794 mMainStack.activityPaused(token, false);
3795 Binder.restoreCallingIdentity(origId);
3796 }
3797
3798 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3799 CharSequence description) {
3800 if (localLOGV) Slog.v(
3801 TAG, "Activity stopped: token=" + token);
3802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 // Refuse possible leaked file descriptors
3804 if (icicle != null && icicle.hasFileDescriptors()) {
3805 throw new IllegalArgumentException("File descriptors passed in Bundle");
3806 }
3807
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003808 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809
3810 final long origId = Binder.clearCallingIdentity();
3811
3812 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003813 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003815 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003816 r.icicle = icicle;
3817 r.haveState = true;
3818 if (thumbnail != null) {
3819 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003820 if (r.task != null) {
3821 r.task.lastThumbnail = r.thumbnail;
3822 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003825 if (r.task != null) {
3826 r.task.lastDescription = r.description;
3827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 r.stopped = true;
3829 r.state = ActivityState.STOPPED;
3830 if (!r.finishing) {
3831 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003832 r.stack.destroyActivityLocked(r, true);
3833 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 }
3835 }
3836 }
3837 }
3838
3839 if (r != null) {
3840 sendPendingThumbnail(r, null, null, null, false);
3841 }
3842
3843 trimApplications();
3844
3845 Binder.restoreCallingIdentity(origId);
3846 }
3847
3848 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003849 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003850 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 }
3852
3853 public String getCallingPackage(IBinder token) {
3854 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003855 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003856 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 }
3858 }
3859
3860 public ComponentName getCallingActivity(IBinder token) {
3861 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003862 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 return r != null ? r.intent.getComponent() : null;
3864 }
3865 }
3866
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003867 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003868 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003869 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003870 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 if (r != null) {
3872 return r.resultTo;
3873 }
3874 }
3875 return null;
3876 }
3877
3878 public ComponentName getActivityClassForToken(IBinder token) {
3879 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003880 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003881 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003882 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 return r.intent.getComponent();
3884 }
3885 return null;
3886 }
3887 }
3888
3889 public String getPackageForToken(IBinder token) {
3890 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003891 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003893 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 return r.packageName;
3895 }
3896 return null;
3897 }
3898 }
3899
3900 public IIntentSender getIntentSender(int type,
3901 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003902 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003904 if (intents != null) {
3905 if (intents.length < 1) {
3906 throw new IllegalArgumentException("Intents array length must be >= 1");
3907 }
3908 for (int i=0; i<intents.length; i++) {
3909 Intent intent = intents[i];
3910 if (intent == null) {
3911 throw new IllegalArgumentException("Null intent at index " + i);
3912 }
3913 if (intent.hasFileDescriptors()) {
3914 throw new IllegalArgumentException("File descriptors passed in Intent");
3915 }
3916 if (type == INTENT_SENDER_BROADCAST &&
3917 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3918 throw new IllegalArgumentException(
3919 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3920 }
3921 intents[i] = new Intent(intent);
3922 }
3923 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003924 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003925 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003926 }
3927 }
3928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 synchronized(this) {
3930 int callingUid = Binder.getCallingUid();
3931 try {
3932 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3933 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003934 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 .getPackageUid(packageName);
3936 if (uid != Binder.getCallingUid()) {
3937 String msg = "Permission Denial: getIntentSender() from pid="
3938 + Binder.getCallingPid()
3939 + ", uid=" + Binder.getCallingUid()
3940 + ", (need uid=" + uid + ")"
3941 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003942 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 throw new SecurityException(msg);
3944 }
3945 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003946
3947 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003948 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 } catch (RemoteException e) {
3951 throw new SecurityException(e);
3952 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003953 }
3954 }
3955
3956 IIntentSender getIntentSenderLocked(int type,
3957 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003958 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003959 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003960 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003961 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003962 if (index < 0) {
3963 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003965 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003966 if (activity.finishing) {
3967 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003969 }
3970
3971 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3972 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3973 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3974 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3975 |PendingIntent.FLAG_UPDATE_CURRENT);
3976
3977 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3978 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003979 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003980 WeakReference<PendingIntentRecord> ref;
3981 ref = mIntentSenderRecords.get(key);
3982 PendingIntentRecord rec = ref != null ? ref.get() : null;
3983 if (rec != null) {
3984 if (!cancelCurrent) {
3985 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003986 if (rec.key.requestIntent != null) {
3987 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3988 }
3989 if (intents != null) {
3990 intents[intents.length-1] = rec.key.requestIntent;
3991 rec.key.allIntents = intents;
3992 rec.key.allResolvedTypes = resolvedTypes;
3993 } else {
3994 rec.key.allIntents = null;
3995 rec.key.allResolvedTypes = null;
3996 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 return rec;
3999 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004000 rec.canceled = true;
4001 mIntentSenderRecords.remove(key);
4002 }
4003 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 return rec;
4005 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004006 rec = new PendingIntentRecord(this, key, callingUid);
4007 mIntentSenderRecords.put(key, rec.ref);
4008 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4009 if (activity.pendingResults == null) {
4010 activity.pendingResults
4011 = new HashSet<WeakReference<PendingIntentRecord>>();
4012 }
4013 activity.pendingResults.add(rec.ref);
4014 }
4015 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 }
4017
4018 public void cancelIntentSender(IIntentSender sender) {
4019 if (!(sender instanceof PendingIntentRecord)) {
4020 return;
4021 }
4022 synchronized(this) {
4023 PendingIntentRecord rec = (PendingIntentRecord)sender;
4024 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004025 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004026 .getPackageUid(rec.key.packageName);
4027 if (uid != Binder.getCallingUid()) {
4028 String msg = "Permission Denial: cancelIntentSender() from pid="
4029 + Binder.getCallingPid()
4030 + ", uid=" + Binder.getCallingUid()
4031 + " is not allowed to cancel packges "
4032 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004033 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 throw new SecurityException(msg);
4035 }
4036 } catch (RemoteException e) {
4037 throw new SecurityException(e);
4038 }
4039 cancelIntentSenderLocked(rec, true);
4040 }
4041 }
4042
4043 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4044 rec.canceled = true;
4045 mIntentSenderRecords.remove(rec.key);
4046 if (cleanActivity && rec.key.activity != null) {
4047 rec.key.activity.pendingResults.remove(rec.ref);
4048 }
4049 }
4050
4051 public String getPackageForIntentSender(IIntentSender pendingResult) {
4052 if (!(pendingResult instanceof PendingIntentRecord)) {
4053 return null;
4054 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004055 try {
4056 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4057 return res.key.packageName;
4058 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 }
4060 return null;
4061 }
4062
4063 public void setProcessLimit(int max) {
4064 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4065 "setProcessLimit()");
4066 mProcessLimit = max;
4067 }
4068
4069 public int getProcessLimit() {
4070 return mProcessLimit;
4071 }
4072
4073 void foregroundTokenDied(ForegroundToken token) {
4074 synchronized (ActivityManagerService.this) {
4075 synchronized (mPidsSelfLocked) {
4076 ForegroundToken cur
4077 = mForegroundProcesses.get(token.pid);
4078 if (cur != token) {
4079 return;
4080 }
4081 mForegroundProcesses.remove(token.pid);
4082 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4083 if (pr == null) {
4084 return;
4085 }
4086 pr.forcingToForeground = null;
4087 pr.foregroundServices = false;
4088 }
4089 updateOomAdjLocked();
4090 }
4091 }
4092
4093 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4094 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4095 "setProcessForeground()");
4096 synchronized(this) {
4097 boolean changed = false;
4098
4099 synchronized (mPidsSelfLocked) {
4100 ProcessRecord pr = mPidsSelfLocked.get(pid);
4101 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004102 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 return;
4104 }
4105 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4106 if (oldToken != null) {
4107 oldToken.token.unlinkToDeath(oldToken, 0);
4108 mForegroundProcesses.remove(pid);
4109 pr.forcingToForeground = null;
4110 changed = true;
4111 }
4112 if (isForeground && token != null) {
4113 ForegroundToken newToken = new ForegroundToken() {
4114 public void binderDied() {
4115 foregroundTokenDied(this);
4116 }
4117 };
4118 newToken.pid = pid;
4119 newToken.token = token;
4120 try {
4121 token.linkToDeath(newToken, 0);
4122 mForegroundProcesses.put(pid, newToken);
4123 pr.forcingToForeground = token;
4124 changed = true;
4125 } catch (RemoteException e) {
4126 // If the process died while doing this, we will later
4127 // do the cleanup with the process death link.
4128 }
4129 }
4130 }
4131
4132 if (changed) {
4133 updateOomAdjLocked();
4134 }
4135 }
4136 }
4137
4138 // =========================================================
4139 // PERMISSIONS
4140 // =========================================================
4141
4142 static class PermissionController extends IPermissionController.Stub {
4143 ActivityManagerService mActivityManagerService;
4144 PermissionController(ActivityManagerService activityManagerService) {
4145 mActivityManagerService = activityManagerService;
4146 }
4147
4148 public boolean checkPermission(String permission, int pid, int uid) {
4149 return mActivityManagerService.checkPermission(permission, pid,
4150 uid) == PackageManager.PERMISSION_GRANTED;
4151 }
4152 }
4153
4154 /**
4155 * This can be called with or without the global lock held.
4156 */
4157 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004158 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 // We might be performing an operation on behalf of an indirect binder
4160 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4161 // client identity accordingly before proceeding.
4162 Identity tlsIdentity = sCallerIdentity.get();
4163 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004164 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4166 uid = tlsIdentity.uid;
4167 pid = tlsIdentity.pid;
4168 }
4169
4170 // Root, system server and our own process get to do everything.
4171 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4172 !Process.supportsProcesses()) {
4173 return PackageManager.PERMISSION_GRANTED;
4174 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004175 // If there is a uid that owns whatever is being accessed, it has
4176 // blanket access to it regardless of the permissions it requires.
4177 if (owningUid >= 0 && uid == owningUid) {
4178 return PackageManager.PERMISSION_GRANTED;
4179 }
4180 // If the target is not exported, then nobody else can get to it.
4181 if (!exported) {
4182 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 return PackageManager.PERMISSION_DENIED;
4184 }
4185 if (permission == null) {
4186 return PackageManager.PERMISSION_GRANTED;
4187 }
4188 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004189 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 .checkUidPermission(permission, uid);
4191 } catch (RemoteException e) {
4192 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004193 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 }
4195 return PackageManager.PERMISSION_DENIED;
4196 }
4197
4198 /**
4199 * As the only public entry point for permissions checking, this method
4200 * can enforce the semantic that requesting a check on a null global
4201 * permission is automatically denied. (Internally a null permission
4202 * string is used when calling {@link #checkComponentPermission} in cases
4203 * when only uid-based security is needed.)
4204 *
4205 * This can be called with or without the global lock held.
4206 */
4207 public int checkPermission(String permission, int pid, int uid) {
4208 if (permission == null) {
4209 return PackageManager.PERMISSION_DENIED;
4210 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004211 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 }
4213
4214 /**
4215 * Binder IPC calls go through the public entry point.
4216 * This can be called with or without the global lock held.
4217 */
4218 int checkCallingPermission(String permission) {
4219 return checkPermission(permission,
4220 Binder.getCallingPid(),
4221 Binder.getCallingUid());
4222 }
4223
4224 /**
4225 * This can be called with or without the global lock held.
4226 */
4227 void enforceCallingPermission(String permission, String func) {
4228 if (checkCallingPermission(permission)
4229 == PackageManager.PERMISSION_GRANTED) {
4230 return;
4231 }
4232
4233 String msg = "Permission Denial: " + func + " from pid="
4234 + Binder.getCallingPid()
4235 + ", uid=" + Binder.getCallingUid()
4236 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004237 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 throw new SecurityException(msg);
4239 }
4240
4241 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004242 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4243 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4244 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4245 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4246 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004248 // Is the component private from the target uid?
4249 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4250
4251 // Acceptable if the there is no read permission needed from the
4252 // target or the target is holding the read permission.
4253 if (!readPerm) {
4254 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004256 == PackageManager.PERMISSION_GRANTED)) {
4257 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 }
4259 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004260
4261 // Acceptable if the there is no write permission needed from the
4262 // target or the target is holding the read permission.
4263 if (!writePerm) {
4264 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004266 == PackageManager.PERMISSION_GRANTED)) {
4267 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 }
4269 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004270
4271 // Acceptable if there is a path permission matching the URI that
4272 // the target holds the permission on.
4273 PathPermission[] pps = pi.pathPermissions;
4274 if (pps != null && (!readPerm || !writePerm)) {
4275 final String path = uri.getPath();
4276 int i = pps.length;
4277 while (i > 0 && (!readPerm || !writePerm)) {
4278 i--;
4279 PathPermission pp = pps[i];
4280 if (!readPerm) {
4281 final String pprperm = pp.getReadPermission();
4282 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4283 + pprperm + " for " + pp.getPath()
4284 + ": match=" + pp.match(path)
4285 + " check=" + pm.checkUidPermission(pprperm, uid));
4286 if (pprperm != null && pp.match(path) &&
4287 (pm.checkUidPermission(pprperm, uid)
4288 == PackageManager.PERMISSION_GRANTED)) {
4289 readPerm = true;
4290 }
4291 }
4292 if (!writePerm) {
4293 final String ppwperm = pp.getWritePermission();
4294 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4295 + ppwperm + " for " + pp.getPath()
4296 + ": match=" + pp.match(path)
4297 + " check=" + pm.checkUidPermission(ppwperm, uid));
4298 if (ppwperm != null && pp.match(path) &&
4299 (pm.checkUidPermission(ppwperm, uid)
4300 == PackageManager.PERMISSION_GRANTED)) {
4301 writePerm = true;
4302 }
4303 }
4304 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 } catch (RemoteException e) {
4307 return false;
4308 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004309
4310 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 }
4312
4313 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4314 int modeFlags) {
4315 // Root gets to do everything.
4316 if (uid == 0 || !Process.supportsProcesses()) {
4317 return true;
4318 }
4319 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4320 if (perms == null) return false;
4321 UriPermission perm = perms.get(uri);
4322 if (perm == null) return false;
4323 return (modeFlags&perm.modeFlags) == modeFlags;
4324 }
4325
4326 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4327 // Another redirected-binder-call permissions check as in
4328 // {@link checkComponentPermission}.
4329 Identity tlsIdentity = sCallerIdentity.get();
4330 if (tlsIdentity != null) {
4331 uid = tlsIdentity.uid;
4332 pid = tlsIdentity.pid;
4333 }
4334
4335 // Our own process gets to do everything.
4336 if (pid == MY_PID) {
4337 return PackageManager.PERMISSION_GRANTED;
4338 }
4339 synchronized(this) {
4340 return checkUriPermissionLocked(uri, uid, modeFlags)
4341 ? PackageManager.PERMISSION_GRANTED
4342 : PackageManager.PERMISSION_DENIED;
4343 }
4344 }
4345
Dianne Hackborn39792d22010-08-19 18:01:52 -07004346 /**
4347 * Check if the targetPkg can be granted permission to access uri by
4348 * the callingUid using the given modeFlags. Throws a security exception
4349 * if callingUid is not allowed to do this. Returns the uid of the target
4350 * if the URI permission grant should be performed; returns -1 if it is not
4351 * needed (for example targetPkg already has permission to access the URI).
4352 */
4353 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4354 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4356 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4357 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004358 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 }
4360
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004361 if (targetPkg != null) {
4362 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4363 "Checking grant " + targetPkg + " permission to " + uri);
4364 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004365
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004366 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367
4368 // If this is not a content: uri, we can't do anything with it.
4369 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004370 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004371 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004372 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 }
4374
4375 String name = uri.getAuthority();
4376 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004377 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 if (cpr != null) {
4379 pi = cpr.info;
4380 } else {
4381 try {
4382 pi = pm.resolveContentProvider(name,
4383 PackageManager.GET_URI_PERMISSION_PATTERNS);
4384 } catch (RemoteException ex) {
4385 }
4386 }
4387 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004388 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004389 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 }
4391
4392 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004393 if (targetPkg != null) {
4394 try {
4395 targetUid = pm.getPackageUid(targetPkg);
4396 if (targetUid < 0) {
4397 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4398 "Can't grant URI permission no uid for: " + targetPkg);
4399 return -1;
4400 }
4401 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004402 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004404 } else {
4405 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004408 if (targetUid >= 0) {
4409 // First... does the target actually need this permission?
4410 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4411 // No need to grant the target this permission.
4412 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4413 "Target " + targetPkg + " already has full permission to " + uri);
4414 return -1;
4415 }
4416 } else {
4417 // First... there is no target package, so can anyone access it?
4418 boolean allowed = pi.exported;
4419 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4420 if (pi.readPermission != null) {
4421 allowed = false;
4422 }
4423 }
4424 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4425 if (pi.writePermission != null) {
4426 allowed = false;
4427 }
4428 }
4429 if (allowed) {
4430 return -1;
4431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 }
4433
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004434 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 if (!pi.grantUriPermissions) {
4436 throw new SecurityException("Provider " + pi.packageName
4437 + "/" + pi.name
4438 + " does not allow granting of Uri permissions (uri "
4439 + uri + ")");
4440 }
4441 if (pi.uriPermissionPatterns != null) {
4442 final int N = pi.uriPermissionPatterns.length;
4443 boolean allowed = false;
4444 for (int i=0; i<N; i++) {
4445 if (pi.uriPermissionPatterns[i] != null
4446 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4447 allowed = true;
4448 break;
4449 }
4450 }
4451 if (!allowed) {
4452 throw new SecurityException("Provider " + pi.packageName
4453 + "/" + pi.name
4454 + " does not allow granting of permission to path of Uri "
4455 + uri);
4456 }
4457 }
4458
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004459 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004461 if (callingUid != Process.myUid()) {
4462 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4463 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4464 throw new SecurityException("Uid " + callingUid
4465 + " does not have permission to uri " + uri);
4466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 }
4468 }
4469
Dianne Hackborn39792d22010-08-19 18:01:52 -07004470 return targetUid;
4471 }
4472
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004473 public int checkGrantUriPermission(int callingUid, String targetPkg,
4474 Uri uri, int modeFlags) {
4475 synchronized(this) {
4476 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4477 }
4478 }
4479
Dianne Hackborn39792d22010-08-19 18:01:52 -07004480 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4481 Uri uri, int modeFlags, UriPermissionOwner owner) {
4482 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4483 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4484 if (modeFlags == 0) {
4485 return;
4486 }
4487
4488 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 // to the uri, and the target doesn't. Let's now give this to
4490 // the target.
4491
Joe Onorato8a9b2202010-02-26 18:56:32 -08004492 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004493 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 HashMap<Uri, UriPermission> targetUris
4496 = mGrantedUriPermissions.get(targetUid);
4497 if (targetUris == null) {
4498 targetUris = new HashMap<Uri, UriPermission>();
4499 mGrantedUriPermissions.put(targetUid, targetUris);
4500 }
4501
4502 UriPermission perm = targetUris.get(uri);
4503 if (perm == null) {
4504 perm = new UriPermission(targetUid, uri);
4505 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004509 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004511 } else {
4512 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4513 perm.readOwners.add(owner);
4514 owner.addReadPermission(perm);
4515 }
4516 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4517 perm.writeOwners.add(owner);
4518 owner.addWritePermission(perm);
4519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 }
4521 }
4522
Dianne Hackborn39792d22010-08-19 18:01:52 -07004523 void grantUriPermissionLocked(int callingUid,
4524 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004525 if (targetPkg == null) {
4526 throw new NullPointerException("targetPkg");
4527 }
4528
Dianne Hackborn39792d22010-08-19 18:01:52 -07004529 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4530 if (targetUid < 0) {
4531 return;
4532 }
4533
4534 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4535 }
4536
4537 /**
4538 * Like checkGrantUriPermissionLocked, but takes an Intent.
4539 */
4540 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4541 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004542 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004543 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004544 + " from " + intent + "; flags=0x"
4545 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4546
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004547 if (targetPkg == null) {
4548 throw new NullPointerException("targetPkg");
4549 }
4550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004552 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004553 }
4554 Uri data = intent.getData();
4555 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004556 return -1;
4557 }
4558 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4559 intent.getFlags());
4560 }
4561
4562 /**
4563 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4564 */
4565 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4566 String targetPkg, Intent intent, UriPermissionOwner owner) {
4567 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4568 intent.getFlags(), owner);
4569 }
4570
4571 void grantUriPermissionFromIntentLocked(int callingUid,
4572 String targetPkg, Intent intent, UriPermissionOwner owner) {
4573 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4574 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 return;
4576 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004577
4578 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580
4581 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4582 Uri uri, int modeFlags) {
4583 synchronized(this) {
4584 final ProcessRecord r = getRecordForAppLocked(caller);
4585 if (r == null) {
4586 throw new SecurityException("Unable to find app for caller "
4587 + caller
4588 + " when granting permission to uri " + uri);
4589 }
4590 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004591 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 }
4593 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004594 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 }
4596
4597 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4598 null);
4599 }
4600 }
4601
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004602 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4604 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4605 HashMap<Uri, UriPermission> perms
4606 = mGrantedUriPermissions.get(perm.uid);
4607 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004608 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004609 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 perms.remove(perm.uri);
4611 if (perms.size() == 0) {
4612 mGrantedUriPermissions.remove(perm.uid);
4613 }
4614 }
4615 }
4616 }
4617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4619 int modeFlags) {
4620 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4621 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4622 if (modeFlags == 0) {
4623 return;
4624 }
4625
Joe Onorato8a9b2202010-02-26 18:56:32 -08004626 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004627 "Revoking all granted permissions to " + uri);
4628
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004629 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630
4631 final String authority = uri.getAuthority();
4632 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004633 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 if (cpr != null) {
4635 pi = cpr.info;
4636 } else {
4637 try {
4638 pi = pm.resolveContentProvider(authority,
4639 PackageManager.GET_URI_PERMISSION_PATTERNS);
4640 } catch (RemoteException ex) {
4641 }
4642 }
4643 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004644 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 return;
4646 }
4647
4648 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004649 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 // Right now, if you are not the original owner of the permission,
4651 // you are not allowed to revoke it.
4652 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4653 throw new SecurityException("Uid " + callingUid
4654 + " does not have permission to uri " + uri);
4655 //}
4656 }
4657
4658 // Go through all of the permissions and remove any that match.
4659 final List<String> SEGMENTS = uri.getPathSegments();
4660 if (SEGMENTS != null) {
4661 final int NS = SEGMENTS.size();
4662 int N = mGrantedUriPermissions.size();
4663 for (int i=0; i<N; i++) {
4664 HashMap<Uri, UriPermission> perms
4665 = mGrantedUriPermissions.valueAt(i);
4666 Iterator<UriPermission> it = perms.values().iterator();
4667 toploop:
4668 while (it.hasNext()) {
4669 UriPermission perm = it.next();
4670 Uri targetUri = perm.uri;
4671 if (!authority.equals(targetUri.getAuthority())) {
4672 continue;
4673 }
4674 List<String> targetSegments = targetUri.getPathSegments();
4675 if (targetSegments == null) {
4676 continue;
4677 }
4678 if (targetSegments.size() < NS) {
4679 continue;
4680 }
4681 for (int j=0; j<NS; j++) {
4682 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4683 continue toploop;
4684 }
4685 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004686 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004687 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 perm.clearModes(modeFlags);
4689 if (perm.modeFlags == 0) {
4690 it.remove();
4691 }
4692 }
4693 if (perms.size() == 0) {
4694 mGrantedUriPermissions.remove(
4695 mGrantedUriPermissions.keyAt(i));
4696 N--;
4697 i--;
4698 }
4699 }
4700 }
4701 }
4702
4703 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4704 int modeFlags) {
4705 synchronized(this) {
4706 final ProcessRecord r = getRecordForAppLocked(caller);
4707 if (r == null) {
4708 throw new SecurityException("Unable to find app for caller "
4709 + caller
4710 + " when revoking permission to uri " + uri);
4711 }
4712 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004713 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 return;
4715 }
4716
4717 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4718 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4719 if (modeFlags == 0) {
4720 return;
4721 }
4722
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004723 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724
4725 final String authority = uri.getAuthority();
4726 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004727 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 if (cpr != null) {
4729 pi = cpr.info;
4730 } else {
4731 try {
4732 pi = pm.resolveContentProvider(authority,
4733 PackageManager.GET_URI_PERMISSION_PATTERNS);
4734 } catch (RemoteException ex) {
4735 }
4736 }
4737 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004738 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 return;
4740 }
4741
4742 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4743 }
4744 }
4745
Dianne Hackborn7e269642010-08-25 19:50:20 -07004746 @Override
4747 public IBinder newUriPermissionOwner(String name) {
4748 synchronized(this) {
4749 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4750 return owner.getExternalTokenLocked();
4751 }
4752 }
4753
4754 @Override
4755 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4756 Uri uri, int modeFlags) {
4757 synchronized(this) {
4758 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4759 if (owner == null) {
4760 throw new IllegalArgumentException("Unknown owner: " + token);
4761 }
4762 if (fromUid != Binder.getCallingUid()) {
4763 if (Binder.getCallingUid() != Process.myUid()) {
4764 // Only system code can grant URI permissions on behalf
4765 // of other users.
4766 throw new SecurityException("nice try");
4767 }
4768 }
4769 if (targetPkg == null) {
4770 throw new IllegalArgumentException("null target");
4771 }
4772 if (uri == null) {
4773 throw new IllegalArgumentException("null uri");
4774 }
4775
4776 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4777 }
4778 }
4779
4780 @Override
4781 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4782 synchronized(this) {
4783 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4784 if (owner == null) {
4785 throw new IllegalArgumentException("Unknown owner: " + token);
4786 }
4787
4788 if (uri == null) {
4789 owner.removeUriPermissionsLocked(mode);
4790 } else {
4791 owner.removeUriPermissionLocked(uri, mode);
4792 }
4793 }
4794 }
4795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4797 synchronized (this) {
4798 ProcessRecord app =
4799 who != null ? getRecordForAppLocked(who) : null;
4800 if (app == null) return;
4801
4802 Message msg = Message.obtain();
4803 msg.what = WAIT_FOR_DEBUGGER_MSG;
4804 msg.obj = app;
4805 msg.arg1 = waiting ? 1 : 0;
4806 mHandler.sendMessage(msg);
4807 }
4808 }
4809
4810 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4811 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004812 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004814 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 }
4816
4817 // =========================================================
4818 // TASK MANAGEMENT
4819 // =========================================================
4820
4821 public List getTasks(int maxNum, int flags,
4822 IThumbnailReceiver receiver) {
4823 ArrayList list = new ArrayList();
4824
4825 PendingThumbnailsRecord pending = null;
4826 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004827 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828
4829 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004830 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4832 + ", receiver=" + receiver);
4833
4834 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4835 != PackageManager.PERMISSION_GRANTED) {
4836 if (receiver != null) {
4837 // If the caller wants to wait for pending thumbnails,
4838 // it ain't gonna get them.
4839 try {
4840 receiver.finished();
4841 } catch (RemoteException ex) {
4842 }
4843 }
4844 String msg = "Permission Denial: getTasks() from pid="
4845 + Binder.getCallingPid()
4846 + ", uid=" + Binder.getCallingUid()
4847 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004848 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 throw new SecurityException(msg);
4850 }
4851
Dianne Hackbornd2835932010-12-13 16:28:46 -08004852 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4853 && checkCallingPermission(
4854 android.Manifest.permission.READ_FRAME_BUFFER)
4855 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004856
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004857 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004858 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004859 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004860 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 CharSequence topDescription = null;
4862 TaskRecord curTask = null;
4863 int numActivities = 0;
4864 int numRunning = 0;
4865 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004866 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004868 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869
4870 // Initialize state for next task if needed.
4871 if (top == null ||
4872 (top.state == ActivityState.INITIALIZING
4873 && top.task == r.task)) {
4874 top = r;
4875 topDescription = r.description;
4876 curTask = r.task;
4877 numActivities = numRunning = 0;
4878 }
4879
4880 // Add 'r' into the current task.
4881 numActivities++;
4882 if (r.app != null && r.app.thread != null) {
4883 numRunning++;
4884 }
4885 if (topDescription == null) {
4886 topDescription = r.description;
4887 }
4888
Joe Onorato8a9b2202010-02-26 18:56:32 -08004889 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 TAG, r.intent.getComponent().flattenToShortString()
4891 + ": task=" + r.task);
4892
4893 // If the next one is a different task, generate a new
4894 // TaskInfo entry for what we have.
4895 if (next == null || next.task != curTask) {
4896 ActivityManager.RunningTaskInfo ci
4897 = new ActivityManager.RunningTaskInfo();
4898 ci.id = curTask.taskId;
4899 ci.baseActivity = r.intent.getComponent();
4900 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004901 if (canReadFb) {
4902 if (top.thumbnail != null) {
4903 ci.thumbnail = top.thumbnail;
4904 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004905 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004906 }
4907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 ci.description = topDescription;
4909 ci.numActivities = numActivities;
4910 ci.numRunning = numRunning;
4911 //System.out.println(
4912 // "#" + maxNum + ": " + " descr=" + ci.description);
4913 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004914 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 TAG, "State=" + top.state + "Idle=" + top.idle
4916 + " app=" + top.app
4917 + " thr=" + (top.app != null ? top.app.thread : null));
4918 if (top.state == ActivityState.RESUMED
4919 || top.state == ActivityState.PAUSING) {
4920 if (top.idle && top.app != null
4921 && top.app.thread != null) {
4922 topRecord = top;
4923 topThumbnail = top.app.thread;
4924 } else {
4925 top.thumbnailNeeded = true;
4926 }
4927 }
4928 if (pending == null) {
4929 pending = new PendingThumbnailsRecord(receiver);
4930 }
4931 pending.pendingRecords.add(top);
4932 }
4933 list.add(ci);
4934 maxNum--;
4935 top = null;
4936 }
4937 }
4938
4939 if (pending != null) {
4940 mPendingThumbnails.add(pending);
4941 }
4942 }
4943
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945
4946 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004947 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 try {
4949 topThumbnail.requestThumbnail(topRecord);
4950 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004951 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 sendPendingThumbnail(null, topRecord, null, null, true);
4953 }
4954 }
4955
4956 if (pending == null && receiver != null) {
4957 // In this case all thumbnails were available and the client
4958 // is being asked to be told when the remaining ones come in...
4959 // which is unusually, since the top-most currently running
4960 // activity should never have a canned thumbnail! Oh well.
4961 try {
4962 receiver.finished();
4963 } catch (RemoteException ex) {
4964 }
4965 }
4966
4967 return list;
4968 }
4969
4970 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4971 int flags) {
4972 synchronized (this) {
4973 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4974 "getRecentTasks()");
4975
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004976 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004977
Dianne Hackbornd2835932010-12-13 16:28:46 -08004978 ActivityRecord resumed = mMainStack.mResumedActivity;
4979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 final int N = mRecentTasks.size();
4981 ArrayList<ActivityManager.RecentTaskInfo> res
4982 = new ArrayList<ActivityManager.RecentTaskInfo>(
4983 maxNum < N ? maxNum : N);
4984 for (int i=0; i<N && maxNum > 0; i++) {
4985 TaskRecord tr = mRecentTasks.get(i);
4986 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4987 || (tr.intent == null)
4988 || ((tr.intent.getFlags()
4989 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4990 ActivityManager.RecentTaskInfo rti
4991 = new ActivityManager.RecentTaskInfo();
4992 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004993 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 rti.baseIntent = new Intent(
4995 tr.intent != null ? tr.intent : tr.affinityIntent);
4996 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08004997 rti.description = tr.lastDescription;
4998
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004999 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5000 // Check whether this activity is currently available.
5001 try {
5002 if (rti.origActivity != null) {
5003 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5004 continue;
5005 }
5006 } else if (rti.baseIntent != null) {
5007 if (pm.queryIntentActivities(rti.baseIntent,
5008 null, 0) == null) {
5009 continue;
5010 }
5011 }
5012 } catch (RemoteException e) {
5013 // Will never happen.
5014 }
5015 }
5016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 res.add(rti);
5018 maxNum--;
5019 }
5020 }
5021 return res;
5022 }
5023 }
5024
Dianne Hackbornd94df452011-02-16 18:53:31 -08005025 public Bitmap getTaskThumbnail(int id) {
5026 synchronized (this) {
5027 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5028 "getTaskThumbnail()");
5029 ActivityRecord resumed = mMainStack.mResumedActivity;
5030 final int N = mRecentTasks.size();
5031 for (int i=0; i<N; i++) {
5032 TaskRecord tr = mRecentTasks.get(i);
5033 if (tr.taskId == id) {
5034 if (resumed != null && resumed.task == tr) {
5035 return resumed.stack.screenshotActivities(resumed);
5036 } else {
5037 return tr.lastThumbnail;
5038 }
5039 }
5040 }
5041 }
5042 return null;
5043 }
5044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005045 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5046 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005047 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 TaskRecord jt = startTask;
5049
5050 // First look backwards
5051 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005052 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 if (r.task != jt) {
5054 jt = r.task;
5055 if (affinity.equals(jt.affinity)) {
5056 return j;
5057 }
5058 }
5059 }
5060
5061 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005062 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 jt = startTask;
5064 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005065 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 if (r.task != jt) {
5067 if (affinity.equals(jt.affinity)) {
5068 return j;
5069 }
5070 jt = r.task;
5071 }
5072 }
5073
5074 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005075 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 return N-1;
5077 }
5078
5079 return -1;
5080 }
5081
5082 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005083 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005085 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5087 "moveTaskToFront()");
5088
5089 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005090 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5091 Binder.getCallingUid(), "Task to front")) {
5092 return;
5093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 final long origId = Binder.clearCallingIdentity();
5095 try {
5096 int N = mRecentTasks.size();
5097 for (int i=0; i<N; i++) {
5098 TaskRecord tr = mRecentTasks.get(i);
5099 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005100 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5101 mMainStack.mUserLeaving = true;
5102 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005103 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5104 // Caller wants the home activity moved with it. To accomplish this,
5105 // we'll just move the home task to the top first.
5106 mMainStack.moveHomeToFrontLocked();
5107 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005108 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 return;
5110 }
5111 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005112 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5113 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005115 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5116 mMainStack.mUserLeaving = true;
5117 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005118 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5119 // Caller wants the home activity moved with it. To accomplish this,
5120 // we'll just move the home task to the top first.
5121 mMainStack.moveHomeToFrontLocked();
5122 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005123 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 return;
5125 }
5126 }
5127 } finally {
5128 Binder.restoreCallingIdentity(origId);
5129 }
5130 }
5131 }
5132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 public void moveTaskToBack(int task) {
5134 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5135 "moveTaskToBack()");
5136
5137 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005138 if (mMainStack.mResumedActivity != null
5139 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005140 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5141 Binder.getCallingUid(), "Task to back")) {
5142 return;
5143 }
5144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005146 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 Binder.restoreCallingIdentity(origId);
5148 }
5149 }
5150
5151 /**
5152 * Moves an activity, and all of the other activities within the same task, to the bottom
5153 * of the history stack. The activity's order within the task is unchanged.
5154 *
5155 * @param token A reference to the activity we wish to move
5156 * @param nonRoot If false then this only works if the activity is the root
5157 * of a task; if true it will work for any activity in a task.
5158 * @return Returns true if the move completed, false if not.
5159 */
5160 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5161 synchronized(this) {
5162 final long origId = Binder.clearCallingIdentity();
5163 int taskId = getTaskForActivityLocked(token, !nonRoot);
5164 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005165 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 }
5167 Binder.restoreCallingIdentity(origId);
5168 }
5169 return false;
5170 }
5171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 public void moveTaskBackwards(int task) {
5173 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5174 "moveTaskBackwards()");
5175
5176 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005177 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5178 Binder.getCallingUid(), "Task backwards")) {
5179 return;
5180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 final long origId = Binder.clearCallingIdentity();
5182 moveTaskBackwardsLocked(task);
5183 Binder.restoreCallingIdentity(origId);
5184 }
5185 }
5186
5187 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005188 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 }
5190
5191 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5192 synchronized(this) {
5193 return getTaskForActivityLocked(token, onlyRoot);
5194 }
5195 }
5196
5197 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005198 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 TaskRecord lastTask = null;
5200 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005201 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 if (r == token) {
5203 if (!onlyRoot || lastTask != r.task) {
5204 return r.task.taskId;
5205 }
5206 return -1;
5207 }
5208 lastTask = r.task;
5209 }
5210
5211 return -1;
5212 }
5213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 public void finishOtherInstances(IBinder token, ComponentName className) {
5215 synchronized(this) {
5216 final long origId = Binder.clearCallingIdentity();
5217
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005218 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 TaskRecord lastTask = null;
5220 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005221 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 if (r.realActivity.equals(className)
5223 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005224 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 null, "others")) {
5226 i--;
5227 N--;
5228 }
5229 }
5230 lastTask = r.task;
5231 }
5232
5233 Binder.restoreCallingIdentity(origId);
5234 }
5235 }
5236
5237 // =========================================================
5238 // THUMBNAILS
5239 // =========================================================
5240
5241 public void reportThumbnail(IBinder token,
5242 Bitmap thumbnail, CharSequence description) {
5243 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5244 final long origId = Binder.clearCallingIdentity();
5245 sendPendingThumbnail(null, token, thumbnail, description, true);
5246 Binder.restoreCallingIdentity(origId);
5247 }
5248
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005249 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 Bitmap thumbnail, CharSequence description, boolean always) {
5251 TaskRecord task = null;
5252 ArrayList receivers = null;
5253
5254 //System.out.println("Send pending thumbnail: " + r);
5255
5256 synchronized(this) {
5257 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005258 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 if (index < 0) {
5260 return;
5261 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005262 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 }
5264 if (thumbnail == null) {
5265 thumbnail = r.thumbnail;
5266 description = r.description;
5267 }
5268 if (thumbnail == null && !always) {
5269 // If there is no thumbnail, and this entry is not actually
5270 // going away, then abort for now and pick up the next
5271 // thumbnail we get.
5272 return;
5273 }
5274 task = r.task;
5275
5276 int N = mPendingThumbnails.size();
5277 int i=0;
5278 while (i<N) {
5279 PendingThumbnailsRecord pr =
5280 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5281 //System.out.println("Looking in " + pr.pendingRecords);
5282 if (pr.pendingRecords.remove(r)) {
5283 if (receivers == null) {
5284 receivers = new ArrayList();
5285 }
5286 receivers.add(pr);
5287 if (pr.pendingRecords.size() == 0) {
5288 pr.finished = true;
5289 mPendingThumbnails.remove(i);
5290 N--;
5291 continue;
5292 }
5293 }
5294 i++;
5295 }
5296 }
5297
5298 if (receivers != null) {
5299 final int N = receivers.size();
5300 for (int i=0; i<N; i++) {
5301 try {
5302 PendingThumbnailsRecord pr =
5303 (PendingThumbnailsRecord)receivers.get(i);
5304 pr.receiver.newThumbnail(
5305 task != null ? task.taskId : -1, thumbnail, description);
5306 if (pr.finished) {
5307 pr.receiver.finished();
5308 }
5309 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005310 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 }
5312 }
5313 }
5314 }
5315
5316 // =========================================================
5317 // CONTENT PROVIDERS
5318 // =========================================================
5319
5320 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5321 List providers = null;
5322 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005323 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005325 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 } catch (RemoteException ex) {
5327 }
5328 if (providers != null) {
5329 final int N = providers.size();
5330 for (int i=0; i<N; i++) {
5331 ProviderInfo cpi =
5332 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005333 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 if (cpr == null) {
5335 cpr = new ContentProviderRecord(cpi, app.info);
5336 mProvidersByClass.put(cpi.name, cpr);
5337 }
5338 app.pubProviders.put(cpi.name, cpr);
5339 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005340 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 }
5342 }
5343 return providers;
5344 }
5345
5346 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005347 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5349 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5350 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005351 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005352 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 return null;
5354 }
5355 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005356 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 == PackageManager.PERMISSION_GRANTED) {
5358 return null;
5359 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005360
5361 PathPermission[] pps = cpi.pathPermissions;
5362 if (pps != null) {
5363 int i = pps.length;
5364 while (i > 0) {
5365 i--;
5366 PathPermission pp = pps[i];
5367 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005368 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005369 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005370 return null;
5371 }
5372 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005373 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005374 == PackageManager.PERMISSION_GRANTED) {
5375 return null;
5376 }
5377 }
5378 }
5379
Dianne Hackbornb424b632010-08-18 15:59:05 -07005380 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5381 if (perms != null) {
5382 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5383 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5384 return null;
5385 }
5386 }
5387 }
5388
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005389 String msg;
5390 if (!cpi.exported) {
5391 msg = "Permission Denial: opening provider " + cpi.name
5392 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5393 + ", uid=" + callingUid + ") that is not exported from uid "
5394 + cpi.applicationInfo.uid;
5395 } else {
5396 msg = "Permission Denial: opening provider " + cpi.name
5397 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5398 + ", uid=" + callingUid + ") requires "
5399 + cpi.readPermission + " or " + cpi.writePermission;
5400 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005401 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 return msg;
5403 }
5404
5405 private final ContentProviderHolder getContentProviderImpl(
5406 IApplicationThread caller, String name) {
5407 ContentProviderRecord cpr;
5408 ProviderInfo cpi = null;
5409
5410 synchronized(this) {
5411 ProcessRecord r = null;
5412 if (caller != null) {
5413 r = getRecordForAppLocked(caller);
5414 if (r == null) {
5415 throw new SecurityException(
5416 "Unable to find app for caller " + caller
5417 + " (pid=" + Binder.getCallingPid()
5418 + ") when getting content provider " + name);
5419 }
5420 }
5421
5422 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005423 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 if (cpr != null) {
5425 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005426 String msg;
5427 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5428 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 }
5430
5431 if (r != null && cpr.canRunHere(r)) {
5432 // This provider has been published or is in the process
5433 // of being published... but it is also allowed to run
5434 // in the caller's process, so don't make a connection
5435 // and just let the caller instantiate its own instance.
5436 if (cpr.provider != null) {
5437 // don't give caller the provider object, it needs
5438 // to make its own.
5439 cpr = new ContentProviderRecord(cpr);
5440 }
5441 return cpr;
5442 }
5443
5444 final long origId = Binder.clearCallingIdentity();
5445
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005446 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 // return it right away.
5448 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005449 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005450 "Adding provider requested by "
5451 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005452 + cpr.info.processName);
5453 Integer cnt = r.conProviders.get(cpr);
5454 if (cnt == null) {
5455 r.conProviders.put(cpr, new Integer(1));
5456 } else {
5457 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005460 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5461 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005462 // make sure to count it as being accessed and thus
5463 // back up on the LRU list. This is good because
5464 // content providers are often expensive to start.
5465 updateLruProcessLocked(cpr.app, false, true);
5466 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005467 } else {
5468 cpr.externals++;
5469 }
5470
5471 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 updateOomAdjLocked(cpr.app);
5473 }
5474
5475 Binder.restoreCallingIdentity(origId);
5476
5477 } else {
5478 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005479 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005480 resolveContentProvider(name,
5481 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 } catch (RemoteException ex) {
5483 }
5484 if (cpi == null) {
5485 return null;
5486 }
5487
Dianne Hackbornb424b632010-08-18 15:59:05 -07005488 String msg;
5489 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5490 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 }
5492
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005493 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005494 && !cpi.processName.equals("system")) {
5495 // If this content provider does not run in the system
5496 // process, and the system is not yet ready to run other
5497 // processes, then fail fast instead of hanging.
5498 throw new IllegalArgumentException(
5499 "Attempt to launch content provider before system ready");
5500 }
5501
Dianne Hackborn860755f2010-06-03 18:47:52 -07005502 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005503 final boolean firstClass = cpr == null;
5504 if (firstClass) {
5505 try {
5506 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005507 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 getApplicationInfo(
5509 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005510 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005512 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 + cpi.name);
5514 return null;
5515 }
5516 cpr = new ContentProviderRecord(cpi, ai);
5517 } catch (RemoteException ex) {
5518 // pm is in same process, this will never happen.
5519 }
5520 }
5521
5522 if (r != null && cpr.canRunHere(r)) {
5523 // If this is a multiprocess provider, then just return its
5524 // info and allow the caller to instantiate it. Only do
5525 // this if the provider is the same user as the caller's
5526 // process, or can run as root (so can be in any process).
5527 return cpr;
5528 }
5529
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005530 if (DEBUG_PROVIDER) {
5531 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005532 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005533 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 }
5535
5536 // This is single process, and our app is now connecting to it.
5537 // See if we are already in the process of launching this
5538 // provider.
5539 final int N = mLaunchingProviders.size();
5540 int i;
5541 for (i=0; i<N; i++) {
5542 if (mLaunchingProviders.get(i) == cpr) {
5543 break;
5544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005545 }
5546
5547 // If the provider is not already being launched, then get it
5548 // started.
5549 if (i >= N) {
5550 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005551
5552 try {
5553 // Content provider is now in use, its package can't be stopped.
5554 try {
5555 AppGlobals.getPackageManager().setPackageStoppedState(
5556 cpr.appInfo.packageName, false);
5557 } catch (RemoteException e) {
5558 }
5559
5560 ProcessRecord proc = startProcessLocked(cpi.processName,
5561 cpr.appInfo, false, 0, "content provider",
5562 new ComponentName(cpi.applicationInfo.packageName,
5563 cpi.name), false);
5564 if (proc == null) {
5565 Slog.w(TAG, "Unable to launch app "
5566 + cpi.applicationInfo.packageName + "/"
5567 + cpi.applicationInfo.uid + " for provider "
5568 + name + ": process is bad");
5569 return null;
5570 }
5571 cpr.launchingApp = proc;
5572 mLaunchingProviders.add(cpr);
5573 } finally {
5574 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 }
5577
5578 // Make sure the provider is published (the same provider class
5579 // may be published under multiple names).
5580 if (firstClass) {
5581 mProvidersByClass.put(cpi.name, cpr);
5582 }
5583 mProvidersByName.put(name, cpr);
5584
5585 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005586 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005587 "Adding provider requested by "
5588 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005589 + cpr.info.processName);
5590 Integer cnt = r.conProviders.get(cpr);
5591 if (cnt == null) {
5592 r.conProviders.put(cpr, new Integer(1));
5593 } else {
5594 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 cpr.clients.add(r);
5597 } else {
5598 cpr.externals++;
5599 }
5600 }
5601 }
5602
5603 // Wait for the provider to be published...
5604 synchronized (cpr) {
5605 while (cpr.provider == null) {
5606 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005607 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 + cpi.applicationInfo.packageName + "/"
5609 + cpi.applicationInfo.uid + " for provider "
5610 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005611 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 cpi.applicationInfo.packageName,
5613 cpi.applicationInfo.uid, name);
5614 return null;
5615 }
5616 try {
5617 cpr.wait();
5618 } catch (InterruptedException ex) {
5619 }
5620 }
5621 }
5622 return cpr;
5623 }
5624
5625 public final ContentProviderHolder getContentProvider(
5626 IApplicationThread caller, String name) {
5627 if (caller == null) {
5628 String msg = "null IApplicationThread when getting content provider "
5629 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005630 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 throw new SecurityException(msg);
5632 }
5633
5634 return getContentProviderImpl(caller, name);
5635 }
5636
5637 private ContentProviderHolder getContentProviderExternal(String name) {
5638 return getContentProviderImpl(null, name);
5639 }
5640
5641 /**
5642 * Drop a content provider from a ProcessRecord's bookkeeping
5643 * @param cpr
5644 */
5645 public void removeContentProvider(IApplicationThread caller, String name) {
5646 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005647 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005649 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005650 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005651 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 return;
5653 }
5654 final ProcessRecord r = getRecordForAppLocked(caller);
5655 if (r == null) {
5656 throw new SecurityException(
5657 "Unable to find app for caller " + caller +
5658 " when removing content provider " + name);
5659 }
5660 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005661 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005662 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005663 + r.info.processName + " from process "
5664 + localCpr.appInfo.processName);
5665 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005667 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005668 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 return;
5670 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005671 Integer cnt = r.conProviders.get(localCpr);
5672 if (cnt == null || cnt.intValue() <= 1) {
5673 localCpr.clients.remove(r);
5674 r.conProviders.remove(localCpr);
5675 } else {
5676 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 }
5679 updateOomAdjLocked();
5680 }
5681 }
5682
5683 private void removeContentProviderExternal(String name) {
5684 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005685 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 if(cpr == null) {
5687 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005688 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 return;
5690 }
5691
5692 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005693 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 localCpr.externals--;
5695 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005696 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 }
5698 updateOomAdjLocked();
5699 }
5700 }
5701
5702 public final void publishContentProviders(IApplicationThread caller,
5703 List<ContentProviderHolder> providers) {
5704 if (providers == null) {
5705 return;
5706 }
5707
5708 synchronized(this) {
5709 final ProcessRecord r = getRecordForAppLocked(caller);
5710 if (r == null) {
5711 throw new SecurityException(
5712 "Unable to find app for caller " + caller
5713 + " (pid=" + Binder.getCallingPid()
5714 + ") when publishing content providers");
5715 }
5716
5717 final long origId = Binder.clearCallingIdentity();
5718
5719 final int N = providers.size();
5720 for (int i=0; i<N; i++) {
5721 ContentProviderHolder src = providers.get(i);
5722 if (src == null || src.info == null || src.provider == null) {
5723 continue;
5724 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005725 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 if (dst != null) {
5727 mProvidersByClass.put(dst.info.name, dst);
5728 String names[] = dst.info.authority.split(";");
5729 for (int j = 0; j < names.length; j++) {
5730 mProvidersByName.put(names[j], dst);
5731 }
5732
5733 int NL = mLaunchingProviders.size();
5734 int j;
5735 for (j=0; j<NL; j++) {
5736 if (mLaunchingProviders.get(j) == dst) {
5737 mLaunchingProviders.remove(j);
5738 j--;
5739 NL--;
5740 }
5741 }
5742 synchronized (dst) {
5743 dst.provider = src.provider;
5744 dst.app = r;
5745 dst.notifyAll();
5746 }
5747 updateOomAdjLocked(r);
5748 }
5749 }
5750
5751 Binder.restoreCallingIdentity(origId);
5752 }
5753 }
5754
5755 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005756 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005757 synchronized (mSelf) {
5758 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5759 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005760 if (providers != null) {
5761 for (int i=providers.size()-1; i>=0; i--) {
5762 ProviderInfo pi = (ProviderInfo)providers.get(i);
5763 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5764 Slog.w(TAG, "Not installing system proc provider " + pi.name
5765 + ": not system .apk");
5766 providers.remove(i);
5767 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005768 }
5769 }
5770 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005771 if (providers != null) {
5772 mSystemThread.installSystemProviders(providers);
5773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 }
5775
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005776 /**
5777 * Allows app to retrieve the MIME type of a URI without having permission
5778 * to access its content provider.
5779 *
5780 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5781 *
5782 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5783 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5784 */
5785 public String getProviderMimeType(Uri uri) {
5786 final String name = uri.getAuthority();
5787 final long ident = Binder.clearCallingIdentity();
5788 ContentProviderHolder holder = null;
5789
5790 try {
5791 holder = getContentProviderExternal(name);
5792 if (holder != null) {
5793 return holder.provider.getType(uri);
5794 }
5795 } catch (RemoteException e) {
5796 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5797 return null;
5798 } finally {
5799 if (holder != null) {
5800 removeContentProviderExternal(name);
5801 }
5802 Binder.restoreCallingIdentity(ident);
5803 }
5804
5805 return null;
5806 }
5807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 // =========================================================
5809 // GLOBAL MANAGEMENT
5810 // =========================================================
5811
5812 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5813 ApplicationInfo info, String customProcess) {
5814 String proc = customProcess != null ? customProcess : info.processName;
5815 BatteryStatsImpl.Uid.Proc ps = null;
5816 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5817 synchronized (stats) {
5818 ps = stats.getProcessStatsLocked(info.uid, proc);
5819 }
5820 return new ProcessRecord(ps, thread, info, proc);
5821 }
5822
5823 final ProcessRecord addAppLocked(ApplicationInfo info) {
5824 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5825
5826 if (app == null) {
5827 app = newProcessRecordLocked(null, info, null);
5828 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005829 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 }
5831
Dianne Hackborne7f97212011-02-24 14:40:20 -08005832 // This package really, really can not be stopped.
5833 try {
5834 AppGlobals.getPackageManager().setPackageStoppedState(
5835 info.packageName, false);
5836 } catch (RemoteException e) {
5837 }
5838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5840 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5841 app.persistent = true;
5842 app.maxAdj = CORE_SERVER_ADJ;
5843 }
5844 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5845 mPersistentStartingProcesses.add(app);
5846 startProcessLocked(app, "added application", app.processName);
5847 }
5848
5849 return app;
5850 }
5851
5852 public void unhandledBack() {
5853 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5854 "unhandledBack()");
5855
5856 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005857 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005858 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859 TAG, "Performing unhandledBack(): stack size = " + count);
5860 if (count > 1) {
5861 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005862 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5864 Binder.restoreCallingIdentity(origId);
5865 }
5866 }
5867 }
5868
5869 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5870 String name = uri.getAuthority();
5871 ContentProviderHolder cph = getContentProviderExternal(name);
5872 ParcelFileDescriptor pfd = null;
5873 if (cph != null) {
5874 // We record the binder invoker's uid in thread-local storage before
5875 // going to the content provider to open the file. Later, in the code
5876 // that handles all permissions checks, we look for this uid and use
5877 // that rather than the Activity Manager's own uid. The effect is that
5878 // we do the check against the caller's permissions even though it looks
5879 // to the content provider like the Activity Manager itself is making
5880 // the request.
5881 sCallerIdentity.set(new Identity(
5882 Binder.getCallingPid(), Binder.getCallingUid()));
5883 try {
5884 pfd = cph.provider.openFile(uri, "r");
5885 } catch (FileNotFoundException e) {
5886 // do nothing; pfd will be returned null
5887 } finally {
5888 // Ensure that whatever happens, we clean up the identity state
5889 sCallerIdentity.remove();
5890 }
5891
5892 // We've got the fd now, so we're done with the provider.
5893 removeContentProviderExternal(name);
5894 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005895 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 }
5897 return pfd;
5898 }
5899
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005900 // Actually is sleeping or shutting down or whatever else in the future
5901 // is an inactive state.
5902 public boolean isSleeping() {
5903 return mSleeping || mShuttingDown;
5904 }
5905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 public void goingToSleep() {
5907 synchronized(this) {
5908 mSleeping = true;
5909 mWindowManager.setEventDispatching(false);
5910
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005911 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005912
5913 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005914 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005915 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5916 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005917 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 }
5919 }
5920
Dianne Hackborn55280a92009-05-07 15:53:46 -07005921 public boolean shutdown(int timeout) {
5922 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5923 != PackageManager.PERMISSION_GRANTED) {
5924 throw new SecurityException("Requires permission "
5925 + android.Manifest.permission.SHUTDOWN);
5926 }
5927
5928 boolean timedout = false;
5929
5930 synchronized(this) {
5931 mShuttingDown = true;
5932 mWindowManager.setEventDispatching(false);
5933
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005934 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005935 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005936 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005937 while (mMainStack.mResumedActivity != null
5938 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005939 long delay = endTime - System.currentTimeMillis();
5940 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005941 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005942 timedout = true;
5943 break;
5944 }
5945 try {
5946 this.wait();
5947 } catch (InterruptedException e) {
5948 }
5949 }
5950 }
5951 }
5952
5953 mUsageStatsService.shutdown();
5954 mBatteryStatsService.shutdown();
5955
5956 return timedout;
5957 }
5958
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005959 public final void activitySlept(IBinder token) {
5960 if (localLOGV) Slog.v(
5961 TAG, "Activity slept: token=" + token);
5962
5963 ActivityRecord r = null;
5964
5965 final long origId = Binder.clearCallingIdentity();
5966
5967 synchronized (this) {
5968 int index = mMainStack.indexOfTokenLocked(token);
5969 if (index >= 0) {
5970 r = (ActivityRecord)mMainStack.mHistory.get(index);
5971 mMainStack.activitySleptLocked(r);
5972 }
5973 }
5974
5975 Binder.restoreCallingIdentity(origId);
5976 }
5977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 public void wakingUp() {
5979 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005980 mWindowManager.setEventDispatching(true);
5981 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005982 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005983 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 }
5985 }
5986
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005987 public void stopAppSwitches() {
5988 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5989 != PackageManager.PERMISSION_GRANTED) {
5990 throw new SecurityException("Requires permission "
5991 + android.Manifest.permission.STOP_APP_SWITCHES);
5992 }
5993
5994 synchronized(this) {
5995 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5996 + APP_SWITCH_DELAY_TIME;
5997 mDidAppSwitch = false;
5998 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5999 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6000 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6001 }
6002 }
6003
6004 public void resumeAppSwitches() {
6005 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6006 != PackageManager.PERMISSION_GRANTED) {
6007 throw new SecurityException("Requires permission "
6008 + android.Manifest.permission.STOP_APP_SWITCHES);
6009 }
6010
6011 synchronized(this) {
6012 // Note that we don't execute any pending app switches... we will
6013 // let those wait until either the timeout, or the next start
6014 // activity request.
6015 mAppSwitchesAllowedTime = 0;
6016 }
6017 }
6018
6019 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6020 String name) {
6021 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6022 return true;
6023 }
6024
6025 final int perm = checkComponentPermission(
6026 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006027 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006028 if (perm == PackageManager.PERMISSION_GRANTED) {
6029 return true;
6030 }
6031
Joe Onorato8a9b2202010-02-26 18:56:32 -08006032 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006033 return false;
6034 }
6035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006036 public void setDebugApp(String packageName, boolean waitForDebugger,
6037 boolean persistent) {
6038 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6039 "setDebugApp()");
6040
6041 // Note that this is not really thread safe if there are multiple
6042 // callers into it at the same time, but that's not a situation we
6043 // care about.
6044 if (persistent) {
6045 final ContentResolver resolver = mContext.getContentResolver();
6046 Settings.System.putString(
6047 resolver, Settings.System.DEBUG_APP,
6048 packageName);
6049 Settings.System.putInt(
6050 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6051 waitForDebugger ? 1 : 0);
6052 }
6053
6054 synchronized (this) {
6055 if (!persistent) {
6056 mOrigDebugApp = mDebugApp;
6057 mOrigWaitForDebugger = mWaitForDebugger;
6058 }
6059 mDebugApp = packageName;
6060 mWaitForDebugger = waitForDebugger;
6061 mDebugTransient = !persistent;
6062 if (packageName != null) {
6063 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006064 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 Binder.restoreCallingIdentity(origId);
6066 }
6067 }
6068 }
6069
6070 public void setAlwaysFinish(boolean enabled) {
6071 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6072 "setAlwaysFinish()");
6073
6074 Settings.System.putInt(
6075 mContext.getContentResolver(),
6076 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6077
6078 synchronized (this) {
6079 mAlwaysFinishActivities = enabled;
6080 }
6081 }
6082
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006083 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006085 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006087 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088 }
6089 }
6090
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006091 public boolean isUserAMonkey() {
6092 // For now the fact that there is a controller implies
6093 // we have a monkey.
6094 synchronized (this) {
6095 return mController != null;
6096 }
6097 }
6098
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006099 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006100 synchronized (this) {
6101 mWatchers.register(watcher);
6102 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006103 }
6104
6105 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006106 synchronized (this) {
6107 mWatchers.unregister(watcher);
6108 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006109 }
6110
Daniel Sandler69a48172010-06-23 16:29:36 -04006111 public void setImmersive(IBinder token, boolean immersive) {
6112 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006113 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006114 if (index < 0) {
6115 throw new IllegalArgumentException();
6116 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006117 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006118 r.immersive = immersive;
6119 }
6120 }
6121
6122 public boolean isImmersive(IBinder token) {
6123 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006124 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006125 if (index < 0) {
6126 throw new IllegalArgumentException();
6127 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006128 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006129 return r.immersive;
6130 }
6131 }
6132
6133 public boolean isTopActivityImmersive() {
6134 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006135 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006136 return (r != null) ? r.immersive : false;
6137 }
6138 }
6139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 public final void enterSafeMode() {
6141 synchronized(this) {
6142 // It only makes sense to do this before the system is ready
6143 // and started launching other packages.
6144 if (!mSystemReady) {
6145 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006146 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 } catch (RemoteException e) {
6148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006149 }
6150 }
6151 }
6152
Jeff Brownb09abc12011-01-13 21:08:27 -08006153 public final void showSafeModeOverlay() {
6154 View v = LayoutInflater.from(mContext).inflate(
6155 com.android.internal.R.layout.safe_mode, null);
6156 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6157 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6158 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6159 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6160 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6161 lp.format = v.getBackground().getOpacity();
6162 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6163 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6164 ((WindowManager)mContext.getSystemService(
6165 Context.WINDOW_SERVICE)).addView(v, lp);
6166 }
6167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 public void noteWakeupAlarm(IIntentSender sender) {
6169 if (!(sender instanceof PendingIntentRecord)) {
6170 return;
6171 }
6172 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6173 synchronized (stats) {
6174 if (mBatteryStatsService.isOnBattery()) {
6175 mBatteryStatsService.enforceCallingPermission();
6176 PendingIntentRecord rec = (PendingIntentRecord)sender;
6177 int MY_UID = Binder.getCallingUid();
6178 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6179 BatteryStatsImpl.Uid.Pkg pkg =
6180 stats.getPackageStatsLocked(uid, rec.key.packageName);
6181 pkg.incWakeupsLocked();
6182 }
6183 }
6184 }
6185
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006186 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006187 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006188 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006189 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006190 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006191 // XXX Note: don't acquire main activity lock here, because the window
6192 // manager calls in with its locks held.
6193
6194 boolean killed = false;
6195 synchronized (mPidsSelfLocked) {
6196 int[] types = new int[pids.length];
6197 int worstType = 0;
6198 for (int i=0; i<pids.length; i++) {
6199 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6200 if (proc != null) {
6201 int type = proc.setAdj;
6202 types[i] = type;
6203 if (type > worstType) {
6204 worstType = type;
6205 }
6206 }
6207 }
6208
6209 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6210 // then constrain it so we will kill all hidden procs.
6211 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6212 worstType = HIDDEN_APP_MIN_ADJ;
6213 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006214 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 for (int i=0; i<pids.length; i++) {
6216 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6217 if (proc == null) {
6218 continue;
6219 }
6220 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006221 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006222 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006223 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6224 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006225 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006226 proc.killedBackground = true;
6227 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006228 }
6229 }
6230 }
6231 return killed;
6232 }
6233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 public final void startRunning(String pkg, String cls, String action,
6235 String data) {
6236 synchronized(this) {
6237 if (mStartRunning) {
6238 return;
6239 }
6240 mStartRunning = true;
6241 mTopComponent = pkg != null && cls != null
6242 ? new ComponentName(pkg, cls) : null;
6243 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6244 mTopData = data;
6245 if (!mSystemReady) {
6246 return;
6247 }
6248 }
6249
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006250 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 }
6252
6253 private void retrieveSettings() {
6254 final ContentResolver resolver = mContext.getContentResolver();
6255 String debugApp = Settings.System.getString(
6256 resolver, Settings.System.DEBUG_APP);
6257 boolean waitForDebugger = Settings.System.getInt(
6258 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6259 boolean alwaysFinishActivities = Settings.System.getInt(
6260 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6261
6262 Configuration configuration = new Configuration();
6263 Settings.System.getConfiguration(resolver, configuration);
6264
6265 synchronized (this) {
6266 mDebugApp = mOrigDebugApp = debugApp;
6267 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6268 mAlwaysFinishActivities = alwaysFinishActivities;
6269 // This happens before any activities are started, so we can
6270 // change mConfiguration in-place.
6271 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006272 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006273 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 }
6275 }
6276
6277 public boolean testIsSystemReady() {
6278 // no need to synchronize(this) just to read & return the value
6279 return mSystemReady;
6280 }
6281
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006282 private static File getCalledPreBootReceiversFile() {
6283 File dataDir = Environment.getDataDirectory();
6284 File systemDir = new File(dataDir, "system");
6285 File fname = new File(systemDir, "called_pre_boots.dat");
6286 return fname;
6287 }
6288
6289 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6290 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6291 File file = getCalledPreBootReceiversFile();
6292 FileInputStream fis = null;
6293 try {
6294 fis = new FileInputStream(file);
6295 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6296 int vers = dis.readInt();
6297 String codename = dis.readUTF();
6298 if (vers == android.os.Build.VERSION.SDK_INT
6299 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6300 int num = dis.readInt();
6301 while (num > 0) {
6302 num--;
6303 String pkg = dis.readUTF();
6304 String cls = dis.readUTF();
6305 lastDoneReceivers.add(new ComponentName(pkg, cls));
6306 }
6307 }
6308 } catch (FileNotFoundException e) {
6309 } catch (IOException e) {
6310 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6311 } finally {
6312 if (fis != null) {
6313 try {
6314 fis.close();
6315 } catch (IOException e) {
6316 }
6317 }
6318 }
6319 return lastDoneReceivers;
6320 }
6321
6322 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6323 File file = getCalledPreBootReceiversFile();
6324 FileOutputStream fos = null;
6325 DataOutputStream dos = null;
6326 try {
6327 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6328 fos = new FileOutputStream(file);
6329 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6330 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6331 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6332 dos.writeInt(list.size());
6333 for (int i=0; i<list.size(); i++) {
6334 dos.writeUTF(list.get(i).getPackageName());
6335 dos.writeUTF(list.get(i).getClassName());
6336 }
6337 } catch (IOException e) {
6338 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6339 file.delete();
6340 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006341 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006342 if (dos != null) {
6343 try {
6344 dos.close();
6345 } catch (IOException e) {
6346 // TODO Auto-generated catch block
6347 e.printStackTrace();
6348 }
6349 }
6350 }
6351 }
6352
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006353 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006354 // In the simulator, startRunning will never have been called, which
6355 // normally sets a few crucial variables. Do it here instead.
6356 if (!Process.supportsProcesses()) {
6357 mStartRunning = true;
6358 mTopAction = Intent.ACTION_MAIN;
6359 }
6360
6361 synchronized(this) {
6362 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006363 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 return;
6365 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006366
6367 // Check to see if there are any update receivers to run.
6368 if (!mDidUpdate) {
6369 if (mWaitingUpdate) {
6370 return;
6371 }
6372 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6373 List<ResolveInfo> ris = null;
6374 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006375 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006376 intent, null, 0);
6377 } catch (RemoteException e) {
6378 }
6379 if (ris != null) {
6380 for (int i=ris.size()-1; i>=0; i--) {
6381 if ((ris.get(i).activityInfo.applicationInfo.flags
6382 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6383 ris.remove(i);
6384 }
6385 }
6386 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006387
6388 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6389
6390 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006391 for (int i=0; i<ris.size(); i++) {
6392 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006393 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6394 if (lastDoneReceivers.contains(comp)) {
6395 ris.remove(i);
6396 i--;
6397 }
6398 }
6399
6400 for (int i=0; i<ris.size(); i++) {
6401 ActivityInfo ai = ris.get(i).activityInfo;
6402 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6403 doneReceivers.add(comp);
6404 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006405 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006406 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006407 finisher = new IIntentReceiver.Stub() {
6408 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006409 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006410 boolean sticky) {
6411 // The raw IIntentReceiver interface is called
6412 // with the AM lock held, so redispatch to
6413 // execute our code without the lock.
6414 mHandler.post(new Runnable() {
6415 public void run() {
6416 synchronized (ActivityManagerService.this) {
6417 mDidUpdate = true;
6418 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006419 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006420 systemReady(goingCallback);
6421 }
6422 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006423 }
6424 };
6425 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006426 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006427 broadcastIntentLocked(null, null, intent, null, finisher,
6428 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006429 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006430 mWaitingUpdate = true;
6431 }
6432 }
6433 }
6434 if (mWaitingUpdate) {
6435 return;
6436 }
6437 mDidUpdate = true;
6438 }
6439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 mSystemReady = true;
6441 if (!mStartRunning) {
6442 return;
6443 }
6444 }
6445
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006446 ArrayList<ProcessRecord> procsToKill = null;
6447 synchronized(mPidsSelfLocked) {
6448 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6449 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6450 if (!isAllowedWhileBooting(proc.info)){
6451 if (procsToKill == null) {
6452 procsToKill = new ArrayList<ProcessRecord>();
6453 }
6454 procsToKill.add(proc);
6455 }
6456 }
6457 }
6458
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006459 synchronized(this) {
6460 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006461 for (int i=procsToKill.size()-1; i>=0; i--) {
6462 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006463 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006464 removeProcessLocked(proc, true);
6465 }
6466 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006467
6468 // Now that we have cleaned up any update processes, we
6469 // are ready to start launching real processes and know that
6470 // we won't trample on them any more.
6471 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006472 }
6473
Joe Onorato8a9b2202010-02-26 18:56:32 -08006474 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006475 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 SystemClock.uptimeMillis());
6477
6478 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006479 // Make sure we have no pre-ready processes sitting around.
6480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6482 ResolveInfo ri = mContext.getPackageManager()
6483 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006484 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 CharSequence errorMsg = null;
6486 if (ri != null) {
6487 ActivityInfo ai = ri.activityInfo;
6488 ApplicationInfo app = ai.applicationInfo;
6489 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6490 mTopAction = Intent.ACTION_FACTORY_TEST;
6491 mTopData = null;
6492 mTopComponent = new ComponentName(app.packageName,
6493 ai.name);
6494 } else {
6495 errorMsg = mContext.getResources().getText(
6496 com.android.internal.R.string.factorytest_not_system);
6497 }
6498 } else {
6499 errorMsg = mContext.getResources().getText(
6500 com.android.internal.R.string.factorytest_no_action);
6501 }
6502 if (errorMsg != null) {
6503 mTopAction = null;
6504 mTopData = null;
6505 mTopComponent = null;
6506 Message msg = Message.obtain();
6507 msg.what = SHOW_FACTORY_ERROR_MSG;
6508 msg.getData().putCharSequence("msg", errorMsg);
6509 mHandler.sendMessage(msg);
6510 }
6511 }
6512 }
6513
6514 retrieveSettings();
6515
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006516 if (goingCallback != null) goingCallback.run();
6517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 synchronized (this) {
6519 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6520 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006521 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006522 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 if (apps != null) {
6524 int N = apps.size();
6525 int i;
6526 for (i=0; i<N; i++) {
6527 ApplicationInfo info
6528 = (ApplicationInfo)apps.get(i);
6529 if (info != null &&
6530 !info.packageName.equals("android")) {
6531 addAppLocked(info);
6532 }
6533 }
6534 }
6535 } catch (RemoteException ex) {
6536 // pm is in same process, this will never happen.
6537 }
6538 }
6539
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006540 // Start up initial activity.
6541 mBooting = true;
6542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006543 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006544 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 Message msg = Message.obtain();
6546 msg.what = SHOW_UID_ERROR_MSG;
6547 mHandler.sendMessage(msg);
6548 }
6549 } catch (RemoteException e) {
6550 }
6551
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006552 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 }
6554 }
6555
Dan Egnorb7f03672009-12-09 16:22:32 -08006556 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006557 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006559 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006560 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 startAppProblemLocked(app);
6562 app.stopFreezingAllLocked();
6563 return handleAppCrashLocked(app);
6564 }
6565
Dan Egnorb7f03672009-12-09 16:22:32 -08006566 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006567 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006569 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006570 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6571 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006572 startAppProblemLocked(app);
6573 app.stopFreezingAllLocked();
6574 }
6575
6576 /**
6577 * Generate a process error record, suitable for attachment to a ProcessRecord.
6578 *
6579 * @param app The ProcessRecord in which the error occurred.
6580 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6581 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006582 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 * @param shortMsg Short message describing the crash.
6584 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006585 * @param stackTrace Full crash stack trace, may be null.
6586 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006587 * @return Returns a fully-formed AppErrorStateInfo record.
6588 */
6589 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006590 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 report.condition = condition;
6594 report.processName = app.processName;
6595 report.pid = app.pid;
6596 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006597 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006598 report.shortMsg = shortMsg;
6599 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006600 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006601
6602 return report;
6603 }
6604
Dan Egnor42471dd2010-01-07 17:25:22 -08006605 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 synchronized (this) {
6607 app.crashing = false;
6608 app.crashingReport = null;
6609 app.notResponding = false;
6610 app.notRespondingReport = null;
6611 if (app.anrDialog == fromDialog) {
6612 app.anrDialog = null;
6613 }
6614 if (app.waitDialog == fromDialog) {
6615 app.waitDialog = null;
6616 }
6617 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006618 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006619 Slog.i(ActivityManagerService.TAG, "Killing "
6620 + app.processName + " (pid=" + app.pid + "): user's request");
6621 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6622 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006623 Process.killProcess(app.pid);
6624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006625 }
6626 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006627
Dan Egnorb7f03672009-12-09 16:22:32 -08006628 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 long now = SystemClock.uptimeMillis();
6630
6631 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6632 app.info.uid);
6633 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6634 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006635 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006637 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006639 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6640 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006642 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006643 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006644 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 }
6646 }
6647 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006648 // Don't let services in this process be restarted and potentially
6649 // annoy the user repeatedly. Unless it is persistent, since those
6650 // processes run critical code.
6651 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006652 // We don't want to start this process again until the user
6653 // explicitly does so... but for persistent process, we really
6654 // need to keep it running. If a persistent process is actually
6655 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006656 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006657 app.info.processName);
6658 mBadProcesses.put(app.info.processName, app.info.uid, now);
6659 app.bad = true;
6660 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6661 app.removed = true;
6662 removeProcessLocked(app, false);
6663 return false;
6664 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006665 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006666 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006667 if (r.app == app) {
6668 // If the top running activity is from this crashing
6669 // process, then terminate it to avoid getting in a loop.
6670 Slog.w(TAG, " Force finishing activity "
6671 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006672 int index = mMainStack.indexOfTokenLocked(r);
6673 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006674 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006675 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006676 // stopped, to avoid a situation where one will get
6677 // re-start our crashing activity once it gets resumed again.
6678 index--;
6679 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006680 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006681 if (r.state == ActivityState.RESUMED
6682 || r.state == ActivityState.PAUSING
6683 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006684 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006685 Slog.w(TAG, " Force finishing activity "
6686 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006687 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006688 Activity.RESULT_CANCELED, null, "crashed");
6689 }
6690 }
6691 }
6692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 }
6694
6695 // Bump up the crash count of any services currently running in the proc.
6696 if (app.services.size() != 0) {
6697 // Any services running in the application need to be placed
6698 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006699 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006700 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006701 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 sr.crashCount++;
6703 }
6704 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006705
6706 // If the crashing process is what we consider to be the "home process" and it has been
6707 // replaced by a third-party app, clear the package preferred activities from packages
6708 // with a home activity running in the process to prevent a repeatedly crashing app
6709 // from blocking the user to manually clear the list.
6710 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6711 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6712 Iterator it = mHomeProcess.activities.iterator();
6713 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006714 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006715 if (r.isHomeActivity) {
6716 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6717 try {
6718 ActivityThread.getPackageManager()
6719 .clearPackagePreferredActivities(r.packageName);
6720 } catch (RemoteException c) {
6721 // pm is in same process, this will never happen.
6722 }
6723 }
6724 }
6725 }
6726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006727 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6728 return true;
6729 }
6730
6731 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006732 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6733 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006734 skipCurrentReceiverLocked(app);
6735 }
6736
6737 void skipCurrentReceiverLocked(ProcessRecord app) {
6738 boolean reschedule = false;
6739 BroadcastRecord r = app.curReceiver;
6740 if (r != null) {
6741 // The current broadcast is waiting for this app's receiver
6742 // to be finished. Looks like that's not going to happen, so
6743 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006744 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6746 r.resultExtras, r.resultAbort, true);
6747 reschedule = true;
6748 }
6749 r = mPendingBroadcast;
6750 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006751 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006753 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6755 r.resultExtras, r.resultAbort, true);
6756 reschedule = true;
6757 }
6758 if (reschedule) {
6759 scheduleBroadcastsLocked();
6760 }
6761 }
6762
Dan Egnor60d87622009-12-16 16:32:58 -08006763 /**
6764 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6765 * The application process will exit immediately after this call returns.
6766 * @param app object of the crashing app, null for the system server
6767 * @param crashInfo describing the exception
6768 */
6769 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6770 ProcessRecord r = findAppProcess(app);
6771
6772 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6773 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006774 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006775 crashInfo.exceptionClassName,
6776 crashInfo.exceptionMessage,
6777 crashInfo.throwFileName,
6778 crashInfo.throwLineNumber);
6779
Dan Egnor42471dd2010-01-07 17:25:22 -08006780 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006781
6782 crashApplication(r, crashInfo);
6783 }
6784
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006785 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006786 IBinder app,
6787 int violationMask,
6788 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006789 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006790
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006791 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006792 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006793 boolean logIt = true;
6794 synchronized (mAlreadyLoggedViolatedStacks) {
6795 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6796 logIt = false;
6797 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006798 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006799 // the relative pain numbers, without logging all
6800 // the stack traces repeatedly. We'd want to do
6801 // likewise in the client code, which also does
6802 // dup suppression, before the Binder call.
6803 } else {
6804 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6805 mAlreadyLoggedViolatedStacks.clear();
6806 }
6807 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6808 }
6809 }
6810 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006811 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006812 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006813 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006814
6815 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6816 AppErrorResult result = new AppErrorResult();
6817 synchronized (this) {
6818 final long origId = Binder.clearCallingIdentity();
6819
6820 Message msg = Message.obtain();
6821 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6822 HashMap<String, Object> data = new HashMap<String, Object>();
6823 data.put("result", result);
6824 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006825 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006826 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006827 msg.obj = data;
6828 mHandler.sendMessage(msg);
6829
6830 Binder.restoreCallingIdentity(origId);
6831 }
6832 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006833 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006834 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006835 }
6836
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006837 // Depending on the policy in effect, there could be a bunch of
6838 // these in quick succession so we try to batch these together to
6839 // minimize disk writes, number of dropbox entries, and maximize
6840 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006841 private void logStrictModeViolationToDropBox(
6842 ProcessRecord process,
6843 StrictMode.ViolationInfo info) {
6844 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006845 return;
6846 }
6847 final boolean isSystemApp = process == null ||
6848 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6849 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6850 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6851 final DropBoxManager dbox = (DropBoxManager)
6852 mContext.getSystemService(Context.DROPBOX_SERVICE);
6853
6854 // Exit early if the dropbox isn't configured to accept this report type.
6855 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6856
6857 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006858 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006859 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6860 synchronized (sb) {
6861 bufferWasEmpty = sb.length() == 0;
6862 appendDropBoxProcessHeaders(process, sb);
6863 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6864 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006865 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6866 if (info.violationNumThisLoop != 0) {
6867 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6868 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006869 if (info.numAnimationsRunning != 0) {
6870 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6871 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006872 if (info.broadcastIntentAction != null) {
6873 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6874 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006875 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006876 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006877 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006878 if (info.numInstances != -1) {
6879 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6880 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006881 if (info.tags != null) {
6882 for (String tag : info.tags) {
6883 sb.append("Span-Tag: ").append(tag).append("\n");
6884 }
6885 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006886 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006887 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6888 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006889 }
6890 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006891
6892 // Only buffer up to ~64k. Various logging bits truncate
6893 // things at 128k.
6894 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006895 }
6896
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006897 // Flush immediately if the buffer's grown too large, or this
6898 // is a non-system app. Non-system apps are isolated with a
6899 // different tag & policy and not batched.
6900 //
6901 // Batching is useful during internal testing with
6902 // StrictMode settings turned up high. Without batching,
6903 // thousands of separate files could be created on boot.
6904 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006905 new Thread("Error dump: " + dropboxTag) {
6906 @Override
6907 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006908 String report;
6909 synchronized (sb) {
6910 report = sb.toString();
6911 sb.delete(0, sb.length());
6912 sb.trimToSize();
6913 }
6914 if (report.length() != 0) {
6915 dbox.addText(dropboxTag, report);
6916 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006917 }
6918 }.start();
6919 return;
6920 }
6921
6922 // System app batching:
6923 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006924 // An existing dropbox-writing thread is outstanding, so
6925 // we don't need to start it up. The existing thread will
6926 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006927 return;
6928 }
6929
6930 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6931 // (After this point, we shouldn't access AMS internal data structures.)
6932 new Thread("Error dump: " + dropboxTag) {
6933 @Override
6934 public void run() {
6935 // 5 second sleep to let stacks arrive and be batched together
6936 try {
6937 Thread.sleep(5000); // 5 seconds
6938 } catch (InterruptedException e) {}
6939
6940 String errorReport;
6941 synchronized (mStrictModeBuffer) {
6942 errorReport = mStrictModeBuffer.toString();
6943 if (errorReport.length() == 0) {
6944 return;
6945 }
6946 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6947 mStrictModeBuffer.trimToSize();
6948 }
6949 dbox.addText(dropboxTag, errorReport);
6950 }
6951 }.start();
6952 }
6953
Dan Egnor60d87622009-12-16 16:32:58 -08006954 /**
6955 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6956 * @param app object of the crashing app, null for the system server
6957 * @param tag reported by the caller
6958 * @param crashInfo describing the context of the error
6959 * @return true if the process should exit immediately (WTF is fatal)
6960 */
6961 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006962 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006963 ProcessRecord r = findAppProcess(app);
6964
6965 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6966 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006967 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006968 tag, crashInfo.exceptionMessage);
6969
Dan Egnor42471dd2010-01-07 17:25:22 -08006970 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006971
Doug Zongker43866e02010-01-07 12:09:54 -08006972 if (Settings.Secure.getInt(mContext.getContentResolver(),
6973 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006974 crashApplication(r, crashInfo);
6975 return true;
6976 } else {
6977 return false;
6978 }
6979 }
6980
6981 /**
6982 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6983 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6984 */
6985 private ProcessRecord findAppProcess(IBinder app) {
6986 if (app == null) {
6987 return null;
6988 }
6989
6990 synchronized (this) {
6991 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6992 final int NA = apps.size();
6993 for (int ia=0; ia<NA; ia++) {
6994 ProcessRecord p = apps.valueAt(ia);
6995 if (p.thread != null && p.thread.asBinder() == app) {
6996 return p;
6997 }
6998 }
6999 }
7000
Joe Onorato8a9b2202010-02-26 18:56:32 -08007001 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007002 return null;
7003 }
7004 }
7005
7006 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007007 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7008 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007009 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007010 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7011 // Note: ProcessRecord 'process' is guarded by the service
7012 // instance. (notably process.pkgList, which could otherwise change
7013 // concurrently during execution of this method)
7014 synchronized (this) {
7015 if (process == null || process.pid == MY_PID) {
7016 sb.append("Process: system_server\n");
7017 } else {
7018 sb.append("Process: ").append(process.processName).append("\n");
7019 }
7020 if (process == null) {
7021 return;
7022 }
Dan Egnora455d192010-03-12 08:52:28 -08007023 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007024 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007025 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7026 for (String pkg : process.pkgList) {
7027 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007028 try {
Dan Egnora455d192010-03-12 08:52:28 -08007029 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7030 if (pi != null) {
7031 sb.append(" v").append(pi.versionCode);
7032 if (pi.versionName != null) {
7033 sb.append(" (").append(pi.versionName).append(")");
7034 }
7035 }
7036 } catch (RemoteException e) {
7037 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007038 }
Dan Egnora455d192010-03-12 08:52:28 -08007039 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007040 }
Dan Egnora455d192010-03-12 08:52:28 -08007041 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007042 }
7043
7044 private static String processClass(ProcessRecord process) {
7045 if (process == null || process.pid == MY_PID) {
7046 return "system_server";
7047 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7048 return "system_app";
7049 } else {
7050 return "data_app";
7051 }
7052 }
7053
7054 /**
7055 * Write a description of an error (crash, WTF, ANR) to the drop box.
7056 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7057 * @param process which caused the error, null means the system server
7058 * @param activity which triggered the error, null if unknown
7059 * @param parent activity related to the error, null if unknown
7060 * @param subject line related to the error, null if absent
7061 * @param report in long form describing the error, null if absent
7062 * @param logFile to include in the report, null if none
7063 * @param crashInfo giving an application stack trace, null if absent
7064 */
7065 public void addErrorToDropBox(String eventType,
7066 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7067 final String report, final File logFile,
7068 final ApplicationErrorReport.CrashInfo crashInfo) {
7069 // NOTE -- this must never acquire the ActivityManagerService lock,
7070 // otherwise the watchdog may be prevented from resetting the system.
7071
7072 final String dropboxTag = processClass(process) + "_" + eventType;
7073 final DropBoxManager dbox = (DropBoxManager)
7074 mContext.getSystemService(Context.DROPBOX_SERVICE);
7075
7076 // Exit early if the dropbox isn't configured to accept this report type.
7077 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7078
7079 final StringBuilder sb = new StringBuilder(1024);
7080 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007081 if (activity != null) {
7082 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7083 }
7084 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7085 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7086 }
7087 if (parent != null && parent != activity) {
7088 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7089 }
7090 if (subject != null) {
7091 sb.append("Subject: ").append(subject).append("\n");
7092 }
7093 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007094 if (Debug.isDebuggerConnected()) {
7095 sb.append("Debugger: Connected\n");
7096 }
Dan Egnora455d192010-03-12 08:52:28 -08007097 sb.append("\n");
7098
7099 // Do the rest in a worker thread to avoid blocking the caller on I/O
7100 // (After this point, we shouldn't access AMS internal data structures.)
7101 Thread worker = new Thread("Error dump: " + dropboxTag) {
7102 @Override
7103 public void run() {
7104 if (report != null) {
7105 sb.append(report);
7106 }
7107 if (logFile != null) {
7108 try {
7109 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7110 } catch (IOException e) {
7111 Slog.e(TAG, "Error reading " + logFile, e);
7112 }
7113 }
7114 if (crashInfo != null && crashInfo.stackTrace != null) {
7115 sb.append(crashInfo.stackTrace);
7116 }
7117
7118 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7119 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7120 if (lines > 0) {
7121 sb.append("\n");
7122
7123 // Merge several logcat streams, and take the last N lines
7124 InputStreamReader input = null;
7125 try {
7126 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7127 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7128 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7129
7130 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7131 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7132 input = new InputStreamReader(logcat.getInputStream());
7133
7134 int num;
7135 char[] buf = new char[8192];
7136 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7137 } catch (IOException e) {
7138 Slog.e(TAG, "Error running logcat", e);
7139 } finally {
7140 if (input != null) try { input.close(); } catch (IOException e) {}
7141 }
7142 }
7143
7144 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007145 }
Dan Egnora455d192010-03-12 08:52:28 -08007146 };
7147
7148 if (process == null || process.pid == MY_PID) {
7149 worker.run(); // We may be about to die -- need to run this synchronously
7150 } else {
7151 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007152 }
7153 }
7154
7155 /**
7156 * Bring up the "unexpected error" dialog box for a crashing app.
7157 * Deal with edge cases (intercepts from instrumented applications,
7158 * ActivityController, error intent receivers, that sort of thing).
7159 * @param r the application crashing
7160 * @param crashInfo describing the failure
7161 */
7162 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007163 long timeMillis = System.currentTimeMillis();
7164 String shortMsg = crashInfo.exceptionClassName;
7165 String longMsg = crashInfo.exceptionMessage;
7166 String stackTrace = crashInfo.stackTrace;
7167 if (shortMsg != null && longMsg != null) {
7168 longMsg = shortMsg + ": " + longMsg;
7169 } else if (shortMsg != null) {
7170 longMsg = shortMsg;
7171 }
7172
Dan Egnor60d87622009-12-16 16:32:58 -08007173 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007175 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176 try {
7177 String name = r != null ? r.processName : null;
7178 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007179 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007180 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007181 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182 + " at watcher's request");
7183 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007184 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007185 }
7186 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007187 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 }
7189 }
7190
7191 final long origId = Binder.clearCallingIdentity();
7192
7193 // If this process is running instrumentation, finish it.
7194 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007195 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007197 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7198 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007199 Bundle info = new Bundle();
7200 info.putString("shortMsg", shortMsg);
7201 info.putString("longMsg", longMsg);
7202 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7203 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007204 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 }
7206
Dan Egnor60d87622009-12-16 16:32:58 -08007207 // If we can't identify the process or it's already exceeded its crash quota,
7208 // quit right away without showing a crash dialog.
7209 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007211 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007212 }
7213
7214 Message msg = Message.obtain();
7215 msg.what = SHOW_ERROR_MSG;
7216 HashMap data = new HashMap();
7217 data.put("result", result);
7218 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 msg.obj = data;
7220 mHandler.sendMessage(msg);
7221
7222 Binder.restoreCallingIdentity(origId);
7223 }
7224
7225 int res = result.get();
7226
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007227 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 synchronized (this) {
7229 if (r != null) {
7230 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7231 SystemClock.uptimeMillis());
7232 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007233 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007234 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007235 }
7236 }
7237
7238 if (appErrorIntent != null) {
7239 try {
7240 mContext.startActivity(appErrorIntent);
7241 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007242 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007246
7247 Intent createAppErrorIntentLocked(ProcessRecord r,
7248 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7249 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007250 if (report == null) {
7251 return null;
7252 }
7253 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7254 result.setComponent(r.errorReportReceiver);
7255 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7256 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7257 return result;
7258 }
7259
Dan Egnorb7f03672009-12-09 16:22:32 -08007260 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7261 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007262 if (r.errorReportReceiver == null) {
7263 return null;
7264 }
7265
7266 if (!r.crashing && !r.notResponding) {
7267 return null;
7268 }
7269
Dan Egnorb7f03672009-12-09 16:22:32 -08007270 ApplicationErrorReport report = new ApplicationErrorReport();
7271 report.packageName = r.info.packageName;
7272 report.installerPackageName = r.errorReportReceiver.getPackageName();
7273 report.processName = r.processName;
7274 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007275 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007276
Dan Egnorb7f03672009-12-09 16:22:32 -08007277 if (r.crashing) {
7278 report.type = ApplicationErrorReport.TYPE_CRASH;
7279 report.crashInfo = crashInfo;
7280 } else if (r.notResponding) {
7281 report.type = ApplicationErrorReport.TYPE_ANR;
7282 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007283
Dan Egnorb7f03672009-12-09 16:22:32 -08007284 report.anrInfo.activity = r.notRespondingReport.tag;
7285 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7286 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007287 }
7288
Dan Egnorb7f03672009-12-09 16:22:32 -08007289 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007290 }
7291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7293 // assume our apps are happy - lazy create the list
7294 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7295
7296 synchronized (this) {
7297
7298 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007299 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7300 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007301 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7302 // This one's in trouble, so we'll generate a report for it
7303 // crashes are higher priority (in case there's a crash *and* an anr)
7304 ActivityManager.ProcessErrorStateInfo report = null;
7305 if (app.crashing) {
7306 report = app.crashingReport;
7307 } else if (app.notResponding) {
7308 report = app.notRespondingReport;
7309 }
7310
7311 if (report != null) {
7312 if (errList == null) {
7313 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7314 }
7315 errList.add(report);
7316 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007317 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 " crashing = " + app.crashing +
7319 " notResponding = " + app.notResponding);
7320 }
7321 }
7322 }
7323 }
7324
7325 return errList;
7326 }
7327
7328 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7329 // Lazy instantiation of list
7330 List<ActivityManager.RunningAppProcessInfo> runList = null;
7331 synchronized (this) {
7332 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007333 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7334 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7336 // Generate process state info for running application
7337 ActivityManager.RunningAppProcessInfo currApp =
7338 new ActivityManager.RunningAppProcessInfo(app.processName,
7339 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007340 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007341 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007342 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007343 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007344 if (app.persistent) {
7345 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007348 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7350 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7351 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007352 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7353 } else if (adj >= HOME_APP_ADJ) {
7354 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7355 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 } else if (adj >= SECONDARY_SERVER_ADJ) {
7357 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007358 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007359 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007360 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7361 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 } else if (adj >= VISIBLE_APP_ADJ) {
7363 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7364 } else {
7365 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7366 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007367 currApp.importanceReasonCode = app.adjTypeCode;
7368 if (app.adjSource instanceof ProcessRecord) {
7369 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007370 } else if (app.adjSource instanceof ActivityRecord) {
7371 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007372 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7373 }
7374 if (app.adjTarget instanceof ComponentName) {
7375 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7376 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007377 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 // + " lru=" + currApp.lru);
7379 if (runList == null) {
7380 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7381 }
7382 runList.add(currApp);
7383 }
7384 }
7385 }
7386 return runList;
7387 }
7388
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007389 public List<ApplicationInfo> getRunningExternalApplications() {
7390 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7391 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7392 if (runningApps != null && runningApps.size() > 0) {
7393 Set<String> extList = new HashSet<String>();
7394 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7395 if (app.pkgList != null) {
7396 for (String pkg : app.pkgList) {
7397 extList.add(pkg);
7398 }
7399 }
7400 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007401 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007402 for (String pkg : extList) {
7403 try {
7404 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7405 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7406 retList.add(info);
7407 }
7408 } catch (RemoteException e) {
7409 }
7410 }
7411 }
7412 return retList;
7413 }
7414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 @Override
7416 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007417 if (checkCallingPermission(android.Manifest.permission.DUMP)
7418 != PackageManager.PERMISSION_GRANTED) {
7419 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7420 + Binder.getCallingPid()
7421 + ", uid=" + Binder.getCallingUid()
7422 + " without permission "
7423 + android.Manifest.permission.DUMP);
7424 return;
7425 }
7426
7427 boolean dumpAll = false;
7428
7429 int opti = 0;
7430 while (opti < args.length) {
7431 String opt = args[opti];
7432 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7433 break;
7434 }
7435 opti++;
7436 if ("-a".equals(opt)) {
7437 dumpAll = true;
7438 } else if ("-h".equals(opt)) {
7439 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007440 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007441 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007442 pw.println(" a[ctivities]: activity stack state");
7443 pw.println(" b[roadcasts]: broadcast state");
7444 pw.println(" i[ntents]: pending intent state");
7445 pw.println(" p[rocesses]: process state");
7446 pw.println(" o[om]: out of memory management");
7447 pw.println(" prov[iders]: content provider state");
7448 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007449 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007450 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7451 pw.println(" a partial substring in a component name, or an");
7452 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007454 } else {
7455 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007456 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007457 }
7458
7459 // Is the caller requesting to dump a particular piece of data?
7460 if (opti < args.length) {
7461 String cmd = args[opti];
7462 opti++;
7463 if ("activities".equals(cmd) || "a".equals(cmd)) {
7464 synchronized (this) {
7465 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007467 return;
7468 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7469 synchronized (this) {
7470 dumpBroadcastsLocked(fd, pw, args, opti, true);
7471 }
7472 return;
7473 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7474 synchronized (this) {
7475 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7476 }
7477 return;
7478 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7479 synchronized (this) {
7480 dumpProcessesLocked(fd, pw, args, opti, true);
7481 }
7482 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007483 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7484 synchronized (this) {
7485 dumpOomLocked(fd, pw, args, opti, true);
7486 }
7487 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007488 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7489 synchronized (this) {
7490 dumpProvidersLocked(fd, pw, args, opti, true);
7491 }
7492 return;
7493 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007494 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007495 return;
7496 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7497 synchronized (this) {
7498 dumpServicesLocked(fd, pw, args, opti, true);
7499 }
7500 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007501 } else {
7502 // Dumping a single activity?
7503 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7504 return;
7505 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007506 pw.println("Bad activity command, or no activities match: " + cmd);
7507 pw.println("Use -h for help.");
7508 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007510 }
7511
7512 // No piece of data specified, dump everything.
7513 synchronized (this) {
7514 boolean needSep;
7515 if (dumpAll) {
7516 pw.println("Providers in Current Activity Manager State:");
7517 }
7518 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7519 if (needSep) {
7520 pw.println(" ");
7521 }
7522 if (dumpAll) {
7523 pw.println("-------------------------------------------------------------------------------");
7524 pw.println("Broadcasts in Current Activity Manager State:");
7525 }
7526 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7527 if (needSep) {
7528 pw.println(" ");
7529 }
7530 if (dumpAll) {
7531 pw.println("-------------------------------------------------------------------------------");
7532 pw.println("Services in Current Activity Manager State:");
7533 }
7534 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7535 if (needSep) {
7536 pw.println(" ");
7537 }
7538 if (dumpAll) {
7539 pw.println("-------------------------------------------------------------------------------");
7540 pw.println("PendingIntents in Current Activity Manager State:");
7541 }
7542 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7543 if (needSep) {
7544 pw.println(" ");
7545 }
7546 if (dumpAll) {
7547 pw.println("-------------------------------------------------------------------------------");
7548 pw.println("Activities in Current Activity Manager State:");
7549 }
7550 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7551 if (needSep) {
7552 pw.println(" ");
7553 }
7554 if (dumpAll) {
7555 pw.println("-------------------------------------------------------------------------------");
7556 pw.println("Processes in Current Activity Manager State:");
7557 }
7558 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7559 }
7560 }
7561
7562 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7563 int opti, boolean dumpAll, boolean needHeader) {
7564 if (needHeader) {
7565 pw.println(" Activity stack:");
7566 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007567 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007568 pw.println(" ");
7569 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007570 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7571 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007573 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007574 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007575 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007576 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007577 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007578 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007579 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007580 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007581 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7582 pw.println(" ");
7583 pw.println(" Activities waiting to sleep:");
7584 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7585 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007586 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007587 pw.println(" ");
7588 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007589 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007592 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007593 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7594 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007595 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007596 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007597 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007599 if (dumpAll && mRecentTasks.size() > 0) {
7600 pw.println(" ");
7601 pw.println("Recent tasks in Current Activity Manager State:");
7602
7603 final int N = mRecentTasks.size();
7604 for (int i=0; i<N; i++) {
7605 TaskRecord tr = mRecentTasks.get(i);
7606 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7607 pw.println(tr);
7608 mRecentTasks.get(i).dump(pw, " ");
7609 }
7610 }
7611
7612 pw.println(" ");
7613 pw.println(" mCurTask: " + mCurTask);
7614
7615 return true;
7616 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007617
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007618 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7619 int opti, boolean dumpAll) {
7620 boolean needSep = false;
7621 int numPers = 0;
7622
7623 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7625 final int NA = procs.size();
7626 for (int ia=0; ia<NA; ia++) {
7627 if (!needSep) {
7628 pw.println(" All known processes:");
7629 needSep = true;
7630 }
7631 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007632 pw.print(r.persistent ? " *PERS*" : " *APP*");
7633 pw.print(" UID "); pw.print(procs.keyAt(ia));
7634 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 r.dump(pw, " ");
7636 if (r.persistent) {
7637 numPers++;
7638 }
7639 }
7640 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007641 }
7642
7643 if (mLruProcesses.size() > 0) {
7644 if (needSep) pw.println(" ");
7645 needSep = true;
7646 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007647 dumpProcessOomList(pw, this, mLruProcesses, " ",
7648 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007649 needSep = true;
7650 }
7651
7652 synchronized (mPidsSelfLocked) {
7653 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 if (needSep) pw.println(" ");
7655 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007656 pw.println(" PID mappings:");
7657 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7658 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7659 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 }
7661 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007662 }
7663
7664 if (mForegroundProcesses.size() > 0) {
7665 if (needSep) pw.println(" ");
7666 needSep = true;
7667 pw.println(" Foreground Processes:");
7668 for (int i=0; i<mForegroundProcesses.size(); i++) {
7669 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7670 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007672 }
7673
7674 if (mPersistentStartingProcesses.size() > 0) {
7675 if (needSep) pw.println(" ");
7676 needSep = true;
7677 pw.println(" Persisent processes that are starting:");
7678 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007679 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007682 if (mStartingProcesses.size() > 0) {
7683 if (needSep) pw.println(" ");
7684 needSep = true;
7685 pw.println(" Processes that are starting:");
7686 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007687 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007690 if (mRemovedProcesses.size() > 0) {
7691 if (needSep) pw.println(" ");
7692 needSep = true;
7693 pw.println(" Processes that are being removed:");
7694 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007695 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007696 }
7697
7698 if (mProcessesOnHold.size() > 0) {
7699 if (needSep) pw.println(" ");
7700 needSep = true;
7701 pw.println(" Processes that are on old until the system is ready:");
7702 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007703 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705
Dianne Hackborn287952c2010-09-22 22:34:31 -07007706 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007707
7708 if (mProcessCrashTimes.getMap().size() > 0) {
7709 if (needSep) pw.println(" ");
7710 needSep = true;
7711 pw.println(" Time since processes crashed:");
7712 long now = SystemClock.uptimeMillis();
7713 for (Map.Entry<String, SparseArray<Long>> procs
7714 : mProcessCrashTimes.getMap().entrySet()) {
7715 SparseArray<Long> uids = procs.getValue();
7716 final int N = uids.size();
7717 for (int i=0; i<N; i++) {
7718 pw.print(" Process "); pw.print(procs.getKey());
7719 pw.print(" uid "); pw.print(uids.keyAt(i));
7720 pw.print(": last crashed ");
7721 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007722 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007723 }
7724 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007727 if (mBadProcesses.getMap().size() > 0) {
7728 if (needSep) pw.println(" ");
7729 needSep = true;
7730 pw.println(" Bad processes:");
7731 for (Map.Entry<String, SparseArray<Long>> procs
7732 : mBadProcesses.getMap().entrySet()) {
7733 SparseArray<Long> uids = procs.getValue();
7734 final int N = uids.size();
7735 for (int i=0; i<N; i++) {
7736 pw.print(" Bad process "); pw.print(procs.getKey());
7737 pw.print(" uid "); pw.print(uids.keyAt(i));
7738 pw.print(": crashed at time ");
7739 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 }
7741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007743
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007744 pw.println(" ");
7745 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007746 if (mHeavyWeightProcess != null) {
7747 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7748 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007749 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007750 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007751 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7752 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7753 || mOrigWaitForDebugger) {
7754 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7755 + " mDebugTransient=" + mDebugTransient
7756 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7757 }
7758 if (mAlwaysFinishActivities || mController != null) {
7759 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7760 + " mController=" + mController);
7761 }
7762 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007765 + " mProcessesReady=" + mProcessesReady
7766 + " mSystemReady=" + mSystemReady);
7767 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 + " mBooted=" + mBooted
7769 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007770 pw.print(" mLastPowerCheckRealtime=");
7771 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7772 pw.println("");
7773 pw.print(" mLastPowerCheckUptime=");
7774 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7775 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007776 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7777 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007778 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007780
7781 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 }
7783
Dianne Hackborn287952c2010-09-22 22:34:31 -07007784 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7785 int opti, boolean needSep, boolean dumpAll) {
7786 if (mProcessesToGc.size() > 0) {
7787 if (needSep) pw.println(" ");
7788 needSep = true;
7789 pw.println(" Processes that are waiting to GC:");
7790 long now = SystemClock.uptimeMillis();
7791 for (int i=0; i<mProcessesToGc.size(); i++) {
7792 ProcessRecord proc = mProcessesToGc.get(i);
7793 pw.print(" Process "); pw.println(proc);
7794 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7795 pw.print(", last gced=");
7796 pw.print(now-proc.lastRequestedGc);
7797 pw.print(" ms ago, last lowMem=");
7798 pw.print(now-proc.lastLowMemory);
7799 pw.println(" ms ago");
7800
7801 }
7802 }
7803 return needSep;
7804 }
7805
7806 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7807 int opti, boolean dumpAll) {
7808 boolean needSep = false;
7809
7810 if (mLruProcesses.size() > 0) {
7811 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7812
7813 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7814 @Override
7815 public int compare(ProcessRecord object1, ProcessRecord object2) {
7816 if (object1.setAdj != object2.setAdj) {
7817 return object1.setAdj > object2.setAdj ? -1 : 1;
7818 }
7819 if (object1.setSchedGroup != object2.setSchedGroup) {
7820 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7821 }
7822 if (object1.keeping != object2.keeping) {
7823 return object1.keeping ? -1 : 1;
7824 }
7825 if (object1.pid != object2.pid) {
7826 return object1.pid > object2.pid ? -1 : 1;
7827 }
7828 return 0;
7829 }
7830 };
7831
7832 Collections.sort(procs, comparator);
7833
7834 if (needSep) pw.println(" ");
7835 needSep = true;
7836 pw.println(" Process OOM control:");
7837 dumpProcessOomList(pw, this, procs, " ",
7838 "Proc", "PERS", true);
7839 needSep = true;
7840 }
7841
7842 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7843
7844 pw.println(" ");
7845 pw.println(" mHomeProcess: " + mHomeProcess);
7846 if (mHeavyWeightProcess != null) {
7847 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7848 }
7849
7850 return true;
7851 }
7852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 /**
7854 * There are three ways to call this:
7855 * - no service specified: dump all the services
7856 * - a flattened component name that matched an existing service was specified as the
7857 * first arg: dump that one service
7858 * - the first arg isn't the flattened component name of an existing service:
7859 * dump all services whose component contains the first arg as a substring
7860 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007861 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 String[] newArgs;
7863 String componentNameString;
7864 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007865 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 componentNameString = null;
7867 newArgs = EMPTY_STRING_ARRAY;
7868 r = null;
7869 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007870 componentNameString = args[opti];
7871 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007873 synchronized (this) {
7874 r = componentName != null ? mServices.get(componentName) : null;
7875 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007876 newArgs = new String[args.length - opti];
7877 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 }
7879
7880 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007881 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007883 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7884 synchronized (this) {
7885 for (ServiceRecord r1 : mServices.values()) {
7886 if (componentNameString == null
7887 || r1.name.flattenToString().contains(componentNameString)) {
7888 services.add(r1);
7889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 }
7891 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007892 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007893 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 }
7896 }
7897
7898 /**
7899 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7900 * there is a thread associated with the service.
7901 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007902 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7903 pw.println("------------------------------------------------------------"
7904 + "-------------------");
7905 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 if (r.app != null && r.app.thread != null) {
7907 try {
7908 // flush anything that is already in the PrintWriter since the thread is going
7909 // to write to the file descriptor directly
7910 pw.flush();
7911 r.app.thread.dumpService(fd, r, args);
7912 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007913 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 } catch (RemoteException e) {
7915 pw.println("got a RemoteException while dumping the service");
7916 }
7917 }
7918 }
7919
Dianne Hackborn625ac272010-09-17 18:29:22 -07007920 /**
7921 * There are three things that cmd can be:
7922 * - a flattened component name that matched an existing activity
7923 * - the cmd arg isn't the flattened component name of an existing activity:
7924 * dump all activity whose component contains the cmd as a substring
7925 * - A hex number of the ActivityRecord object instance.
7926 */
7927 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7928 int opti, boolean dumpAll) {
7929 String[] newArgs;
7930 ComponentName componentName = ComponentName.unflattenFromString(name);
7931 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007932 if (componentName == null) {
7933 // Not a '/' separated full component name; maybe an object ID?
7934 try {
7935 objectId = Integer.parseInt(name, 16);
7936 name = null;
7937 componentName = null;
7938 } catch (RuntimeException e) {
7939 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007940 }
7941 newArgs = new String[args.length - opti];
7942 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7943
7944 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7945 synchronized (this) {
7946 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7947 if (componentName != null) {
7948 if (r1.intent.getComponent().equals(componentName)) {
7949 activities.add(r1);
7950 }
7951 } else if (name != null) {
7952 if (r1.intent.getComponent().flattenToString().contains(name)) {
7953 activities.add(r1);
7954 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007955 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007956 activities.add(r1);
7957 }
7958 }
7959 }
7960
7961 if (activities.size() <= 0) {
7962 return false;
7963 }
7964
Dianne Hackborn30d71892010-12-11 10:37:55 -08007965 TaskRecord lastTask = null;
7966 for (int i=activities.size()-1; i>=0; i--) {
7967 ActivityRecord r = (ActivityRecord)activities.get(i);
7968 if (lastTask != r.task) {
7969 lastTask = r.task;
7970 pw.print("* Task "); pw.print(lastTask.affinity);
7971 pw.print(" id="); pw.println(lastTask.taskId);
7972 if (dumpAll) {
7973 lastTask.dump(pw, " ");
7974 }
7975 }
7976 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007977 }
7978 return true;
7979 }
7980
7981 /**
7982 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7983 * there is a thread associated with the activity.
7984 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007985 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7986 ActivityRecord r, String[] args, boolean dumpAll) {
7987 synchronized (this) {
7988 pw.print(prefix); pw.print("* Activity ");
7989 pw.print(Integer.toHexString(System.identityHashCode(r)));
7990 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7991 if (r.app != null) pw.println(r.app.pid);
7992 else pw.println("(not running)");
7993 if (dumpAll) {
7994 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007995 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007996 }
7997 if (r.app != null && r.app.thread != null) {
7998 try {
7999 // flush anything that is already in the PrintWriter since the thread is going
8000 // to write to the file descriptor directly
8001 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08008002 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008003 pw.flush();
8004 } catch (RemoteException e) {
8005 pw.println("got a RemoteException while dumping the activity");
8006 }
8007 }
8008 }
8009
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008010 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8011 int opti, boolean dumpAll) {
8012 boolean needSep = false;
8013
8014 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 if (mRegisteredReceivers.size() > 0) {
8016 pw.println(" ");
8017 pw.println(" Registered Receivers:");
8018 Iterator it = mRegisteredReceivers.values().iterator();
8019 while (it.hasNext()) {
8020 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008021 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 r.dump(pw, " ");
8023 }
8024 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 pw.println(" ");
8027 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008028 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008029 needSep = true;
8030 }
8031
8032 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8033 || mPendingBroadcast != null) {
8034 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008036 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008038 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8039 pw.println(" Broadcast #" + i + ":");
8040 mParallelBroadcasts.get(i).dump(pw, " ");
8041 }
8042 if (mOrderedBroadcasts.size() > 0) {
8043 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008044 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008045 }
8046 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8047 pw.println(" Serialized Broadcast #" + i + ":");
8048 mOrderedBroadcasts.get(i).dump(pw, " ");
8049 }
8050 pw.println(" ");
8051 pw.println(" Pending broadcast:");
8052 if (mPendingBroadcast != null) {
8053 mPendingBroadcast.dump(pw, " ");
8054 } else {
8055 pw.println(" (null)");
8056 }
8057 needSep = true;
8058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008060 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008062 pw.println(" Historical broadcasts:");
8063 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8064 BroadcastRecord r = mBroadcastHistory[i];
8065 if (r == null) {
8066 break;
8067 }
8068 pw.println(" Historical Broadcast #" + i + ":");
8069 r.dump(pw, " ");
8070 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008071 needSep = true;
8072 }
8073
8074 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008075 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008076 pw.println(" Sticky broadcasts:");
8077 StringBuilder sb = new StringBuilder(128);
8078 for (Map.Entry<String, ArrayList<Intent>> ent
8079 : mStickyBroadcasts.entrySet()) {
8080 pw.print(" * Sticky action "); pw.print(ent.getKey());
8081 pw.println(":");
8082 ArrayList<Intent> intents = ent.getValue();
8083 final int N = intents.size();
8084 for (int i=0; i<N; i++) {
8085 sb.setLength(0);
8086 sb.append(" Intent: ");
8087 intents.get(i).toShortString(sb, true, false);
8088 pw.println(sb.toString());
8089 Bundle bundle = intents.get(i).getExtras();
8090 if (bundle != null) {
8091 pw.print(" ");
8092 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093 }
8094 }
8095 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008096 needSep = true;
8097 }
8098
8099 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008101 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008102 pw.println(" mHandler:");
8103 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008104 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008105 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008106
8107 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 }
8109
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008110 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8111 int opti, boolean dumpAll) {
8112 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008114 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 if (mServices.size() > 0) {
8116 pw.println(" Active services:");
8117 Iterator<ServiceRecord> it = mServices.values().iterator();
8118 while (it.hasNext()) {
8119 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008120 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 r.dump(pw, " ");
8122 }
8123 needSep = true;
8124 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008126
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008127 if (mPendingServices.size() > 0) {
8128 if (needSep) pw.println(" ");
8129 pw.println(" Pending services:");
8130 for (int i=0; i<mPendingServices.size(); i++) {
8131 ServiceRecord r = mPendingServices.get(i);
8132 pw.print(" * Pending "); pw.println(r);
8133 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008135 needSep = true;
8136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008138 if (mRestartingServices.size() > 0) {
8139 if (needSep) pw.println(" ");
8140 pw.println(" Restarting services:");
8141 for (int i=0; i<mRestartingServices.size(); i++) {
8142 ServiceRecord r = mRestartingServices.get(i);
8143 pw.print(" * Restarting "); pw.println(r);
8144 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008146 needSep = true;
8147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008148
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008149 if (mStoppingServices.size() > 0) {
8150 if (needSep) pw.println(" ");
8151 pw.println(" Stopping services:");
8152 for (int i=0; i<mStoppingServices.size(); i++) {
8153 ServiceRecord r = mStoppingServices.get(i);
8154 pw.print(" * Stopping "); pw.println(r);
8155 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008157 needSep = true;
8158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008160 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 if (mServiceConnections.size() > 0) {
8162 if (needSep) pw.println(" ");
8163 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008164 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 = mServiceConnections.values().iterator();
8166 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008167 ArrayList<ConnectionRecord> r = it.next();
8168 for (int i=0; i<r.size(); i++) {
8169 pw.print(" * "); pw.println(r.get(i));
8170 r.get(i).dump(pw, " ");
8171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008173 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 }
8175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008176
8177 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 }
8179
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008180 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8181 int opti, boolean dumpAll) {
8182 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008184 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 if (mProvidersByClass.size() > 0) {
8186 if (needSep) pw.println(" ");
8187 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008188 Iterator<Map.Entry<String, ContentProviderRecord>> it
8189 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008191 Map.Entry<String, ContentProviderRecord> e = it.next();
8192 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008193 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 r.dump(pw, " ");
8195 }
8196 needSep = true;
8197 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008198
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008199 if (mProvidersByName.size() > 0) {
8200 pw.println(" ");
8201 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008202 Iterator<Map.Entry<String, ContentProviderRecord>> it
8203 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008204 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008205 Map.Entry<String, ContentProviderRecord> e = it.next();
8206 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008207 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8208 pw.println(r);
8209 }
8210 needSep = true;
8211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008213
8214 if (mLaunchingProviders.size() > 0) {
8215 if (needSep) pw.println(" ");
8216 pw.println(" Launching content providers:");
8217 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8218 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8219 pw.println(mLaunchingProviders.get(i));
8220 }
8221 needSep = true;
8222 }
8223
8224 if (mGrantedUriPermissions.size() > 0) {
8225 pw.println();
8226 pw.println("Granted Uri Permissions:");
8227 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8228 int uid = mGrantedUriPermissions.keyAt(i);
8229 HashMap<Uri, UriPermission> perms
8230 = mGrantedUriPermissions.valueAt(i);
8231 pw.print(" * UID "); pw.print(uid);
8232 pw.println(" holds:");
8233 for (UriPermission perm : perms.values()) {
8234 pw.print(" "); pw.println(perm);
8235 perm.dump(pw, " ");
8236 }
8237 }
8238 needSep = true;
8239 }
8240
8241 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008242 }
8243
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008244 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8245 int opti, boolean dumpAll) {
8246 boolean needSep = false;
8247
8248 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 if (this.mIntentSenderRecords.size() > 0) {
8250 Iterator<WeakReference<PendingIntentRecord>> it
8251 = mIntentSenderRecords.values().iterator();
8252 while (it.hasNext()) {
8253 WeakReference<PendingIntentRecord> ref = it.next();
8254 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008255 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008257 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008258 rec.dump(pw, " ");
8259 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008260 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 }
8262 }
8263 }
8264 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008265
8266 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008267 }
8268
8269 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008270 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 TaskRecord lastTask = null;
8272 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008273 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008274 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 if (lastTask != r.task) {
8276 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008277 pw.print(prefix);
8278 pw.print(full ? "* " : " ");
8279 pw.println(lastTask);
8280 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008281 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008284 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8285 pw.print(" #"); pw.print(i); pw.print(": ");
8286 pw.println(r);
8287 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008288 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008290 }
8291 }
8292
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008293 private static String buildOomTag(String prefix, String space, int val, int base) {
8294 if (val == base) {
8295 if (space == null) return prefix;
8296 return prefix + " ";
8297 }
8298 return prefix + "+" + Integer.toString(val-base);
8299 }
8300
8301 private static final int dumpProcessList(PrintWriter pw,
8302 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008303 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008305 final int N = list.size()-1;
8306 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008307 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008308 pw.println(String.format("%s%s #%2d: %s",
8309 prefix, (r.persistent ? persistentLabel : normalLabel),
8310 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 if (r.persistent) {
8312 numPers++;
8313 }
8314 }
8315 return numPers;
8316 }
8317
Dianne Hackborn287952c2010-09-22 22:34:31 -07008318 private static final void dumpProcessOomList(PrintWriter pw,
8319 ActivityManagerService service, List<ProcessRecord> list,
8320 String prefix, String normalLabel, String persistentLabel,
8321 boolean inclDetails) {
8322
8323 final long curRealtime = SystemClock.elapsedRealtime();
8324 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8325 final long curUptime = SystemClock.uptimeMillis();
8326 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8327
8328 final int N = list.size()-1;
8329 for (int i=N; i>=0; i--) {
8330 ProcessRecord r = list.get(i);
8331 String oomAdj;
8332 if (r.setAdj >= EMPTY_APP_ADJ) {
8333 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8334 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8335 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8336 } else if (r.setAdj >= HOME_APP_ADJ) {
8337 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8338 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8339 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8340 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8341 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8342 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8343 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8344 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8345 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8346 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8347 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8348 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8349 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8350 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8351 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8352 } else if (r.setAdj >= SYSTEM_ADJ) {
8353 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8354 } else {
8355 oomAdj = Integer.toString(r.setAdj);
8356 }
8357 String schedGroup;
8358 switch (r.setSchedGroup) {
8359 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8360 schedGroup = "B";
8361 break;
8362 case Process.THREAD_GROUP_DEFAULT:
8363 schedGroup = "F";
8364 break;
8365 default:
8366 schedGroup = Integer.toString(r.setSchedGroup);
8367 break;
8368 }
8369 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8370 prefix, (r.persistent ? persistentLabel : normalLabel),
8371 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8372 if (r.adjSource != null || r.adjTarget != null) {
8373 pw.print(prefix);
8374 pw.print(" ");
8375 if (r.adjTarget instanceof ComponentName) {
8376 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8377 } else if (r.adjTarget != null) {
8378 pw.print(r.adjTarget.toString());
8379 } else {
8380 pw.print("{null}");
8381 }
8382 pw.print("<=");
8383 if (r.adjSource instanceof ProcessRecord) {
8384 pw.print("Proc{");
8385 pw.print(((ProcessRecord)r.adjSource).toShortString());
8386 pw.println("}");
8387 } else if (r.adjSource != null) {
8388 pw.println(r.adjSource.toString());
8389 } else {
8390 pw.println("{null}");
8391 }
8392 }
8393 if (inclDetails) {
8394 pw.print(prefix);
8395 pw.print(" ");
8396 pw.print("oom: max="); pw.print(r.maxAdj);
8397 pw.print(" hidden="); pw.print(r.hiddenAdj);
8398 pw.print(" curRaw="); pw.print(r.curRawAdj);
8399 pw.print(" setRaw="); pw.print(r.setRawAdj);
8400 pw.print(" cur="); pw.print(r.curAdj);
8401 pw.print(" set="); pw.println(r.setAdj);
8402 pw.print(prefix);
8403 pw.print(" ");
8404 pw.print("keeping="); pw.print(r.keeping);
8405 pw.print(" hidden="); pw.print(r.hidden);
8406 pw.print(" empty="); pw.println(r.empty);
8407
8408 if (!r.keeping) {
8409 if (r.lastWakeTime != 0) {
8410 long wtime;
8411 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8412 synchronized (stats) {
8413 wtime = stats.getProcessWakeTime(r.info.uid,
8414 r.pid, curRealtime);
8415 }
8416 long timeUsed = wtime - r.lastWakeTime;
8417 pw.print(prefix);
8418 pw.print(" ");
8419 pw.print("keep awake over ");
8420 TimeUtils.formatDuration(realtimeSince, pw);
8421 pw.print(" used ");
8422 TimeUtils.formatDuration(timeUsed, pw);
8423 pw.print(" (");
8424 pw.print((timeUsed*100)/realtimeSince);
8425 pw.println("%)");
8426 }
8427 if (r.lastCpuTime != 0) {
8428 long timeUsed = r.curCpuTime - r.lastCpuTime;
8429 pw.print(prefix);
8430 pw.print(" ");
8431 pw.print("run cpu over ");
8432 TimeUtils.formatDuration(uptimeSince, pw);
8433 pw.print(" used ");
8434 TimeUtils.formatDuration(timeUsed, pw);
8435 pw.print(" (");
8436 pw.print((timeUsed*100)/uptimeSince);
8437 pw.println("%)");
8438 }
8439 }
8440 }
8441 }
8442 }
8443
Dianne Hackborn472ad872010-04-07 17:31:48 -07008444 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008446 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 long uptime = SystemClock.uptimeMillis();
8448 long realtime = SystemClock.elapsedRealtime();
8449
8450 if (isCheckinRequest) {
8451 // short checkin version
8452 pw.println(uptime + "," + realtime);
8453 pw.flush();
8454 } else {
8455 pw.println("Applications Memory Usage (kB):");
8456 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8457 }
8458 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8459 ProcessRecord r = (ProcessRecord)list.get(i);
8460 if (r.thread != null) {
8461 if (!isCheckinRequest) {
8462 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8463 pw.flush();
8464 }
8465 try {
8466 r.thread.asBinder().dump(fd, args);
8467 } catch (RemoteException e) {
8468 if (!isCheckinRequest) {
8469 pw.println("Got RemoteException!");
8470 pw.flush();
8471 }
8472 }
8473 }
8474 }
8475 }
8476
8477 /**
8478 * Searches array of arguments for the specified string
8479 * @param args array of argument strings
8480 * @param value value to search for
8481 * @return true if the value is contained in the array
8482 */
8483 private static boolean scanArgs(String[] args, String value) {
8484 if (args != null) {
8485 for (String arg : args) {
8486 if (value.equals(arg)) {
8487 return true;
8488 }
8489 }
8490 }
8491 return false;
8492 }
8493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 private final void killServicesLocked(ProcessRecord app,
8495 boolean allowRestart) {
8496 // Report disconnected services.
8497 if (false) {
8498 // XXX we are letting the client link to the service for
8499 // death notifications.
8500 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008501 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008503 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008505 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 = r.connections.values().iterator();
8507 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008508 ArrayList<ConnectionRecord> cl = jt.next();
8509 for (int i=0; i<cl.size(); i++) {
8510 ConnectionRecord c = cl.get(i);
8511 if (c.binding.client != app) {
8512 try {
8513 //c.conn.connected(r.className, null);
8514 } catch (Exception e) {
8515 // todo: this should be asynchronous!
8516 Slog.w(TAG, "Exception thrown disconnected servce "
8517 + r.shortName
8518 + " from app " + app.processName, e);
8519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 }
8521 }
8522 }
8523 }
8524 }
8525 }
8526 }
8527
8528 // Clean up any connections this application has to other services.
8529 if (app.connections.size() > 0) {
8530 Iterator<ConnectionRecord> it = app.connections.iterator();
8531 while (it.hasNext()) {
8532 ConnectionRecord r = it.next();
8533 removeConnectionLocked(r, app, null);
8534 }
8535 }
8536 app.connections.clear();
8537
8538 if (app.services.size() != 0) {
8539 // Any services running in the application need to be placed
8540 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008541 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008543 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 synchronized (sr.stats.getBatteryStats()) {
8545 sr.stats.stopLaunchedLocked();
8546 }
8547 sr.app = null;
8548 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008549 if (mStoppingServices.remove(sr)) {
8550 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8551 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008552
8553 boolean hasClients = sr.bindings.size() > 0;
8554 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 Iterator<IntentBindRecord> bindings
8556 = sr.bindings.values().iterator();
8557 while (bindings.hasNext()) {
8558 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008559 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008560 + ": shouldUnbind=" + b.hasBound);
8561 b.binder = null;
8562 b.requested = b.received = b.hasBound = false;
8563 }
8564 }
8565
Dianne Hackborn070783f2010-12-29 16:46:28 -08008566 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8567 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008568 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008570 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 sr.crashCount, sr.shortName, app.pid);
8572 bringDownServiceLocked(sr, true);
8573 } else if (!allowRestart) {
8574 bringDownServiceLocked(sr, true);
8575 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008576 boolean canceled = scheduleServiceRestartLocked(sr, true);
8577
8578 // Should the service remain running? Note that in the
8579 // extreme case of so many attempts to deliver a command
8580 // that it failed, that we also will stop it here.
8581 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8582 if (sr.pendingStarts.size() == 0) {
8583 sr.startRequested = false;
8584 if (!hasClients) {
8585 // Whoops, no reason to restart!
8586 bringDownServiceLocked(sr, true);
8587 }
8588 }
8589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008590 }
8591 }
8592
8593 if (!allowRestart) {
8594 app.services.clear();
8595 }
8596 }
8597
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008598 // Make sure we have no more records on the stopping list.
8599 int i = mStoppingServices.size();
8600 while (i > 0) {
8601 i--;
8602 ServiceRecord sr = mStoppingServices.get(i);
8603 if (sr.app == app) {
8604 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008605 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008606 }
8607 }
8608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 app.executingServices.clear();
8610 }
8611
8612 private final void removeDyingProviderLocked(ProcessRecord proc,
8613 ContentProviderRecord cpr) {
8614 synchronized (cpr) {
8615 cpr.launchingApp = null;
8616 cpr.notifyAll();
8617 }
8618
8619 mProvidersByClass.remove(cpr.info.name);
8620 String names[] = cpr.info.authority.split(";");
8621 for (int j = 0; j < names.length; j++) {
8622 mProvidersByName.remove(names[j]);
8623 }
8624
8625 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8626 while (cit.hasNext()) {
8627 ProcessRecord capp = cit.next();
8628 if (!capp.persistent && capp.thread != null
8629 && capp.pid != 0
8630 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008631 Slog.i(TAG, "Kill " + capp.processName
8632 + " (pid " + capp.pid + "): provider " + cpr.info.name
8633 + " in dying process " + proc.processName);
8634 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8635 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 Process.killProcess(capp.pid);
8637 }
8638 }
8639
8640 mLaunchingProviders.remove(cpr);
8641 }
8642
8643 /**
8644 * Main code for cleaning up a process when it has gone away. This is
8645 * called both as a result of the process dying, or directly when stopping
8646 * a process when running in single process mode.
8647 */
8648 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8649 boolean restarting, int index) {
8650 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008651 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 }
8653
Dianne Hackborn36124872009-10-08 16:22:03 -07008654 mProcessesToGc.remove(app);
8655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 // Dismiss any open dialogs.
8657 if (app.crashDialog != null) {
8658 app.crashDialog.dismiss();
8659 app.crashDialog = null;
8660 }
8661 if (app.anrDialog != null) {
8662 app.anrDialog.dismiss();
8663 app.anrDialog = null;
8664 }
8665 if (app.waitDialog != null) {
8666 app.waitDialog.dismiss();
8667 app.waitDialog = null;
8668 }
8669
8670 app.crashing = false;
8671 app.notResponding = false;
8672
8673 app.resetPackageList();
8674 app.thread = null;
8675 app.forcingToForeground = null;
8676 app.foregroundServices = false;
8677
8678 killServicesLocked(app, true);
8679
8680 boolean restart = false;
8681
8682 int NL = mLaunchingProviders.size();
8683
8684 // Remove published content providers.
8685 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008686 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008688 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 cpr.provider = null;
8690 cpr.app = null;
8691
8692 // See if someone is waiting for this provider... in which
8693 // case we don't remove it, but just let it restart.
8694 int i = 0;
8695 if (!app.bad) {
8696 for (; i<NL; i++) {
8697 if (mLaunchingProviders.get(i) == cpr) {
8698 restart = true;
8699 break;
8700 }
8701 }
8702 } else {
8703 i = NL;
8704 }
8705
8706 if (i >= NL) {
8707 removeDyingProviderLocked(app, cpr);
8708 NL = mLaunchingProviders.size();
8709 }
8710 }
8711 app.pubProviders.clear();
8712 }
8713
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008714 // Take care of any launching providers waiting for this process.
8715 if (checkAppInLaunchingProvidersLocked(app, false)) {
8716 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008719 // Unregister from connected content providers.
8720 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008721 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008722 while (it.hasNext()) {
8723 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8724 cpr.clients.remove(app);
8725 }
8726 app.conProviders.clear();
8727 }
8728
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008729 // At this point there may be remaining entries in mLaunchingProviders
8730 // where we were the only one waiting, so they are no longer of use.
8731 // Look for these and clean up if found.
8732 // XXX Commented out for now. Trying to figure out a way to reproduce
8733 // the actual situation to identify what is actually going on.
8734 if (false) {
8735 for (int i=0; i<NL; i++) {
8736 ContentProviderRecord cpr = (ContentProviderRecord)
8737 mLaunchingProviders.get(i);
8738 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8739 synchronized (cpr) {
8740 cpr.launchingApp = null;
8741 cpr.notifyAll();
8742 }
8743 }
8744 }
8745 }
8746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 skipCurrentReceiverLocked(app);
8748
8749 // Unregister any receivers.
8750 if (app.receivers.size() > 0) {
8751 Iterator<ReceiverList> it = app.receivers.iterator();
8752 while (it.hasNext()) {
8753 removeReceiverLocked(it.next());
8754 }
8755 app.receivers.clear();
8756 }
8757
Christopher Tate181fafa2009-05-14 11:12:14 -07008758 // If the app is undergoing backup, tell the backup manager about it
8759 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008760 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008761 try {
8762 IBackupManager bm = IBackupManager.Stub.asInterface(
8763 ServiceManager.getService(Context.BACKUP_SERVICE));
8764 bm.agentDisconnected(app.info.packageName);
8765 } catch (RemoteException e) {
8766 // can't happen; backup manager is local
8767 }
8768 }
8769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770 // If the caller is restarting this app, then leave it in its
8771 // current lists and let the caller take care of it.
8772 if (restarting) {
8773 return;
8774 }
8775
8776 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008777 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778 "Removing non-persistent process during cleanup: " + app);
8779 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008780 if (mHeavyWeightProcess == app) {
8781 mHeavyWeightProcess = null;
8782 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 } else if (!app.removed) {
8785 // This app is persistent, so we need to keep its record around.
8786 // If it is not already on the pending app list, add it there
8787 // and start a new process for it.
8788 app.thread = null;
8789 app.forcingToForeground = null;
8790 app.foregroundServices = false;
8791 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8792 mPersistentStartingProcesses.add(app);
8793 restart = true;
8794 }
8795 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008796 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8797 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008798 mProcessesOnHold.remove(app);
8799
The Android Open Source Project4df24232009-03-05 14:34:35 -08008800 if (app == mHomeProcess) {
8801 mHomeProcess = null;
8802 }
8803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 if (restart) {
8805 // We have components that still need to be running in the
8806 // process, so re-launch it.
8807 mProcessNames.put(app.processName, app.info.uid, app);
8808 startProcessLocked(app, "restart", app.processName);
8809 } else if (app.pid > 0 && app.pid != MY_PID) {
8810 // Goodbye!
8811 synchronized (mPidsSelfLocked) {
8812 mPidsSelfLocked.remove(app.pid);
8813 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8814 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008815 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 }
8817 }
8818
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008819 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8820 // Look through the content providers we are waiting to have launched,
8821 // and if any run in this process then either schedule a restart of
8822 // the process or kill the client waiting for it if this process has
8823 // gone bad.
8824 int NL = mLaunchingProviders.size();
8825 boolean restart = false;
8826 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008827 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008828 if (cpr.launchingApp == app) {
8829 if (!alwaysBad && !app.bad) {
8830 restart = true;
8831 } else {
8832 removeDyingProviderLocked(app, cpr);
8833 NL = mLaunchingProviders.size();
8834 }
8835 }
8836 }
8837 return restart;
8838 }
8839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 // =========================================================
8841 // SERVICES
8842 // =========================================================
8843
8844 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8845 ActivityManager.RunningServiceInfo info =
8846 new ActivityManager.RunningServiceInfo();
8847 info.service = r.name;
8848 if (r.app != null) {
8849 info.pid = r.app.pid;
8850 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008851 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008852 info.process = r.processName;
8853 info.foreground = r.isForeground;
8854 info.activeSince = r.createTime;
8855 info.started = r.startRequested;
8856 info.clientCount = r.connections.size();
8857 info.crashCount = r.crashCount;
8858 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008859 if (r.isForeground) {
8860 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8861 }
8862 if (r.startRequested) {
8863 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8864 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008865 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008866 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8867 }
8868 if (r.app != null && r.app.persistent) {
8869 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8870 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008871
8872 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8873 for (int i=0; i<connl.size(); i++) {
8874 ConnectionRecord conn = connl.get(i);
8875 if (conn.clientLabel != 0) {
8876 info.clientPackage = conn.binding.client.info.packageName;
8877 info.clientLabel = conn.clientLabel;
8878 return info;
8879 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008880 }
8881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008882 return info;
8883 }
8884
8885 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8886 int flags) {
8887 synchronized (this) {
8888 ArrayList<ActivityManager.RunningServiceInfo> res
8889 = new ArrayList<ActivityManager.RunningServiceInfo>();
8890
8891 if (mServices.size() > 0) {
8892 Iterator<ServiceRecord> it = mServices.values().iterator();
8893 while (it.hasNext() && res.size() < maxNum) {
8894 res.add(makeRunningServiceInfoLocked(it.next()));
8895 }
8896 }
8897
8898 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8899 ServiceRecord r = mRestartingServices.get(i);
8900 ActivityManager.RunningServiceInfo info =
8901 makeRunningServiceInfoLocked(r);
8902 info.restarting = r.nextRestartTime;
8903 res.add(info);
8904 }
8905
8906 return res;
8907 }
8908 }
8909
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008910 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8911 synchronized (this) {
8912 ServiceRecord r = mServices.get(name);
8913 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008914 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8915 for (int i=0; i<conn.size(); i++) {
8916 if (conn.get(i).clientIntent != null) {
8917 return conn.get(i).clientIntent;
8918 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008919 }
8920 }
8921 }
8922 }
8923 return null;
8924 }
8925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 private final ServiceRecord findServiceLocked(ComponentName name,
8927 IBinder token) {
8928 ServiceRecord r = mServices.get(name);
8929 return r == token ? r : null;
8930 }
8931
8932 private final class ServiceLookupResult {
8933 final ServiceRecord record;
8934 final String permission;
8935
8936 ServiceLookupResult(ServiceRecord _record, String _permission) {
8937 record = _record;
8938 permission = _permission;
8939 }
8940 };
8941
8942 private ServiceLookupResult findServiceLocked(Intent service,
8943 String resolvedType) {
8944 ServiceRecord r = null;
8945 if (service.getComponent() != null) {
8946 r = mServices.get(service.getComponent());
8947 }
8948 if (r == null) {
8949 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8950 r = mServicesByIntent.get(filter);
8951 }
8952
8953 if (r == null) {
8954 try {
8955 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008956 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 service, resolvedType, 0);
8958 ServiceInfo sInfo =
8959 rInfo != null ? rInfo.serviceInfo : null;
8960 if (sInfo == null) {
8961 return null;
8962 }
8963
8964 ComponentName name = new ComponentName(
8965 sInfo.applicationInfo.packageName, sInfo.name);
8966 r = mServices.get(name);
8967 } catch (RemoteException ex) {
8968 // pm is in same process, this will never happen.
8969 }
8970 }
8971 if (r != null) {
8972 int callingPid = Binder.getCallingPid();
8973 int callingUid = Binder.getCallingUid();
8974 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008975 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008977 if (!r.exported) {
8978 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
8979 + " from pid=" + callingPid
8980 + ", uid=" + callingUid
8981 + " that is not exported from uid " + r.appInfo.uid);
8982 return new ServiceLookupResult(null, "not exported from uid "
8983 + r.appInfo.uid);
8984 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008985 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 + " from pid=" + callingPid
8987 + ", uid=" + callingUid
8988 + " requires " + r.permission);
8989 return new ServiceLookupResult(null, r.permission);
8990 }
8991 return new ServiceLookupResult(r, null);
8992 }
8993 return null;
8994 }
8995
8996 private class ServiceRestarter implements Runnable {
8997 private ServiceRecord mService;
8998
8999 void setService(ServiceRecord service) {
9000 mService = service;
9001 }
9002
9003 public void run() {
9004 synchronized(ActivityManagerService.this) {
9005 performServiceRestartLocked(mService);
9006 }
9007 }
9008 }
9009
9010 private ServiceLookupResult retrieveServiceLocked(Intent service,
9011 String resolvedType, int callingPid, int callingUid) {
9012 ServiceRecord r = null;
9013 if (service.getComponent() != null) {
9014 r = mServices.get(service.getComponent());
9015 }
9016 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9017 r = mServicesByIntent.get(filter);
9018 if (r == null) {
9019 try {
9020 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009021 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009022 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009023 ServiceInfo sInfo =
9024 rInfo != null ? rInfo.serviceInfo : null;
9025 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 ": not found");
9028 return null;
9029 }
9030
9031 ComponentName name = new ComponentName(
9032 sInfo.applicationInfo.packageName, sInfo.name);
9033 r = mServices.get(name);
9034 if (r == null) {
9035 filter = new Intent.FilterComparison(service.cloneFilter());
9036 ServiceRestarter res = new ServiceRestarter();
9037 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9038 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9039 synchronized (stats) {
9040 ss = stats.getServiceStatsLocked(
9041 sInfo.applicationInfo.uid, sInfo.packageName,
9042 sInfo.name);
9043 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009044 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 res.setService(r);
9046 mServices.put(name, r);
9047 mServicesByIntent.put(filter, r);
9048
9049 // Make sure this component isn't in the pending list.
9050 int N = mPendingServices.size();
9051 for (int i=0; i<N; i++) {
9052 ServiceRecord pr = mPendingServices.get(i);
9053 if (pr.name.equals(name)) {
9054 mPendingServices.remove(i);
9055 i--;
9056 N--;
9057 }
9058 }
9059 }
9060 } catch (RemoteException ex) {
9061 // pm is in same process, this will never happen.
9062 }
9063 }
9064 if (r != null) {
9065 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009066 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009067 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009068 if (!r.exported) {
9069 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9070 + " from pid=" + callingPid
9071 + ", uid=" + callingUid
9072 + " that is not exported from uid " + r.appInfo.uid);
9073 return new ServiceLookupResult(null, "not exported from uid "
9074 + r.appInfo.uid);
9075 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009076 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009077 + " from pid=" + callingPid
9078 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009079 + " requires " + r.permission);
9080 return new ServiceLookupResult(null, r.permission);
9081 }
9082 return new ServiceLookupResult(r, null);
9083 }
9084 return null;
9085 }
9086
Dianne Hackborn287952c2010-09-22 22:34:31 -07009087 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9088 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9089 + why + " of " + r + " in app " + r.app);
9090 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9091 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 long now = SystemClock.uptimeMillis();
9093 if (r.executeNesting == 0 && r.app != null) {
9094 if (r.app.executingServices.size() == 0) {
9095 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9096 msg.obj = r.app;
9097 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9098 }
9099 r.app.executingServices.add(r);
9100 }
9101 r.executeNesting++;
9102 r.executingStart = now;
9103 }
9104
9105 private final void sendServiceArgsLocked(ServiceRecord r,
9106 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009107 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 if (N == 0) {
9109 return;
9110 }
9111
Dianne Hackborn39792d22010-08-19 18:01:52 -07009112 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009114 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009115 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9116 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009117 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009118 // If somehow we got a dummy start at the front, then
9119 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009120 continue;
9121 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009122 si.deliveredTime = SystemClock.uptimeMillis();
9123 r.deliveredStarts.add(si);
9124 si.deliveryCount++;
9125 if (si.targetPermissionUid >= 0) {
9126 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009127 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009128 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009129 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 if (!oomAdjusted) {
9131 oomAdjusted = true;
9132 updateOomAdjLocked(r.app);
9133 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009134 int flags = 0;
9135 if (si.deliveryCount > 0) {
9136 flags |= Service.START_FLAG_RETRY;
9137 }
9138 if (si.doneExecutingCount > 0) {
9139 flags |= Service.START_FLAG_REDELIVERY;
9140 }
9141 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009142 } catch (RemoteException e) {
9143 // Remote process gone... we'll let the normal cleanup take
9144 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009145 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009146 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009148 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009149 break;
9150 }
9151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009152 }
9153
9154 private final boolean requestServiceBindingLocked(ServiceRecord r,
9155 IntentBindRecord i, boolean rebind) {
9156 if (r.app == null || r.app.thread == null) {
9157 // If service is not currently running, can't yet bind.
9158 return false;
9159 }
9160 if ((!i.requested || rebind) && i.apps.size() > 0) {
9161 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009162 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9164 if (!rebind) {
9165 i.requested = true;
9166 }
9167 i.hasBound = true;
9168 i.doRebind = false;
9169 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009170 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171 return false;
9172 }
9173 }
9174 return true;
9175 }
9176
9177 private final void requestServiceBindingsLocked(ServiceRecord r) {
9178 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9179 while (bindings.hasNext()) {
9180 IntentBindRecord i = bindings.next();
9181 if (!requestServiceBindingLocked(r, i, false)) {
9182 break;
9183 }
9184 }
9185 }
9186
9187 private final void realStartServiceLocked(ServiceRecord r,
9188 ProcessRecord app) throws RemoteException {
9189 if (app.thread == null) {
9190 throw new RemoteException();
9191 }
9192
9193 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009194 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195
9196 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009197 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009198 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199
9200 boolean created = false;
9201 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009202 mStringBuilder.setLength(0);
9203 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009204 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009205 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009206 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 synchronized (r.stats.getBatteryStats()) {
9208 r.stats.startLaunchedLocked();
9209 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009210 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009212 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 created = true;
9214 } finally {
9215 if (!created) {
9216 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009217 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 }
9219 }
9220
9221 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009222
9223 // If the service is in the started state, and there are no
9224 // pending arguments, then fake up one so its onStartCommand() will
9225 // be called.
9226 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9227 r.lastStartId++;
9228 if (r.lastStartId < 1) {
9229 r.lastStartId = 1;
9230 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009231 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009232 }
9233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 sendServiceArgsLocked(r, true);
9235 }
9236
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009237 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9238 boolean allowCancel) {
9239 boolean canceled = false;
9240
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009241 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009242 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009243 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009244
Dianne Hackborn070783f2010-12-29 16:46:28 -08009245 if ((r.serviceInfo.applicationInfo.flags
9246 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9247 minDuration /= 4;
9248 }
9249
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009250 // Any delivered but not yet finished starts should be put back
9251 // on the pending list.
9252 final int N = r.deliveredStarts.size();
9253 if (N > 0) {
9254 for (int i=N-1; i>=0; i--) {
9255 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009256 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009257 if (si.intent == null) {
9258 // We'll generate this again if needed.
9259 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9260 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9261 r.pendingStarts.add(0, si);
9262 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9263 dur *= 2;
9264 if (minDuration < dur) minDuration = dur;
9265 if (resetTime < dur) resetTime = dur;
9266 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009267 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009268 + r.name);
9269 canceled = true;
9270 }
9271 }
9272 r.deliveredStarts.clear();
9273 }
9274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009275 r.totalRestartCount++;
9276 if (r.restartDelay == 0) {
9277 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009278 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 } else {
9280 // If it has been a "reasonably long time" since the service
9281 // was started, then reset our restart duration back to
9282 // the beginning, so we don't infinitely increase the duration
9283 // on a service that just occasionally gets killed (which is
9284 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009285 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009287 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009289 if ((r.serviceInfo.applicationInfo.flags
9290 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9291 // Services in peristent processes will restart much more
9292 // quickly, since they are pretty important. (Think SystemUI).
9293 r.restartDelay += minDuration/2;
9294 } else {
9295 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9296 if (r.restartDelay < minDuration) {
9297 r.restartDelay = minDuration;
9298 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 }
9301 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009302
9303 r.nextRestartTime = now + r.restartDelay;
9304
9305 // Make sure that we don't end up restarting a bunch of services
9306 // all at the same time.
9307 boolean repeat;
9308 do {
9309 repeat = false;
9310 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9311 ServiceRecord r2 = mRestartingServices.get(i);
9312 if (r2 != r && r.nextRestartTime
9313 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9314 && r.nextRestartTime
9315 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9316 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9317 r.restartDelay = r.nextRestartTime - now;
9318 repeat = true;
9319 break;
9320 }
9321 }
9322 } while (repeat);
9323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 if (!mRestartingServices.contains(r)) {
9325 mRestartingServices.add(r);
9326 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009327
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009328 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009331 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009333 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009335 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009336 r.shortName, r.restartDelay);
9337
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009338 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 }
9340
9341 final void performServiceRestartLocked(ServiceRecord r) {
9342 if (!mRestartingServices.contains(r)) {
9343 return;
9344 }
9345 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9346 }
9347
9348 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9349 if (r.restartDelay == 0) {
9350 return false;
9351 }
9352 r.resetRestartCounter();
9353 mRestartingServices.remove(r);
9354 mHandler.removeCallbacks(r.restarter);
9355 return true;
9356 }
9357
9358 private final boolean bringUpServiceLocked(ServiceRecord r,
9359 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009360 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009361 //r.dump(" ");
9362
Dianne Hackborn36124872009-10-08 16:22:03 -07009363 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009364 sendServiceArgsLocked(r, false);
9365 return true;
9366 }
9367
9368 if (!whileRestarting && r.restartDelay > 0) {
9369 // If waiting for a restart, then do nothing.
9370 return true;
9371 }
9372
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009373 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009375 // We are now bringing the service up, so no longer in the
9376 // restarting state.
9377 mRestartingServices.remove(r);
9378
Dianne Hackborne7f97212011-02-24 14:40:20 -08009379 // Service is now being launched, its package can't be stopped.
9380 try {
9381 AppGlobals.getPackageManager().setPackageStoppedState(
9382 r.packageName, false);
9383 } catch (RemoteException e) {
9384 }
9385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 final String appName = r.processName;
9387 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9388 if (app != null && app.thread != null) {
9389 try {
9390 realStartServiceLocked(r, app);
9391 return true;
9392 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009393 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 }
9395
9396 // If a dead object exception was thrown -- fall through to
9397 // restart the application.
9398 }
9399
Dianne Hackborn36124872009-10-08 16:22:03 -07009400 // Not running -- get it started, and enqueue this service record
9401 // to be executed when the app comes up.
9402 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9403 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009404 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009405 + r.appInfo.packageName + "/"
9406 + r.appInfo.uid + " for service "
9407 + r.intent.getIntent() + ": process is bad");
9408 bringDownServiceLocked(r, true);
9409 return false;
9410 }
9411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009413 mPendingServices.add(r);
9414 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 return true;
9417 }
9418
9419 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009420 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 //r.dump(" ");
9422
9423 // Does it still need to run?
9424 if (!force && r.startRequested) {
9425 return;
9426 }
9427 if (r.connections.size() > 0) {
9428 if (!force) {
9429 // XXX should probably keep a count of the number of auto-create
9430 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009431 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009432 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009433 ArrayList<ConnectionRecord> cr = it.next();
9434 for (int i=0; i<cr.size(); i++) {
9435 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9436 return;
9437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438 }
9439 }
9440 }
9441
9442 // Report to all of the connections that the service is no longer
9443 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009444 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009445 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009446 ArrayList<ConnectionRecord> c = it.next();
9447 for (int i=0; i<c.size(); i++) {
9448 try {
9449 c.get(i).conn.connected(r.name, null);
9450 } catch (Exception e) {
9451 Slog.w(TAG, "Failure disconnecting service " + r.name +
9452 " to connection " + c.get(i).conn.asBinder() +
9453 " (in " + c.get(i).binding.client.processName + ")", e);
9454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009455 }
9456 }
9457 }
9458
9459 // Tell the service that it has been unbound.
9460 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9461 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9462 while (it.hasNext()) {
9463 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009464 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 + ": hasBound=" + ibr.hasBound);
9466 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9467 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009468 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 updateOomAdjLocked(r.app);
9470 ibr.hasBound = false;
9471 r.app.thread.scheduleUnbindService(r,
9472 ibr.intent.getIntent());
9473 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009474 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 + r.shortName, e);
9476 serviceDoneExecutingLocked(r, true);
9477 }
9478 }
9479 }
9480 }
9481
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009482 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009483 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 System.identityHashCode(r), r.shortName,
9485 (r.app != null) ? r.app.pid : -1);
9486
9487 mServices.remove(r.name);
9488 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 r.totalRestartCount = 0;
9490 unscheduleServiceRestartLocked(r);
9491
9492 // Also make sure it is not on the pending list.
9493 int N = mPendingServices.size();
9494 for (int i=0; i<N; i++) {
9495 if (mPendingServices.get(i) == r) {
9496 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009497 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 i--;
9499 N--;
9500 }
9501 }
9502
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009503 r.cancelNotification();
9504 r.isForeground = false;
9505 r.foregroundId = 0;
9506 r.foregroundNoti = null;
9507
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009508 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009509 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009510 r.pendingStarts.clear();
9511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 if (r.app != null) {
9513 synchronized (r.stats.getBatteryStats()) {
9514 r.stats.stopLaunchedLocked();
9515 }
9516 r.app.services.remove(r);
9517 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009519 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 mStoppingServices.add(r);
9521 updateOomAdjLocked(r.app);
9522 r.app.thread.scheduleStopService(r);
9523 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009524 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009525 + r.shortName, e);
9526 serviceDoneExecutingLocked(r, true);
9527 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009528 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009529 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009530 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009531 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009532 }
9533 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009534 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009535 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009536 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009537
9538 if (r.bindings.size() > 0) {
9539 r.bindings.clear();
9540 }
9541
9542 if (r.restarter instanceof ServiceRestarter) {
9543 ((ServiceRestarter)r.restarter).setService(null);
9544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 }
9546
9547 ComponentName startServiceLocked(IApplicationThread caller,
9548 Intent service, String resolvedType,
9549 int callingPid, int callingUid) {
9550 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009551 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 + " type=" + resolvedType + " args=" + service.getExtras());
9553
9554 if (caller != null) {
9555 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9556 if (callerApp == null) {
9557 throw new SecurityException(
9558 "Unable to find app for caller " + caller
9559 + " (pid=" + Binder.getCallingPid()
9560 + ") when starting service " + service);
9561 }
9562 }
9563
9564 ServiceLookupResult res =
9565 retrieveServiceLocked(service, resolvedType,
9566 callingPid, callingUid);
9567 if (res == null) {
9568 return null;
9569 }
9570 if (res.record == null) {
9571 return new ComponentName("!", res.permission != null
9572 ? res.permission : "private to package");
9573 }
9574 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009575 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9576 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009578 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009579 }
9580 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009581 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 r.lastStartId++;
9583 if (r.lastStartId < 1) {
9584 r.lastStartId = 1;
9585 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009586 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9587 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 r.lastActivity = SystemClock.uptimeMillis();
9589 synchronized (r.stats.getBatteryStats()) {
9590 r.stats.startRunningLocked();
9591 }
9592 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9593 return new ComponentName("!", "Service process is bad");
9594 }
9595 return r.name;
9596 }
9597 }
9598
9599 public ComponentName startService(IApplicationThread caller, Intent service,
9600 String resolvedType) {
9601 // Refuse possible leaked file descriptors
9602 if (service != null && service.hasFileDescriptors() == true) {
9603 throw new IllegalArgumentException("File descriptors passed in Intent");
9604 }
9605
9606 synchronized(this) {
9607 final int callingPid = Binder.getCallingPid();
9608 final int callingUid = Binder.getCallingUid();
9609 final long origId = Binder.clearCallingIdentity();
9610 ComponentName res = startServiceLocked(caller, service,
9611 resolvedType, callingPid, callingUid);
9612 Binder.restoreCallingIdentity(origId);
9613 return res;
9614 }
9615 }
9616
9617 ComponentName startServiceInPackage(int uid,
9618 Intent service, String resolvedType) {
9619 synchronized(this) {
9620 final long origId = Binder.clearCallingIdentity();
9621 ComponentName res = startServiceLocked(null, service,
9622 resolvedType, -1, uid);
9623 Binder.restoreCallingIdentity(origId);
9624 return res;
9625 }
9626 }
9627
9628 public int stopService(IApplicationThread caller, Intent service,
9629 String resolvedType) {
9630 // Refuse possible leaked file descriptors
9631 if (service != null && service.hasFileDescriptors() == true) {
9632 throw new IllegalArgumentException("File descriptors passed in Intent");
9633 }
9634
9635 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009636 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 + " type=" + resolvedType);
9638
9639 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9640 if (caller != null && callerApp == null) {
9641 throw new SecurityException(
9642 "Unable to find app for caller " + caller
9643 + " (pid=" + Binder.getCallingPid()
9644 + ") when stopping service " + service);
9645 }
9646
9647 // If this service is active, make sure it is stopped.
9648 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9649 if (r != null) {
9650 if (r.record != null) {
9651 synchronized (r.record.stats.getBatteryStats()) {
9652 r.record.stats.stopRunningLocked();
9653 }
9654 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009655 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656 final long origId = Binder.clearCallingIdentity();
9657 bringDownServiceLocked(r.record, false);
9658 Binder.restoreCallingIdentity(origId);
9659 return 1;
9660 }
9661 return -1;
9662 }
9663 }
9664
9665 return 0;
9666 }
9667
9668 public IBinder peekService(Intent service, String resolvedType) {
9669 // Refuse possible leaked file descriptors
9670 if (service != null && service.hasFileDescriptors() == true) {
9671 throw new IllegalArgumentException("File descriptors passed in Intent");
9672 }
9673
9674 IBinder ret = null;
9675
9676 synchronized(this) {
9677 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9678
9679 if (r != null) {
9680 // r.record is null if findServiceLocked() failed the caller permission check
9681 if (r.record == null) {
9682 throw new SecurityException(
9683 "Permission Denial: Accessing service " + r.record.name
9684 + " from pid=" + Binder.getCallingPid()
9685 + ", uid=" + Binder.getCallingUid()
9686 + " requires " + r.permission);
9687 }
9688 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9689 if (ib != null) {
9690 ret = ib.binder;
9691 }
9692 }
9693 }
9694
9695 return ret;
9696 }
9697
9698 public boolean stopServiceToken(ComponentName className, IBinder token,
9699 int startId) {
9700 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009701 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 + " " + token + " startId=" + startId);
9703 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009704 if (r != null) {
9705 if (startId >= 0) {
9706 // Asked to only stop if done with all work. Note that
9707 // to avoid leaks, we will take this as dropping all
9708 // start items up to and including this one.
9709 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9710 if (si != null) {
9711 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009712 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9713 cur.removeUriPermissionsLocked();
9714 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009715 break;
9716 }
9717 }
9718 }
9719
9720 if (r.lastStartId != startId) {
9721 return false;
9722 }
9723
9724 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009725 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009726 + " is last, but have " + r.deliveredStarts.size()
9727 + " remaining args");
9728 }
9729 }
9730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731 synchronized (r.stats.getBatteryStats()) {
9732 r.stats.stopRunningLocked();
9733 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009734 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 }
9736 final long origId = Binder.clearCallingIdentity();
9737 bringDownServiceLocked(r, false);
9738 Binder.restoreCallingIdentity(origId);
9739 return true;
9740 }
9741 }
9742 return false;
9743 }
9744
9745 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009746 int id, Notification notification, boolean removeNotification) {
9747 final long origId = Binder.clearCallingIdentity();
9748 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 synchronized(this) {
9750 ServiceRecord r = findServiceLocked(className, token);
9751 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009752 if (id != 0) {
9753 if (notification == null) {
9754 throw new IllegalArgumentException("null notification");
9755 }
9756 if (r.foregroundId != id) {
9757 r.cancelNotification();
9758 r.foregroundId = id;
9759 }
9760 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9761 r.foregroundNoti = notification;
9762 r.isForeground = true;
9763 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764 if (r.app != null) {
9765 updateServiceForegroundLocked(r.app, true);
9766 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009767 } else {
9768 if (r.isForeground) {
9769 r.isForeground = false;
9770 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009771 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009772 updateServiceForegroundLocked(r.app, true);
9773 }
9774 }
9775 if (removeNotification) {
9776 r.cancelNotification();
9777 r.foregroundId = 0;
9778 r.foregroundNoti = null;
9779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 }
9781 }
9782 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009783 } finally {
9784 Binder.restoreCallingIdentity(origId);
9785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 }
9787
9788 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9789 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009790 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 if (sr.isForeground) {
9792 anyForeground = true;
9793 break;
9794 }
9795 }
9796 if (anyForeground != proc.foregroundServices) {
9797 proc.foregroundServices = anyForeground;
9798 if (oomAdj) {
9799 updateOomAdjLocked();
9800 }
9801 }
9802 }
9803
9804 public int bindService(IApplicationThread caller, IBinder token,
9805 Intent service, String resolvedType,
9806 IServiceConnection connection, int flags) {
9807 // Refuse possible leaked file descriptors
9808 if (service != null && service.hasFileDescriptors() == true) {
9809 throw new IllegalArgumentException("File descriptors passed in Intent");
9810 }
9811
9812 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009813 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009814 + " type=" + resolvedType + " conn=" + connection.asBinder()
9815 + " flags=0x" + Integer.toHexString(flags));
9816 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9817 if (callerApp == null) {
9818 throw new SecurityException(
9819 "Unable to find app for caller " + caller
9820 + " (pid=" + Binder.getCallingPid()
9821 + ") when binding service " + service);
9822 }
9823
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009824 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009826 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009828 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 return 0;
9830 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009831 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 }
9833
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009834 int clientLabel = 0;
9835 PendingIntent clientIntent = null;
9836
9837 if (callerApp.info.uid == Process.SYSTEM_UID) {
9838 // Hacky kind of thing -- allow system stuff to tell us
9839 // what they are, so we can report this elsewhere for
9840 // others to know why certain services are running.
9841 try {
9842 clientIntent = (PendingIntent)service.getParcelableExtra(
9843 Intent.EXTRA_CLIENT_INTENT);
9844 } catch (RuntimeException e) {
9845 }
9846 if (clientIntent != null) {
9847 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9848 if (clientLabel != 0) {
9849 // There are no useful extras in the intent, trash them.
9850 // System code calling with this stuff just needs to know
9851 // this will happen.
9852 service = service.cloneFilter();
9853 }
9854 }
9855 }
9856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 ServiceLookupResult res =
9858 retrieveServiceLocked(service, resolvedType,
9859 Binder.getCallingPid(), Binder.getCallingUid());
9860 if (res == null) {
9861 return 0;
9862 }
9863 if (res.record == null) {
9864 return -1;
9865 }
9866 ServiceRecord s = res.record;
9867
9868 final long origId = Binder.clearCallingIdentity();
9869
9870 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009871 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009872 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 }
9874
9875 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9876 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009877 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878
9879 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009880 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9881 if (clist == null) {
9882 clist = new ArrayList<ConnectionRecord>();
9883 s.connections.put(binder, clist);
9884 }
9885 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886 b.connections.add(c);
9887 if (activity != null) {
9888 if (activity.connections == null) {
9889 activity.connections = new HashSet<ConnectionRecord>();
9890 }
9891 activity.connections.add(c);
9892 }
9893 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009894 clist = mServiceConnections.get(binder);
9895 if (clist == null) {
9896 clist = new ArrayList<ConnectionRecord>();
9897 mServiceConnections.put(binder, clist);
9898 }
9899 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009900
9901 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9902 s.lastActivity = SystemClock.uptimeMillis();
9903 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9904 return 0;
9905 }
9906 }
9907
9908 if (s.app != null) {
9909 // This could have made the service more important.
9910 updateOomAdjLocked(s.app);
9911 }
9912
Joe Onorato8a9b2202010-02-26 18:56:32 -08009913 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 + ": received=" + b.intent.received
9915 + " apps=" + b.intent.apps.size()
9916 + " doRebind=" + b.intent.doRebind);
9917
9918 if (s.app != null && b.intent.received) {
9919 // Service is already running, so we can immediately
9920 // publish the connection.
9921 try {
9922 c.conn.connected(s.name, b.intent.binder);
9923 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009924 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 + " to connection " + c.conn.asBinder()
9926 + " (in " + c.binding.client.processName + ")", e);
9927 }
9928
9929 // If this is the first app connected back to this binding,
9930 // and the service had previously asked to be told when
9931 // rebound, then do so.
9932 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9933 requestServiceBindingLocked(s, b.intent, true);
9934 }
9935 } else if (!b.intent.requested) {
9936 requestServiceBindingLocked(s, b.intent, false);
9937 }
9938
9939 Binder.restoreCallingIdentity(origId);
9940 }
9941
9942 return 1;
9943 }
9944
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009945 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009946 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009947 IBinder binder = c.conn.asBinder();
9948 AppBindRecord b = c.binding;
9949 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009950 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9951 if (clist != null) {
9952 clist.remove(c);
9953 if (clist.size() == 0) {
9954 s.connections.remove(binder);
9955 }
9956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 b.connections.remove(c);
9958 if (c.activity != null && c.activity != skipAct) {
9959 if (c.activity.connections != null) {
9960 c.activity.connections.remove(c);
9961 }
9962 }
9963 if (b.client != skipApp) {
9964 b.client.connections.remove(c);
9965 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009966 clist = mServiceConnections.get(binder);
9967 if (clist != null) {
9968 clist.remove(c);
9969 if (clist.size() == 0) {
9970 mServiceConnections.remove(binder);
9971 }
9972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009973
9974 if (b.connections.size() == 0) {
9975 b.intent.apps.remove(b.client);
9976 }
9977
Joe Onorato8a9b2202010-02-26 18:56:32 -08009978 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 + ": shouldUnbind=" + b.intent.hasBound);
9980 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9981 && b.intent.hasBound) {
9982 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009983 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 updateOomAdjLocked(s.app);
9985 b.intent.hasBound = false;
9986 // Assume the client doesn't want to know about a rebind;
9987 // we will deal with that later if it asks for one.
9988 b.intent.doRebind = false;
9989 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9990 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009991 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 serviceDoneExecutingLocked(s, true);
9993 }
9994 }
9995
9996 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9997 bringDownServiceLocked(s, false);
9998 }
9999 }
10000
10001 public boolean unbindService(IServiceConnection connection) {
10002 synchronized (this) {
10003 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010004 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010005 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10006 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010007 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010008 + connection.asBinder());
10009 return false;
10010 }
10011
10012 final long origId = Binder.clearCallingIdentity();
10013
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010014 while (clist.size() > 0) {
10015 ConnectionRecord r = clist.get(0);
10016 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010018 if (r.binding.service.app != null) {
10019 // This could have made the service less important.
10020 updateOomAdjLocked(r.binding.service.app);
10021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 }
10023
10024 Binder.restoreCallingIdentity(origId);
10025 }
10026
10027 return true;
10028 }
10029
10030 public void publishService(IBinder token, Intent intent, IBinder service) {
10031 // Refuse possible leaked file descriptors
10032 if (intent != null && intent.hasFileDescriptors() == true) {
10033 throw new IllegalArgumentException("File descriptors passed in Intent");
10034 }
10035
10036 synchronized(this) {
10037 if (!(token instanceof ServiceRecord)) {
10038 throw new IllegalArgumentException("Invalid service token");
10039 }
10040 ServiceRecord r = (ServiceRecord)token;
10041
10042 final long origId = Binder.clearCallingIdentity();
10043
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010044 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045 + " " + intent + ": " + service);
10046 if (r != null) {
10047 Intent.FilterComparison filter
10048 = new Intent.FilterComparison(intent);
10049 IntentBindRecord b = r.bindings.get(filter);
10050 if (b != null && !b.received) {
10051 b.binder = service;
10052 b.requested = true;
10053 b.received = true;
10054 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010055 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 = r.connections.values().iterator();
10057 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010058 ArrayList<ConnectionRecord> clist = it.next();
10059 for (int i=0; i<clist.size(); i++) {
10060 ConnectionRecord c = clist.get(i);
10061 if (!filter.equals(c.binding.intent.intent)) {
10062 if (DEBUG_SERVICE) Slog.v(
10063 TAG, "Not publishing to: " + c);
10064 if (DEBUG_SERVICE) Slog.v(
10065 TAG, "Bound intent: " + c.binding.intent.intent);
10066 if (DEBUG_SERVICE) Slog.v(
10067 TAG, "Published intent: " + intent);
10068 continue;
10069 }
10070 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10071 try {
10072 c.conn.connected(r.name, service);
10073 } catch (Exception e) {
10074 Slog.w(TAG, "Failure sending service " + r.name +
10075 " to connection " + c.conn.asBinder() +
10076 " (in " + c.binding.client.processName + ")", e);
10077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 }
10079 }
10080 }
10081 }
10082
10083 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10084
10085 Binder.restoreCallingIdentity(origId);
10086 }
10087 }
10088 }
10089
10090 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10091 // Refuse possible leaked file descriptors
10092 if (intent != null && intent.hasFileDescriptors() == true) {
10093 throw new IllegalArgumentException("File descriptors passed in Intent");
10094 }
10095
10096 synchronized(this) {
10097 if (!(token instanceof ServiceRecord)) {
10098 throw new IllegalArgumentException("Invalid service token");
10099 }
10100 ServiceRecord r = (ServiceRecord)token;
10101
10102 final long origId = Binder.clearCallingIdentity();
10103
10104 if (r != null) {
10105 Intent.FilterComparison filter
10106 = new Intent.FilterComparison(intent);
10107 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010108 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 + " at " + b + ": apps="
10110 + (b != null ? b.apps.size() : 0));
10111 if (b != null) {
10112 if (b.apps.size() > 0) {
10113 // Applications have already bound since the last
10114 // unbind, so just rebind right here.
10115 requestServiceBindingLocked(r, b, true);
10116 } else {
10117 // Note to tell the service the next time there is
10118 // a new client.
10119 b.doRebind = true;
10120 }
10121 }
10122
10123 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10124
10125 Binder.restoreCallingIdentity(origId);
10126 }
10127 }
10128 }
10129
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010130 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010131 synchronized(this) {
10132 if (!(token instanceof ServiceRecord)) {
10133 throw new IllegalArgumentException("Invalid service token");
10134 }
10135 ServiceRecord r = (ServiceRecord)token;
10136 boolean inStopping = mStoppingServices.contains(token);
10137 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010139 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 + " with incorrect token: given " + token
10141 + ", expected " + r);
10142 return;
10143 }
10144
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010145 if (type == 1) {
10146 // This is a call from a service start... take care of
10147 // book-keeping.
10148 r.callStart = true;
10149 switch (res) {
10150 case Service.START_STICKY_COMPATIBILITY:
10151 case Service.START_STICKY: {
10152 // We are done with the associated start arguments.
10153 r.findDeliveredStart(startId, true);
10154 // Don't stop if killed.
10155 r.stopIfKilled = false;
10156 break;
10157 }
10158 case Service.START_NOT_STICKY: {
10159 // We are done with the associated start arguments.
10160 r.findDeliveredStart(startId, true);
10161 if (r.lastStartId == startId) {
10162 // There is no more work, and this service
10163 // doesn't want to hang around if killed.
10164 r.stopIfKilled = true;
10165 }
10166 break;
10167 }
10168 case Service.START_REDELIVER_INTENT: {
10169 // We'll keep this item until they explicitly
10170 // call stop for it, but keep track of the fact
10171 // that it was delivered.
10172 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10173 if (si != null) {
10174 si.deliveryCount = 0;
10175 si.doneExecutingCount++;
10176 // Don't stop if killed.
10177 r.stopIfKilled = true;
10178 }
10179 break;
10180 }
10181 default:
10182 throw new IllegalArgumentException(
10183 "Unknown service start result: " + res);
10184 }
10185 if (res == Service.START_STICKY_COMPATIBILITY) {
10186 r.callStart = false;
10187 }
10188 }
10189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 final long origId = Binder.clearCallingIdentity();
10191 serviceDoneExecutingLocked(r, inStopping);
10192 Binder.restoreCallingIdentity(origId);
10193 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010194 Slog.w(TAG, "Done executing unknown service from pid "
10195 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 }
10197 }
10198 }
10199
10200 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010201 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10202 + ": nesting=" + r.executeNesting
10203 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010204 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 r.executeNesting--;
10206 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010207 if (DEBUG_SERVICE) Slog.v(TAG,
10208 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 r.app.executingServices.remove(r);
10210 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010211 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10212 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10214 }
10215 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010216 if (DEBUG_SERVICE) Slog.v(TAG,
10217 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010218 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010219 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010220 }
10221 updateOomAdjLocked(r.app);
10222 }
10223 }
10224
10225 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010226 String anrMessage = null;
10227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 synchronized(this) {
10229 if (proc.executingServices.size() == 0 || proc.thread == null) {
10230 return;
10231 }
10232 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10233 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10234 ServiceRecord timeout = null;
10235 long nextTime = 0;
10236 while (it.hasNext()) {
10237 ServiceRecord sr = it.next();
10238 if (sr.executingStart < maxTime) {
10239 timeout = sr;
10240 break;
10241 }
10242 if (sr.executingStart > nextTime) {
10243 nextTime = sr.executingStart;
10244 }
10245 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010246 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010247 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010248 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 } else {
10250 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10251 msg.obj = proc;
10252 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10253 }
10254 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010255
10256 if (anrMessage != null) {
10257 appNotResponding(proc, null, null, anrMessage);
10258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 }
10260
10261 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010262 // BACKUP AND RESTORE
10263 // =========================================================
10264
10265 // Cause the target app to be launched if necessary and its backup agent
10266 // instantiated. The backup agent will invoke backupAgentCreated() on the
10267 // activity manager to announce its creation.
10268 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010269 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010270 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10271
10272 synchronized(this) {
10273 // !!! TODO: currently no check here that we're already bound
10274 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10275 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10276 synchronized (stats) {
10277 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10278 }
10279
Dianne Hackborne7f97212011-02-24 14:40:20 -080010280 // Backup agent is now in use, its package can't be stopped.
10281 try {
10282 AppGlobals.getPackageManager().setPackageStoppedState(
10283 app.packageName, false);
10284 } catch (RemoteException e) {
10285 }
10286
Christopher Tate181fafa2009-05-14 11:12:14 -070010287 BackupRecord r = new BackupRecord(ss, app, backupMode);
10288 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10289 // startProcessLocked() returns existing proc's record if it's already running
10290 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010291 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010292 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010293 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010294 return false;
10295 }
10296
10297 r.app = proc;
10298 mBackupTarget = r;
10299 mBackupAppName = app.packageName;
10300
Christopher Tate6fa95972009-06-05 18:43:55 -070010301 // Try not to kill the process during backup
10302 updateOomAdjLocked(proc);
10303
Christopher Tate181fafa2009-05-14 11:12:14 -070010304 // If the process is already attached, schedule the creation of the backup agent now.
10305 // If it is not yet live, this will be done when it attaches to the framework.
10306 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010307 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010308 try {
10309 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10310 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010311 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010312 }
10313 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010314 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010315 }
10316 // Invariants: at this point, the target app process exists and the application
10317 // is either already running or in the process of coming up. mBackupTarget and
10318 // mBackupAppName describe the app, so that when it binds back to the AM we
10319 // know that it's scheduled for a backup-agent operation.
10320 }
10321
10322 return true;
10323 }
10324
10325 // A backup agent has just come up
10326 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010327 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010328 + " = " + agent);
10329
10330 synchronized(this) {
10331 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010332 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010333 return;
10334 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010335 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010336
Dianne Hackborn06740692010-09-22 22:46:21 -070010337 long oldIdent = Binder.clearCallingIdentity();
10338 try {
10339 IBackupManager bm = IBackupManager.Stub.asInterface(
10340 ServiceManager.getService(Context.BACKUP_SERVICE));
10341 bm.agentConnected(agentPackageName, agent);
10342 } catch (RemoteException e) {
10343 // can't happen; the backup manager service is local
10344 } catch (Exception e) {
10345 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10346 e.printStackTrace();
10347 } finally {
10348 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010349 }
10350 }
10351
10352 // done with this agent
10353 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010354 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010355 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010356 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010357 return;
10358 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010359
10360 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010361 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010362 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010363 return;
10364 }
10365
Christopher Tate181fafa2009-05-14 11:12:14 -070010366 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010367 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010368 return;
10369 }
10370
Christopher Tate6fa95972009-06-05 18:43:55 -070010371 ProcessRecord proc = mBackupTarget.app;
10372 mBackupTarget = null;
10373 mBackupAppName = null;
10374
10375 // Not backing this app up any more; reset its OOM adjustment
10376 updateOomAdjLocked(proc);
10377
Christopher Tatec7b31e32009-06-10 15:49:30 -070010378 // If the app crashed during backup, 'thread' will be null here
10379 if (proc.thread != null) {
10380 try {
10381 proc.thread.scheduleDestroyBackupAgent(appInfo);
10382 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010383 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010384 e.printStackTrace();
10385 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010386 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010387 }
10388 }
10389 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010390 // BROADCASTS
10391 // =========================================================
10392
Josh Bartel7f208742010-02-25 11:01:44 -060010393 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 List cur) {
10395 final ContentResolver resolver = mContext.getContentResolver();
10396 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10397 if (list == null) {
10398 return cur;
10399 }
10400 int N = list.size();
10401 for (int i=0; i<N; i++) {
10402 Intent intent = list.get(i);
10403 if (filter.match(resolver, intent, true, TAG) >= 0) {
10404 if (cur == null) {
10405 cur = new ArrayList<Intent>();
10406 }
10407 cur.add(intent);
10408 }
10409 }
10410 return cur;
10411 }
10412
10413 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010414 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 + mBroadcastsScheduled);
10416
10417 if (mBroadcastsScheduled) {
10418 return;
10419 }
10420 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10421 mBroadcastsScheduled = true;
10422 }
10423
10424 public Intent registerReceiver(IApplicationThread caller,
10425 IIntentReceiver receiver, IntentFilter filter, String permission) {
10426 synchronized(this) {
10427 ProcessRecord callerApp = null;
10428 if (caller != null) {
10429 callerApp = getRecordForAppLocked(caller);
10430 if (callerApp == null) {
10431 throw new SecurityException(
10432 "Unable to find app for caller " + caller
10433 + " (pid=" + Binder.getCallingPid()
10434 + ") when registering receiver " + receiver);
10435 }
10436 }
10437
10438 List allSticky = null;
10439
10440 // Look for any matching sticky broadcasts...
10441 Iterator actions = filter.actionsIterator();
10442 if (actions != null) {
10443 while (actions.hasNext()) {
10444 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010445 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 }
10447 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010448 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 }
10450
10451 // The first sticky in the list is returned directly back to
10452 // the client.
10453 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10454
Joe Onorato8a9b2202010-02-26 18:56:32 -080010455 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 + ": " + sticky);
10457
10458 if (receiver == null) {
10459 return sticky;
10460 }
10461
10462 ReceiverList rl
10463 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10464 if (rl == null) {
10465 rl = new ReceiverList(this, callerApp,
10466 Binder.getCallingPid(),
10467 Binder.getCallingUid(), receiver);
10468 if (rl.app != null) {
10469 rl.app.receivers.add(rl);
10470 } else {
10471 try {
10472 receiver.asBinder().linkToDeath(rl, 0);
10473 } catch (RemoteException e) {
10474 return sticky;
10475 }
10476 rl.linkedToDeath = true;
10477 }
10478 mRegisteredReceivers.put(receiver.asBinder(), rl);
10479 }
10480 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10481 rl.add(bf);
10482 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010483 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 }
10485 mReceiverResolver.addFilter(bf);
10486
10487 // Enqueue broadcasts for all existing stickies that match
10488 // this filter.
10489 if (allSticky != null) {
10490 ArrayList receivers = new ArrayList();
10491 receivers.add(bf);
10492
10493 int N = allSticky.size();
10494 for (int i=0; i<N; i++) {
10495 Intent intent = (Intent)allSticky.get(i);
10496 BroadcastRecord r = new BroadcastRecord(intent, null,
10497 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010498 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010499 if (mParallelBroadcasts.size() == 0) {
10500 scheduleBroadcastsLocked();
10501 }
10502 mParallelBroadcasts.add(r);
10503 }
10504 }
10505
10506 return sticky;
10507 }
10508 }
10509
10510 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010511 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512
10513 boolean doNext = false;
10514
10515 synchronized(this) {
10516 ReceiverList rl
10517 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10518 if (rl != null) {
10519 if (rl.curBroadcast != null) {
10520 BroadcastRecord r = rl.curBroadcast;
10521 doNext = finishReceiverLocked(
10522 receiver.asBinder(), r.resultCode, r.resultData,
10523 r.resultExtras, r.resultAbort, true);
10524 }
10525
10526 if (rl.app != null) {
10527 rl.app.receivers.remove(rl);
10528 }
10529 removeReceiverLocked(rl);
10530 if (rl.linkedToDeath) {
10531 rl.linkedToDeath = false;
10532 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10533 }
10534 }
10535 }
10536
10537 if (!doNext) {
10538 return;
10539 }
10540
10541 final long origId = Binder.clearCallingIdentity();
10542 processNextBroadcast(false);
10543 trimApplications();
10544 Binder.restoreCallingIdentity(origId);
10545 }
10546
10547 void removeReceiverLocked(ReceiverList rl) {
10548 mRegisteredReceivers.remove(rl.receiver.asBinder());
10549 int N = rl.size();
10550 for (int i=0; i<N; i++) {
10551 mReceiverResolver.removeFilter(rl.get(i));
10552 }
10553 }
10554
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010555 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10556 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10557 ProcessRecord r = mLruProcesses.get(i);
10558 if (r.thread != null) {
10559 try {
10560 r.thread.dispatchPackageBroadcast(cmd, packages);
10561 } catch (RemoteException ex) {
10562 }
10563 }
10564 }
10565 }
10566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010567 private final int broadcastIntentLocked(ProcessRecord callerApp,
10568 String callerPackage, Intent intent, String resolvedType,
10569 IIntentReceiver resultTo, int resultCode, String resultData,
10570 Bundle map, String requiredPermission,
10571 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10572 intent = new Intent(intent);
10573
Dianne Hackborne7f97212011-02-24 14:40:20 -080010574 // By default broadcasts do not go to stopped apps.
10575 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10576
Joe Onorato8a9b2202010-02-26 18:56:32 -080010577 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10579 + " ordered=" + ordered);
10580 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010581 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010582 }
10583
10584 // Handle special intents: if this broadcast is from the package
10585 // manager about a package being removed, we need to remove all of
10586 // its activities from the history stack.
10587 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10588 intent.getAction());
10589 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10590 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010591 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 || uidRemoved) {
10593 if (checkComponentPermission(
10594 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010595 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010596 == PackageManager.PERMISSION_GRANTED) {
10597 if (uidRemoved) {
10598 final Bundle intentExtras = intent.getExtras();
10599 final int uid = intentExtras != null
10600 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10601 if (uid >= 0) {
10602 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10603 synchronized (bs) {
10604 bs.removeUidStatsLocked(uid);
10605 }
10606 }
10607 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010608 // If resources are unvailble just force stop all
10609 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010610 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010611 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10612 if (list != null && (list.length > 0)) {
10613 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010614 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010615 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010616 sendPackageBroadcastLocked(
10617 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010618 }
10619 } else {
10620 Uri data = intent.getData();
10621 String ssp;
10622 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10623 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10624 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010625 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010626 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010627 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10628 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10629 new String[] {ssp});
10630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 }
10632 }
10633 }
10634 } else {
10635 String msg = "Permission Denial: " + intent.getAction()
10636 + " broadcast from " + callerPackage + " (pid=" + callingPid
10637 + ", uid=" + callingUid + ")"
10638 + " requires "
10639 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010640 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 throw new SecurityException(msg);
10642 }
10643 }
10644
10645 /*
10646 * If this is the time zone changed action, queue up a message that will reset the timezone
10647 * of all currently running processes. This message will get queued up before the broadcast
10648 * happens.
10649 */
10650 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10651 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10652 }
10653
Robert Greenwalt03595d02010-11-02 14:08:23 -070010654 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10655 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10656 }
10657
Robert Greenwalt434203a2010-10-11 16:00:27 -070010658 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10659 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10660 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10661 }
10662
Dianne Hackborn854060af2009-07-09 18:14:31 -070010663 /*
10664 * Prevent non-system code (defined here to be non-persistent
10665 * processes) from sending protected broadcasts.
10666 */
10667 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10668 || callingUid == Process.SHELL_UID || callingUid == 0) {
10669 // Always okay.
10670 } else if (callerApp == null || !callerApp.persistent) {
10671 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010672 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010673 intent.getAction())) {
10674 String msg = "Permission Denial: not allowed to send broadcast "
10675 + intent.getAction() + " from pid="
10676 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010677 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010678 throw new SecurityException(msg);
10679 }
10680 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010681 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010682 return BROADCAST_SUCCESS;
10683 }
10684 }
10685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010686 // Add to the sticky list if requested.
10687 if (sticky) {
10688 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10689 callingPid, callingUid)
10690 != PackageManager.PERMISSION_GRANTED) {
10691 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10692 + callingPid + ", uid=" + callingUid
10693 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010694 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 throw new SecurityException(msg);
10696 }
10697 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010698 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010699 + " and enforce permission " + requiredPermission);
10700 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10701 }
10702 if (intent.getComponent() != null) {
10703 throw new SecurityException(
10704 "Sticky broadcasts can't target a specific component");
10705 }
10706 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10707 if (list == null) {
10708 list = new ArrayList<Intent>();
10709 mStickyBroadcasts.put(intent.getAction(), list);
10710 }
10711 int N = list.size();
10712 int i;
10713 for (i=0; i<N; i++) {
10714 if (intent.filterEquals(list.get(i))) {
10715 // This sticky already exists, replace it.
10716 list.set(i, new Intent(intent));
10717 break;
10718 }
10719 }
10720 if (i >= N) {
10721 list.add(new Intent(intent));
10722 }
10723 }
10724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 // Figure out who all will receive this broadcast.
10726 List receivers = null;
10727 List<BroadcastFilter> registeredReceivers = null;
10728 try {
10729 if (intent.getComponent() != null) {
10730 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010731 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010732 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010733 if (ai != null) {
10734 receivers = new ArrayList();
10735 ResolveInfo ri = new ResolveInfo();
10736 ri.activityInfo = ai;
10737 receivers.add(ri);
10738 }
10739 } else {
10740 // Need to resolve the intent to interested receivers...
10741 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10742 == 0) {
10743 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010744 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010745 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010746 }
Mihai Preda074edef2009-05-18 17:13:31 +020010747 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 }
10749 } catch (RemoteException ex) {
10750 // pm is in same process, this will never happen.
10751 }
10752
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010753 final boolean replacePending =
10754 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10755
Joe Onorato8a9b2202010-02-26 18:56:32 -080010756 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010757 + " replacePending=" + replacePending);
10758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10760 if (!ordered && NR > 0) {
10761 // If we are not serializing this broadcast, then send the
10762 // registered receivers separately so they don't wait for the
10763 // components to be launched.
10764 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10765 callerPackage, callingPid, callingUid, requiredPermission,
10766 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010767 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010768 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 TAG, "Enqueueing parallel broadcast " + r
10770 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010771 boolean replaced = false;
10772 if (replacePending) {
10773 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10774 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010775 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010776 "***** DROPPING PARALLEL: " + intent);
10777 mParallelBroadcasts.set(i, r);
10778 replaced = true;
10779 break;
10780 }
10781 }
10782 }
10783 if (!replaced) {
10784 mParallelBroadcasts.add(r);
10785 scheduleBroadcastsLocked();
10786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 registeredReceivers = null;
10788 NR = 0;
10789 }
10790
10791 // Merge into one list.
10792 int ir = 0;
10793 if (receivers != null) {
10794 // A special case for PACKAGE_ADDED: do not allow the package
10795 // being added to see this broadcast. This prevents them from
10796 // using this as a back door to get run as soon as they are
10797 // installed. Maybe in the future we want to have a special install
10798 // broadcast or such for apps, but we'd like to deliberately make
10799 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010800 String skipPackages[] = null;
10801 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10802 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10803 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10804 Uri data = intent.getData();
10805 if (data != null) {
10806 String pkgName = data.getSchemeSpecificPart();
10807 if (pkgName != null) {
10808 skipPackages = new String[] { pkgName };
10809 }
10810 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010811 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010812 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010813 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010814 if (skipPackages != null && (skipPackages.length > 0)) {
10815 for (String skipPackage : skipPackages) {
10816 if (skipPackage != null) {
10817 int NT = receivers.size();
10818 for (int it=0; it<NT; it++) {
10819 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10820 if (curt.activityInfo.packageName.equals(skipPackage)) {
10821 receivers.remove(it);
10822 it--;
10823 NT--;
10824 }
10825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010826 }
10827 }
10828 }
10829
10830 int NT = receivers != null ? receivers.size() : 0;
10831 int it = 0;
10832 ResolveInfo curt = null;
10833 BroadcastFilter curr = null;
10834 while (it < NT && ir < NR) {
10835 if (curt == null) {
10836 curt = (ResolveInfo)receivers.get(it);
10837 }
10838 if (curr == null) {
10839 curr = registeredReceivers.get(ir);
10840 }
10841 if (curr.getPriority() >= curt.priority) {
10842 // Insert this broadcast record into the final list.
10843 receivers.add(it, curr);
10844 ir++;
10845 curr = null;
10846 it++;
10847 NT++;
10848 } else {
10849 // Skip to the next ResolveInfo in the final list.
10850 it++;
10851 curt = null;
10852 }
10853 }
10854 }
10855 while (ir < NR) {
10856 if (receivers == null) {
10857 receivers = new ArrayList();
10858 }
10859 receivers.add(registeredReceivers.get(ir));
10860 ir++;
10861 }
10862
10863 if ((receivers != null && receivers.size() > 0)
10864 || resultTo != null) {
10865 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10866 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010867 receivers, resultTo, resultCode, resultData, map, ordered,
10868 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010869 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010870 TAG, "Enqueueing ordered broadcast " + r
10871 + ": prev had " + mOrderedBroadcasts.size());
10872 if (DEBUG_BROADCAST) {
10873 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010874 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010876 boolean replaced = false;
10877 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010878 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010879 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010880 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010881 "***** DROPPING ORDERED: " + intent);
10882 mOrderedBroadcasts.set(i, r);
10883 replaced = true;
10884 break;
10885 }
10886 }
10887 }
10888 if (!replaced) {
10889 mOrderedBroadcasts.add(r);
10890 scheduleBroadcastsLocked();
10891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 }
10893
10894 return BROADCAST_SUCCESS;
10895 }
10896
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010897 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 // Refuse possible leaked file descriptors
10899 if (intent != null && intent.hasFileDescriptors() == true) {
10900 throw new IllegalArgumentException("File descriptors passed in Intent");
10901 }
10902
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010903 int flags = intent.getFlags();
10904
10905 if (!mProcessesReady) {
10906 // if the caller really truly claims to know what they're doing, go
10907 // ahead and allow the broadcast without launching any receivers
10908 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10909 intent = new Intent(intent);
10910 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10911 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10912 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10913 + " before boot completion");
10914 throw new IllegalStateException("Cannot broadcast before boot completed");
10915 }
10916 }
10917
10918 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10919 throw new IllegalArgumentException(
10920 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10921 }
10922
10923 return intent;
10924 }
10925
10926 public final int broadcastIntent(IApplicationThread caller,
10927 Intent intent, String resolvedType, IIntentReceiver resultTo,
10928 int resultCode, String resultData, Bundle map,
10929 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010931 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10934 final int callingPid = Binder.getCallingPid();
10935 final int callingUid = Binder.getCallingUid();
10936 final long origId = Binder.clearCallingIdentity();
10937 int res = broadcastIntentLocked(callerApp,
10938 callerApp != null ? callerApp.info.packageName : null,
10939 intent, resolvedType, resultTo,
10940 resultCode, resultData, map, requiredPermission, serialized,
10941 sticky, callingPid, callingUid);
10942 Binder.restoreCallingIdentity(origId);
10943 return res;
10944 }
10945 }
10946
10947 int broadcastIntentInPackage(String packageName, int uid,
10948 Intent intent, String resolvedType, IIntentReceiver resultTo,
10949 int resultCode, String resultData, Bundle map,
10950 String requiredPermission, boolean serialized, boolean sticky) {
10951 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010952 intent = verifyBroadcastLocked(intent);
10953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 final long origId = Binder.clearCallingIdentity();
10955 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10956 resultTo, resultCode, resultData, map, requiredPermission,
10957 serialized, sticky, -1, uid);
10958 Binder.restoreCallingIdentity(origId);
10959 return res;
10960 }
10961 }
10962
10963 public final void unbroadcastIntent(IApplicationThread caller,
10964 Intent intent) {
10965 // Refuse possible leaked file descriptors
10966 if (intent != null && intent.hasFileDescriptors() == true) {
10967 throw new IllegalArgumentException("File descriptors passed in Intent");
10968 }
10969
10970 synchronized(this) {
10971 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10972 != PackageManager.PERMISSION_GRANTED) {
10973 String msg = "Permission Denial: unbroadcastIntent() from pid="
10974 + Binder.getCallingPid()
10975 + ", uid=" + Binder.getCallingUid()
10976 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010977 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 throw new SecurityException(msg);
10979 }
10980 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10981 if (list != null) {
10982 int N = list.size();
10983 int i;
10984 for (i=0; i<N; i++) {
10985 if (intent.filterEquals(list.get(i))) {
10986 list.remove(i);
10987 break;
10988 }
10989 }
10990 }
10991 }
10992 }
10993
10994 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10995 String resultData, Bundle resultExtras, boolean resultAbort,
10996 boolean explicit) {
10997 if (mOrderedBroadcasts.size() == 0) {
10998 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010999 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011000 }
11001 return false;
11002 }
11003 BroadcastRecord r = mOrderedBroadcasts.get(0);
11004 if (r.receiver == null) {
11005 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011006 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 }
11008 return false;
11009 }
11010 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 return false;
11013 }
11014 int state = r.state;
11015 r.state = r.IDLE;
11016 if (state == r.IDLE) {
11017 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011018 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 }
11020 }
11021 r.receiver = null;
11022 r.intent.setComponent(null);
11023 if (r.curApp != null) {
11024 r.curApp.curReceiver = null;
11025 }
11026 if (r.curFilter != null) {
11027 r.curFilter.receiverList.curBroadcast = null;
11028 }
11029 r.curFilter = null;
11030 r.curApp = null;
11031 r.curComponent = null;
11032 r.curReceiver = null;
11033 mPendingBroadcast = null;
11034
11035 r.resultCode = resultCode;
11036 r.resultData = resultData;
11037 r.resultExtras = resultExtras;
11038 r.resultAbort = resultAbort;
11039
11040 // We will process the next receiver right now if this is finishing
11041 // an app receiver (which is always asynchronous) or after we have
11042 // come back from calling a receiver.
11043 return state == BroadcastRecord.APP_RECEIVE
11044 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11045 }
11046
11047 public void finishReceiver(IBinder who, int resultCode, String resultData,
11048 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011049 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050
11051 // Refuse possible leaked file descriptors
11052 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11053 throw new IllegalArgumentException("File descriptors passed in Bundle");
11054 }
11055
11056 boolean doNext;
11057
11058 final long origId = Binder.clearCallingIdentity();
11059
11060 synchronized(this) {
11061 doNext = finishReceiverLocked(
11062 who, resultCode, resultData, resultExtras, resultAbort, true);
11063 }
11064
11065 if (doNext) {
11066 processNextBroadcast(false);
11067 }
11068 trimApplications();
11069
11070 Binder.restoreCallingIdentity(origId);
11071 }
11072
Jeff Brown4d94a762010-09-23 11:33:28 -070011073 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 if (r.nextReceiver > 0) {
11075 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11076 if (curReceiver instanceof BroadcastFilter) {
11077 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011078 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 System.identityHashCode(r),
11080 r.intent.getAction(),
11081 r.nextReceiver - 1,
11082 System.identityHashCode(bf));
11083 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011084 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 System.identityHashCode(r),
11086 r.intent.getAction(),
11087 r.nextReceiver - 1,
11088 ((ResolveInfo)curReceiver).toString());
11089 }
11090 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011091 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011092 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011093 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 System.identityHashCode(r),
11095 r.intent.getAction(),
11096 r.nextReceiver,
11097 "NONE");
11098 }
11099 }
11100
Jeff Brown4d94a762010-09-23 11:33:28 -070011101 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11102 if (! mPendingBroadcastTimeoutMessage) {
11103 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11104 mHandler.sendMessageAtTime(msg, timeoutTime);
11105 mPendingBroadcastTimeoutMessage = true;
11106 }
11107 }
11108
11109 private final void cancelBroadcastTimeoutLocked() {
11110 if (mPendingBroadcastTimeoutMessage) {
11111 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11112 mPendingBroadcastTimeoutMessage = false;
11113 }
11114 }
11115
11116 private final void broadcastTimeoutLocked(boolean fromMsg) {
11117 if (fromMsg) {
11118 mPendingBroadcastTimeoutMessage = false;
11119 }
11120
11121 if (mOrderedBroadcasts.size() == 0) {
11122 return;
11123 }
11124
11125 long now = SystemClock.uptimeMillis();
11126 BroadcastRecord r = mOrderedBroadcasts.get(0);
11127 if (fromMsg) {
11128 if (mDidDexOpt) {
11129 // Delay timeouts until dexopt finishes.
11130 mDidDexOpt = false;
11131 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11132 setBroadcastTimeoutLocked(timeoutTime);
11133 return;
11134 }
11135 if (! mProcessesReady) {
11136 // Only process broadcast timeouts if the system is ready. That way
11137 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11138 // to do heavy lifting for system up.
11139 return;
11140 }
11141
11142 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11143 if (timeoutTime > now) {
11144 // We can observe premature timeouts because we do not cancel and reset the
11145 // broadcast timeout message after each receiver finishes. Instead, we set up
11146 // an initial timeout then kick it down the road a little further as needed
11147 // when it expires.
11148 if (DEBUG_BROADCAST) Slog.v(TAG,
11149 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11150 + timeoutTime);
11151 setBroadcastTimeoutLocked(timeoutTime);
11152 return;
11153 }
11154 }
11155
11156 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11157 + ", started " + (now - r.receiverTime) + "ms ago");
11158 r.receiverTime = now;
11159 r.anrCount++;
11160
11161 // Current receiver has passed its expiration date.
11162 if (r.nextReceiver <= 0) {
11163 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11164 return;
11165 }
11166
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011167 ProcessRecord app = null;
11168 String anrMessage = null;
11169
Jeff Brown4d94a762010-09-23 11:33:28 -070011170 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11171 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11172 logBroadcastReceiverDiscardLocked(r);
11173 if (curReceiver instanceof BroadcastFilter) {
11174 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11175 if (bf.receiverList.pid != 0
11176 && bf.receiverList.pid != MY_PID) {
11177 synchronized (this.mPidsSelfLocked) {
11178 app = this.mPidsSelfLocked.get(
11179 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011182 } else {
11183 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011185
Jeff Brown4d94a762010-09-23 11:33:28 -070011186 if (app != null) {
11187 anrMessage = "Broadcast of " + r.intent.toString();
11188 }
11189
11190 if (mPendingBroadcast == r) {
11191 mPendingBroadcast = null;
11192 }
11193
11194 // Move on to the next receiver.
11195 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11196 r.resultExtras, r.resultAbort, true);
11197 scheduleBroadcastsLocked();
11198
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011199 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011200 // Post the ANR to the handler since we do not want to process ANRs while
11201 // potentially holding our lock.
11202 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 }
11205
11206 private final void processCurBroadcastLocked(BroadcastRecord r,
11207 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011208 if (DEBUG_BROADCAST) Slog.v(TAG,
11209 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 if (app.thread == null) {
11211 throw new RemoteException();
11212 }
11213 r.receiver = app.thread.asBinder();
11214 r.curApp = app;
11215 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011216 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011217
11218 // Tell the application to launch this receiver.
11219 r.intent.setComponent(r.curComponent);
11220
11221 boolean started = false;
11222 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011223 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011224 "Delivering to component " + r.curComponent
11225 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011226 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11228 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011229 if (DEBUG_BROADCAST) Slog.v(TAG,
11230 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 started = true;
11232 } finally {
11233 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011234 if (DEBUG_BROADCAST) Slog.v(TAG,
11235 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 r.receiver = null;
11237 r.curApp = null;
11238 app.curReceiver = null;
11239 }
11240 }
11241
11242 }
11243
Jeff Brown4d94a762010-09-23 11:33:28 -070011244 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011245 Intent intent, int resultCode, String data, Bundle extras,
11246 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011247 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011248 if (app != null && app.thread != null) {
11249 // If we have an app thread, do the call through that so it is
11250 // correctly ordered with other one-way calls.
11251 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011252 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011254 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 }
11256 }
11257
Jeff Brown4d94a762010-09-23 11:33:28 -070011258 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 BroadcastFilter filter, boolean ordered) {
11260 boolean skip = false;
11261 if (filter.requiredPermission != null) {
11262 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011263 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011265 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 + r.intent.toString()
11267 + " from " + r.callerPackage + " (pid="
11268 + r.callingPid + ", uid=" + r.callingUid + ")"
11269 + " requires " + filter.requiredPermission
11270 + " due to registered receiver " + filter);
11271 skip = true;
11272 }
11273 }
11274 if (r.requiredPermission != null) {
11275 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011276 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011277 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011278 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011279 + r.intent.toString()
11280 + " to " + filter.receiverList.app
11281 + " (pid=" + filter.receiverList.pid
11282 + ", uid=" + filter.receiverList.uid + ")"
11283 + " requires " + r.requiredPermission
11284 + " due to sender " + r.callerPackage
11285 + " (uid " + r.callingUid + ")");
11286 skip = true;
11287 }
11288 }
11289
11290 if (!skip) {
11291 // If this is not being sent as an ordered broadcast, then we
11292 // don't want to touch the fields that keep track of the current
11293 // state of ordered broadcasts.
11294 if (ordered) {
11295 r.receiver = filter.receiverList.receiver.asBinder();
11296 r.curFilter = filter;
11297 filter.receiverList.curBroadcast = r;
11298 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011299 if (filter.receiverList.app != null) {
11300 // Bump hosting application to no longer be in background
11301 // scheduling class. Note that we can't do that if there
11302 // isn't an app... but we can only be in that case for
11303 // things that directly call the IActivityManager API, which
11304 // are already core system stuff so don't matter for this.
11305 r.curApp = filter.receiverList.app;
11306 filter.receiverList.app.curReceiver = r;
11307 updateOomAdjLocked();
11308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 }
11310 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011311 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011313 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011314 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011316 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011318 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 if (ordered) {
11320 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11321 }
11322 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011323 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 if (ordered) {
11325 r.receiver = null;
11326 r.curFilter = null;
11327 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011328 if (filter.receiverList.app != null) {
11329 filter.receiverList.app.curReceiver = null;
11330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 }
11332 }
11333 }
11334 }
11335
Dianne Hackborn12527f92009-11-11 17:39:50 -080011336 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11337 if (r.callingUid < 0) {
11338 // This was from a registerReceiver() call; ignore it.
11339 return;
11340 }
11341 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11342 MAX_BROADCAST_HISTORY-1);
11343 r.finishTime = SystemClock.uptimeMillis();
11344 mBroadcastHistory[0] = r;
11345 }
11346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 private final void processNextBroadcast(boolean fromMsg) {
11348 synchronized(this) {
11349 BroadcastRecord r;
11350
Joe Onorato8a9b2202010-02-26 18:56:32 -080011351 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011353 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354
11355 updateCpuStats();
11356
11357 if (fromMsg) {
11358 mBroadcastsScheduled = false;
11359 }
11360
11361 // First, deliver any non-serialized broadcasts right away.
11362 while (mParallelBroadcasts.size() > 0) {
11363 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011364 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011365 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011366 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011367 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011368 for (int i=0; i<N; i++) {
11369 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011370 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011371 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011373 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011375 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011376 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011377 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 }
11379
11380 // Now take care of the next serialized one...
11381
11382 // If we are waiting for a process to come up to handle the next
11383 // broadcast, then do nothing at this point. Just in case, we
11384 // check that the process we're waiting for still exists.
11385 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011386 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011387 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011388 + mPendingBroadcast.curApp);
11389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390
11391 boolean isDead;
11392 synchronized (mPidsSelfLocked) {
11393 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11394 }
11395 if (!isDead) {
11396 // It's still alive, so keep waiting
11397 return;
11398 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011399 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011401 mPendingBroadcast.state = BroadcastRecord.IDLE;
11402 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 mPendingBroadcast = null;
11404 }
11405 }
11406
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011407 boolean looped = false;
11408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 do {
11410 if (mOrderedBroadcasts.size() == 0) {
11411 // No more broadcasts pending, so all done!
11412 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011413 if (looped) {
11414 // If we had finished the last ordered broadcast, then
11415 // make sure all processes have correct oom and sched
11416 // adjustments.
11417 updateOomAdjLocked();
11418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 return;
11420 }
11421 r = mOrderedBroadcasts.get(0);
11422 boolean forceReceive = false;
11423
11424 // Ensure that even if something goes awry with the timeout
11425 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011426 // and continue to make progress.
11427 //
11428 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011429 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011430 // one time heavy lifting after system upgrades and can take
11431 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011433 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011434 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011435 if ((numReceivers > 0) &&
11436 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011437 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 + " now=" + now
11439 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011440 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011441 + " intent=" + r.intent
11442 + " numReceivers=" + numReceivers
11443 + " nextReceiver=" + r.nextReceiver
11444 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011445 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 forceReceive = true;
11447 r.state = BroadcastRecord.IDLE;
11448 }
11449 }
11450
11451 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011452 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 "processNextBroadcast() called when not idle (state="
11454 + r.state + ")");
11455 return;
11456 }
11457
11458 if (r.receivers == null || r.nextReceiver >= numReceivers
11459 || r.resultAbort || forceReceive) {
11460 // No more receivers for this broadcast! Send the final
11461 // result if requested...
11462 if (r.resultTo != null) {
11463 try {
11464 if (DEBUG_BROADCAST) {
11465 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011466 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 + " seq=" + seq + " app=" + r.callerApp);
11468 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011469 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011471 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011472 // Set this to null so that the reference
11473 // (local and remote) isnt kept in the mBroadcastHistory.
11474 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011476 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 }
11478 }
11479
Joe Onorato8a9b2202010-02-26 18:56:32 -080011480 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011481 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482
Joe Onorato8a9b2202010-02-26 18:56:32 -080011483 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011484 + r);
11485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011487 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 mOrderedBroadcasts.remove(0);
11489 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011490 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011491 continue;
11492 }
11493 } while (r == null);
11494
11495 // Get the next receiver...
11496 int recIdx = r.nextReceiver++;
11497
11498 // Keep track of when this receiver started, and make sure there
11499 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011500 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011501 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011502 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503
Joe Onorato8a9b2202010-02-26 18:56:32 -080011504 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011505 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011506 }
11507 if (! mPendingBroadcastTimeoutMessage) {
11508 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011509 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011510 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11511 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 }
11513
11514 Object nextReceiver = r.receivers.get(recIdx);
11515 if (nextReceiver instanceof BroadcastFilter) {
11516 // Simple case: this is a registered receiver who gets
11517 // a direct call.
11518 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011519 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011520 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011521 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011522 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011523 if (r.receiver == null || !r.ordered) {
11524 // The receiver has already finished, so schedule to
11525 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011526 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11527 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011528 r.state = BroadcastRecord.IDLE;
11529 scheduleBroadcastsLocked();
11530 }
11531 return;
11532 }
11533
11534 // Hard case: need to instantiate the receiver, possibly
11535 // starting its application process to host it.
11536
11537 ResolveInfo info =
11538 (ResolveInfo)nextReceiver;
11539
11540 boolean skip = false;
11541 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011542 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11543 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011545 if (!info.activityInfo.exported) {
11546 Slog.w(TAG, "Permission Denial: broadcasting "
11547 + r.intent.toString()
11548 + " from " + r.callerPackage + " (pid=" + r.callingPid
11549 + ", uid=" + r.callingUid + ")"
11550 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11551 + " due to receiver " + info.activityInfo.packageName
11552 + "/" + info.activityInfo.name);
11553 } else {
11554 Slog.w(TAG, "Permission Denial: broadcasting "
11555 + r.intent.toString()
11556 + " from " + r.callerPackage + " (pid=" + r.callingPid
11557 + ", uid=" + r.callingUid + ")"
11558 + " requires " + info.activityInfo.permission
11559 + " due to receiver " + info.activityInfo.packageName
11560 + "/" + info.activityInfo.name);
11561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562 skip = true;
11563 }
11564 if (r.callingUid != Process.SYSTEM_UID &&
11565 r.requiredPermission != null) {
11566 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011567 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 checkPermission(r.requiredPermission,
11569 info.activityInfo.applicationInfo.packageName);
11570 } catch (RemoteException e) {
11571 perm = PackageManager.PERMISSION_DENIED;
11572 }
11573 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011574 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 + r.intent + " to "
11576 + info.activityInfo.applicationInfo.packageName
11577 + " requires " + r.requiredPermission
11578 + " due to sender " + r.callerPackage
11579 + " (uid " + r.callingUid + ")");
11580 skip = true;
11581 }
11582 }
11583 if (r.curApp != null && r.curApp.crashing) {
11584 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011585 if (DEBUG_BROADCAST) Slog.v(TAG,
11586 "Skipping deliver ordered " + r + " to " + r.curApp
11587 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 skip = true;
11589 }
11590
11591 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011592 if (DEBUG_BROADCAST) Slog.v(TAG,
11593 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 r.receiver = null;
11595 r.curFilter = null;
11596 r.state = BroadcastRecord.IDLE;
11597 scheduleBroadcastsLocked();
11598 return;
11599 }
11600
11601 r.state = BroadcastRecord.APP_RECEIVE;
11602 String targetProcess = info.activityInfo.processName;
11603 r.curComponent = new ComponentName(
11604 info.activityInfo.applicationInfo.packageName,
11605 info.activityInfo.name);
11606 r.curReceiver = info.activityInfo;
11607
Dianne Hackborne7f97212011-02-24 14:40:20 -080011608 // Broadcast is being executed, its package can't be stopped.
11609 try {
11610 AppGlobals.getPackageManager().setPackageStoppedState(
11611 r.curComponent.getPackageName(), false);
11612 } catch (RemoteException e) {
11613 }
11614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011615 // Is this receiver's application already running?
11616 ProcessRecord app = getProcessRecordLocked(targetProcess,
11617 info.activityInfo.applicationInfo.uid);
11618 if (app != null && app.thread != null) {
11619 try {
11620 processCurBroadcastLocked(r, app);
11621 return;
11622 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011623 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 + r.curComponent, e);
11625 }
11626
11627 // If a dead object exception was thrown -- fall through to
11628 // restart the application.
11629 }
11630
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011631 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011632 if (DEBUG_BROADCAST) Slog.v(TAG,
11633 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 if ((r.curApp=startProcessLocked(targetProcess,
11635 info.activityInfo.applicationInfo, true,
11636 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011637 "broadcast", r.curComponent,
11638 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11639 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011640 // Ah, this recipient is unavailable. Finish it if necessary,
11641 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 + info.activityInfo.applicationInfo.packageName + "/"
11644 + info.activityInfo.applicationInfo.uid + " for broadcast "
11645 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011646 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11648 r.resultExtras, r.resultAbort, true);
11649 scheduleBroadcastsLocked();
11650 r.state = BroadcastRecord.IDLE;
11651 return;
11652 }
11653
11654 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011655 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011656 }
11657 }
11658
11659 // =========================================================
11660 // INSTRUMENTATION
11661 // =========================================================
11662
11663 public boolean startInstrumentation(ComponentName className,
11664 String profileFile, int flags, Bundle arguments,
11665 IInstrumentationWatcher watcher) {
11666 // Refuse possible leaked file descriptors
11667 if (arguments != null && arguments.hasFileDescriptors()) {
11668 throw new IllegalArgumentException("File descriptors passed in Bundle");
11669 }
11670
11671 synchronized(this) {
11672 InstrumentationInfo ii = null;
11673 ApplicationInfo ai = null;
11674 try {
11675 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011676 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011678 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 } catch (PackageManager.NameNotFoundException e) {
11680 }
11681 if (ii == null) {
11682 reportStartInstrumentationFailure(watcher, className,
11683 "Unable to find instrumentation info for: " + className);
11684 return false;
11685 }
11686 if (ai == null) {
11687 reportStartInstrumentationFailure(watcher, className,
11688 "Unable to find instrumentation target package: " + ii.targetPackage);
11689 return false;
11690 }
11691
11692 int match = mContext.getPackageManager().checkSignatures(
11693 ii.targetPackage, ii.packageName);
11694 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11695 String msg = "Permission Denial: starting instrumentation "
11696 + className + " from pid="
11697 + Binder.getCallingPid()
11698 + ", uid=" + Binder.getCallingPid()
11699 + " not allowed because package " + ii.packageName
11700 + " does not have a signature matching the target "
11701 + ii.targetPackage;
11702 reportStartInstrumentationFailure(watcher, className, msg);
11703 throw new SecurityException(msg);
11704 }
11705
11706 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011707 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708 ProcessRecord app = addAppLocked(ai);
11709 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011710 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011711 app.instrumentationProfileFile = profileFile;
11712 app.instrumentationArguments = arguments;
11713 app.instrumentationWatcher = watcher;
11714 app.instrumentationResultClass = className;
11715 Binder.restoreCallingIdentity(origId);
11716 }
11717
11718 return true;
11719 }
11720
11721 /**
11722 * Report errors that occur while attempting to start Instrumentation. Always writes the
11723 * error to the logs, but if somebody is watching, send the report there too. This enables
11724 * the "am" command to report errors with more information.
11725 *
11726 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11727 * @param cn The component name of the instrumentation.
11728 * @param report The error report.
11729 */
11730 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11731 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011732 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 try {
11734 if (watcher != null) {
11735 Bundle results = new Bundle();
11736 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11737 results.putString("Error", report);
11738 watcher.instrumentationStatus(cn, -1, results);
11739 }
11740 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011741 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742 }
11743 }
11744
11745 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11746 if (app.instrumentationWatcher != null) {
11747 try {
11748 // NOTE: IInstrumentationWatcher *must* be oneway here
11749 app.instrumentationWatcher.instrumentationFinished(
11750 app.instrumentationClass,
11751 resultCode,
11752 results);
11753 } catch (RemoteException e) {
11754 }
11755 }
11756 app.instrumentationWatcher = null;
11757 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011758 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 app.instrumentationProfileFile = null;
11760 app.instrumentationArguments = null;
11761
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011762 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 }
11764
11765 public void finishInstrumentation(IApplicationThread target,
11766 int resultCode, Bundle results) {
11767 // Refuse possible leaked file descriptors
11768 if (results != null && results.hasFileDescriptors()) {
11769 throw new IllegalArgumentException("File descriptors passed in Intent");
11770 }
11771
11772 synchronized(this) {
11773 ProcessRecord app = getRecordForAppLocked(target);
11774 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011775 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 return;
11777 }
11778 final long origId = Binder.clearCallingIdentity();
11779 finishInstrumentationLocked(app, resultCode, results);
11780 Binder.restoreCallingIdentity(origId);
11781 }
11782 }
11783
11784 // =========================================================
11785 // CONFIGURATION
11786 // =========================================================
11787
11788 public ConfigurationInfo getDeviceConfigurationInfo() {
11789 ConfigurationInfo config = new ConfigurationInfo();
11790 synchronized (this) {
11791 config.reqTouchScreen = mConfiguration.touchscreen;
11792 config.reqKeyboardType = mConfiguration.keyboard;
11793 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011794 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11795 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11797 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011798 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11799 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11801 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011802 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011803 }
11804 return config;
11805 }
11806
11807 public Configuration getConfiguration() {
11808 Configuration ci;
11809 synchronized(this) {
11810 ci = new Configuration(mConfiguration);
11811 }
11812 return ci;
11813 }
11814
11815 public void updateConfiguration(Configuration values) {
11816 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11817 "updateConfiguration()");
11818
11819 synchronized(this) {
11820 if (values == null && mWindowManager != null) {
11821 // sentinel: fetch the current configuration from the window manager
11822 values = mWindowManager.computeNewConfiguration();
11823 }
11824
11825 final long origId = Binder.clearCallingIdentity();
11826 updateConfigurationLocked(values, null);
11827 Binder.restoreCallingIdentity(origId);
11828 }
11829 }
11830
11831 /**
11832 * Do either or both things: (1) change the current configuration, and (2)
11833 * make sure the given activity is running with the (now) current
11834 * configuration. Returns true if the activity has been left running, or
11835 * false if <var>starting</var> is being destroyed to match the new
11836 * configuration.
11837 */
11838 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011839 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 int changes = 0;
11841
11842 boolean kept = true;
11843
11844 if (values != null) {
11845 Configuration newConfig = new Configuration(mConfiguration);
11846 changes = newConfig.updateFrom(values);
11847 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011848 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011849 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 }
11851
Doug Zongker2bec3d42009-12-04 12:52:44 -080011852 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853
11854 if (values.locale != null) {
11855 saveLocaleLocked(values.locale,
11856 !values.locale.equals(mConfiguration.locale),
11857 values.userSetLocale);
11858 }
11859
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011860 mConfigurationSeq++;
11861 if (mConfigurationSeq <= 0) {
11862 mConfigurationSeq = 1;
11863 }
11864 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011866 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011867
11868 AttributeCache ac = AttributeCache.instance();
11869 if (ac != null) {
11870 ac.updateConfiguration(mConfiguration);
11871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011872
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011873 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11874 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11875 msg.obj = new Configuration(mConfiguration);
11876 mHandler.sendMessage(msg);
11877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011879 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11880 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 try {
11882 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011883 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011884 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 app.thread.scheduleConfigurationChanged(mConfiguration);
11886 }
11887 } catch (Exception e) {
11888 }
11889 }
11890 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011891 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11892 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11894 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011895 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11896 broadcastIntentLocked(null, null,
11897 new Intent(Intent.ACTION_LOCALE_CHANGED),
11898 null, null, 0, null, null,
11899 null, false, false, MY_PID, Process.SYSTEM_UID);
11900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011901 }
11902 }
11903
11904 if (changes != 0 && starting == null) {
11905 // If the configuration changed, and the caller is not already
11906 // in the process of starting an activity, then find the top
11907 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011908 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 }
11910
11911 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011912 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011913 // And we need to make sure at this point that all other activities
11914 // are made visible with the correct configuration.
11915 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916 }
11917
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011918 if (values != null && mWindowManager != null) {
11919 mWindowManager.setNewConfiguration(mConfiguration);
11920 }
11921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011922 return kept;
11923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011924
11925 /**
11926 * Save the locale. You must be inside a synchronized (this) block.
11927 */
11928 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11929 if(isDiff) {
11930 SystemProperties.set("user.language", l.getLanguage());
11931 SystemProperties.set("user.region", l.getCountry());
11932 }
11933
11934 if(isPersist) {
11935 SystemProperties.set("persist.sys.language", l.getLanguage());
11936 SystemProperties.set("persist.sys.country", l.getCountry());
11937 SystemProperties.set("persist.sys.localevar", l.getVariant());
11938 }
11939 }
11940
11941 // =========================================================
11942 // LIFETIME MANAGEMENT
11943 // =========================================================
11944
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011945 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11946 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011948 // This adjustment has already been computed. If we are calling
11949 // from the top, we may have already computed our adjustment with
11950 // an earlier hidden adjustment that isn't really for us... if
11951 // so, use the new hidden adjustment.
11952 if (!recursed && app.hidden) {
11953 app.curAdj = hiddenAdj;
11954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 return app.curAdj;
11956 }
11957
11958 if (app.thread == null) {
11959 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011960 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011961 return (app.curAdj=EMPTY_APP_ADJ);
11962 }
11963
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011964 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11965 // The max adjustment doesn't allow this app to be anything
11966 // below foreground, so it is not worth doing work for it.
11967 app.adjType = "fixed";
11968 app.adjSeq = mAdjSeq;
11969 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011970 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011971 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11972 return (app.curAdj=app.maxAdj);
11973 }
11974
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011975 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011976 app.adjSource = null;
11977 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011978 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011979 app.empty = false;
11980 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011981
The Android Open Source Project4df24232009-03-05 14:34:35 -080011982 // Determine the importance of the process, starting with most
11983 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011984 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011985 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011987 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988 // The last app on the list is the foreground app.
11989 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011990 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011991 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011992 } else if (app.instrumentationClass != null) {
11993 // Don't want to kill running instrumentation.
11994 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011995 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011996 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011997 } else if (app.curReceiver != null ||
11998 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11999 // An app that is currently receiving a broadcast also
12000 // counts as being in the foreground.
12001 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012002 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012003 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 } else if (app.executingServices.size() > 0) {
12005 // An app that is currently executing a service callback also
12006 // counts as being in the foreground.
12007 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012008 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012009 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012010 } else if ((N=app.activities.size()) != 0) {
12011 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012012 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012014 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012015 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012016 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012018 ActivityRecord r = app.activities.get(j);
12019 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012021 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012023 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012024 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012026 } else if (r.state == ActivityState.PAUSING
12027 || r.state == ActivityState.PAUSED
12028 || r.state == ActivityState.STOPPING) {
12029 adj = PERCEPTIBLE_APP_ADJ;
12030 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012031 }
12032 }
12033 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012034 // A very not-needed process. If this is lower in the lru list,
12035 // we will push it in to the empty bucket.
12036 app.hidden = true;
12037 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012038 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012039 adj = hiddenAdj;
12040 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012042
12043 if (adj > PERCEPTIBLE_APP_ADJ) {
12044 if (app.foregroundServices) {
12045 // The user is aware of this app, so make it visible.
12046 adj = PERCEPTIBLE_APP_ADJ;
12047 schedGroup = Process.THREAD_GROUP_DEFAULT;
12048 app.adjType = "foreground-service";
12049 } else if (app.forcingToForeground != null) {
12050 // The user is aware of this app, so make it visible.
12051 adj = PERCEPTIBLE_APP_ADJ;
12052 schedGroup = Process.THREAD_GROUP_DEFAULT;
12053 app.adjType = "force-foreground";
12054 app.adjSource = app.forcingToForeground;
12055 }
12056 }
12057
12058 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12059 // We don't want to kill the current heavy-weight process.
12060 adj = HEAVY_WEIGHT_APP_ADJ;
12061 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12062 app.adjType = "heavy";
12063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012064
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012065 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12066 // This process is hosting what we currently consider to be the
12067 // home app, so we don't want to let it go into the background.
12068 adj = HOME_APP_ADJ;
12069 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12070 app.adjType = "home";
12071 }
12072
Joe Onorato8a9b2202010-02-26 18:56:32 -080012073 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012074
The Android Open Source Project4df24232009-03-05 14:34:35 -080012075 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 // there are applications dependent on our services or providers, but
12077 // this gives us a baseline and makes sure we don't get into an
12078 // infinite recursion.
12079 app.adjSeq = mAdjSeq;
12080 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012081
Christopher Tate6fa95972009-06-05 18:43:55 -070012082 if (mBackupTarget != null && app == mBackupTarget.app) {
12083 // If possible we want to avoid killing apps while they're being backed up
12084 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012085 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012086 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012087 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012088 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012089 }
12090 }
12091
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012092 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12093 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 final long now = SystemClock.uptimeMillis();
12095 // This process is more important if the top activity is
12096 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012097 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012098 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012099 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012100 if (s.startRequested) {
12101 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12102 // This service has seen some activity within
12103 // recent memory, so we will keep its process ahead
12104 // of the background processes.
12105 if (adj > SECONDARY_SERVER_ADJ) {
12106 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012107 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012108 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012109 }
12110 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012111 // If we have let the service slide into the background
12112 // state, still have some text describing what it is doing
12113 // even though the service no longer has an impact.
12114 if (adj > SECONDARY_SERVER_ADJ) {
12115 app.adjType = "started-bg-services";
12116 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012117 // Don't kill this process because it is doing work; it
12118 // has said it is doing work.
12119 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012121 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12122 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012123 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012124 = s.connections.values().iterator();
12125 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012126 ArrayList<ConnectionRecord> clist = kt.next();
12127 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12128 // XXX should compute this based on the max of
12129 // all connected clients.
12130 ConnectionRecord cr = clist.get(i);
12131 if (cr.binding.client == app) {
12132 // Binding to ourself is not interesting.
12133 continue;
12134 }
12135 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12136 ProcessRecord client = cr.binding.client;
12137 int myHiddenAdj = hiddenAdj;
12138 if (myHiddenAdj > client.hiddenAdj) {
12139 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12140 myHiddenAdj = client.hiddenAdj;
12141 } else {
12142 myHiddenAdj = VISIBLE_APP_ADJ;
12143 }
12144 }
12145 int clientAdj = computeOomAdjLocked(
12146 client, myHiddenAdj, TOP_APP, true);
12147 if (adj > clientAdj) {
12148 adj = clientAdj >= VISIBLE_APP_ADJ
12149 ? clientAdj : VISIBLE_APP_ADJ;
12150 if (!client.hidden) {
12151 app.hidden = false;
12152 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012153 if (client.keeping) {
12154 app.keeping = true;
12155 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012156 app.adjType = "service";
12157 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12158 .REASON_SERVICE_IN_USE;
12159 app.adjSource = cr.binding.client;
12160 app.adjTarget = s.name;
12161 }
12162 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12163 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12164 schedGroup = Process.THREAD_GROUP_DEFAULT;
12165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 }
12167 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012168 ActivityRecord a = cr.activity;
12169 //if (a != null) {
12170 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12171 //}
12172 if (a != null && adj > FOREGROUND_APP_ADJ &&
12173 (a.state == ActivityState.RESUMED
12174 || a.state == ActivityState.PAUSING)) {
12175 adj = FOREGROUND_APP_ADJ;
12176 schedGroup = Process.THREAD_GROUP_DEFAULT;
12177 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012178 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012179 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12180 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012181 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012182 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012184 }
12185 }
12186 }
12187 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012188
Dianne Hackborn287952c2010-09-22 22:34:31 -070012189 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012190 // would like to avoid killing it unless it would prevent the current
12191 // application from running. By default we put the process in
12192 // with the rest of the background processes; as we scan through
12193 // its services we may bump it up from there.
12194 if (adj > hiddenAdj) {
12195 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012196 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012197 app.adjType = "bg-services";
12198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 }
12200
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012201 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12202 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012203 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012204 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12205 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012206 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 if (cpr.clients.size() != 0) {
12208 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12209 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12210 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012211 if (client == app) {
12212 // Being our own client is not interesting.
12213 continue;
12214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 int myHiddenAdj = hiddenAdj;
12216 if (myHiddenAdj > client.hiddenAdj) {
12217 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12218 myHiddenAdj = client.hiddenAdj;
12219 } else {
12220 myHiddenAdj = FOREGROUND_APP_ADJ;
12221 }
12222 }
12223 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012224 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012225 if (adj > clientAdj) {
12226 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012227 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012228 if (!client.hidden) {
12229 app.hidden = false;
12230 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012231 if (client.keeping) {
12232 app.keeping = true;
12233 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012234 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012235 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12236 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012237 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012238 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012240 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12241 schedGroup = Process.THREAD_GROUP_DEFAULT;
12242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012243 }
12244 }
12245 // If the provider has external (non-framework) process
12246 // dependencies, ensure that its adjustment is at least
12247 // FOREGROUND_APP_ADJ.
12248 if (cpr.externals != 0) {
12249 if (adj > FOREGROUND_APP_ADJ) {
12250 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012251 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012252 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012253 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012254 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012255 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012256 }
12257 }
12258 }
12259 }
12260
12261 app.curRawAdj = adj;
12262
Joe Onorato8a9b2202010-02-26 18:56:32 -080012263 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12265 if (adj > app.maxAdj) {
12266 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012267 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012268 schedGroup = Process.THREAD_GROUP_DEFAULT;
12269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012270 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012271 if (adj < HIDDEN_APP_MIN_ADJ) {
12272 app.keeping = true;
12273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274
12275 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012276 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012278 return adj;
12279 }
12280
12281 /**
12282 * Ask a given process to GC right now.
12283 */
12284 final void performAppGcLocked(ProcessRecord app) {
12285 try {
12286 app.lastRequestedGc = SystemClock.uptimeMillis();
12287 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012288 if (app.reportLowMemory) {
12289 app.reportLowMemory = false;
12290 app.thread.scheduleLowMemory();
12291 } else {
12292 app.thread.processInBackground();
12293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 }
12295 } catch (Exception e) {
12296 // whatever.
12297 }
12298 }
12299
12300 /**
12301 * Returns true if things are idle enough to perform GCs.
12302 */
Josh Bartel7f208742010-02-25 11:01:44 -060012303 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012304 return mParallelBroadcasts.size() == 0
12305 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012306 && (mSleeping || (mMainStack.mResumedActivity != null &&
12307 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 }
12309
12310 /**
12311 * Perform GCs on all processes that are waiting for it, but only
12312 * if things are idle.
12313 */
12314 final void performAppGcsLocked() {
12315 final int N = mProcessesToGc.size();
12316 if (N <= 0) {
12317 return;
12318 }
Josh Bartel7f208742010-02-25 11:01:44 -060012319 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012320 while (mProcessesToGc.size() > 0) {
12321 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012322 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012323 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12324 <= SystemClock.uptimeMillis()) {
12325 // To avoid spamming the system, we will GC processes one
12326 // at a time, waiting a few seconds between each.
12327 performAppGcLocked(proc);
12328 scheduleAppGcsLocked();
12329 return;
12330 } else {
12331 // It hasn't been long enough since we last GCed this
12332 // process... put it in the list to wait for its time.
12333 addProcessToGcListLocked(proc);
12334 break;
12335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 }
12337 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012338
12339 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012340 }
12341 }
12342
12343 /**
12344 * If all looks good, perform GCs on all processes waiting for them.
12345 */
12346 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012347 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012348 performAppGcsLocked();
12349 return;
12350 }
12351 // Still not idle, wait some more.
12352 scheduleAppGcsLocked();
12353 }
12354
12355 /**
12356 * Schedule the execution of all pending app GCs.
12357 */
12358 final void scheduleAppGcsLocked() {
12359 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012360
12361 if (mProcessesToGc.size() > 0) {
12362 // Schedule a GC for the time to the next process.
12363 ProcessRecord proc = mProcessesToGc.get(0);
12364 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12365
12366 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12367 long now = SystemClock.uptimeMillis();
12368 if (when < (now+GC_TIMEOUT)) {
12369 when = now + GC_TIMEOUT;
12370 }
12371 mHandler.sendMessageAtTime(msg, when);
12372 }
12373 }
12374
12375 /**
12376 * Add a process to the array of processes waiting to be GCed. Keeps the
12377 * list in sorted order by the last GC time. The process can't already be
12378 * on the list.
12379 */
12380 final void addProcessToGcListLocked(ProcessRecord proc) {
12381 boolean added = false;
12382 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12383 if (mProcessesToGc.get(i).lastRequestedGc <
12384 proc.lastRequestedGc) {
12385 added = true;
12386 mProcessesToGc.add(i+1, proc);
12387 break;
12388 }
12389 }
12390 if (!added) {
12391 mProcessesToGc.add(0, proc);
12392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012393 }
12394
12395 /**
12396 * Set up to ask a process to GC itself. This will either do it
12397 * immediately, or put it on the list of processes to gc the next
12398 * time things are idle.
12399 */
12400 final void scheduleAppGcLocked(ProcessRecord app) {
12401 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012402 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 return;
12404 }
12405 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012406 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012407 scheduleAppGcsLocked();
12408 }
12409 }
12410
Dianne Hackborn287952c2010-09-22 22:34:31 -070012411 final void checkExcessivePowerUsageLocked(boolean doKills) {
12412 updateCpuStatsNow();
12413
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012414 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012415 boolean doWakeKills = doKills;
12416 boolean doCpuKills = doKills;
12417 if (mLastPowerCheckRealtime == 0) {
12418 doWakeKills = false;
12419 }
12420 if (mLastPowerCheckUptime == 0) {
12421 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012422 }
12423 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012424 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012425 }
12426 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012427 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12428 final long curUptime = SystemClock.uptimeMillis();
12429 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12430 mLastPowerCheckRealtime = curRealtime;
12431 mLastPowerCheckUptime = curUptime;
12432 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12433 doWakeKills = false;
12434 }
12435 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12436 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012437 }
12438 int i = mLruProcesses.size();
12439 while (i > 0) {
12440 i--;
12441 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012442 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012443 long wtime;
12444 synchronized (stats) {
12445 wtime = stats.getProcessWakeTime(app.info.uid,
12446 app.pid, curRealtime);
12447 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012448 long wtimeUsed = wtime - app.lastWakeTime;
12449 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12450 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012451 StringBuilder sb = new StringBuilder(128);
12452 sb.append("Wake for ");
12453 app.toShortString(sb);
12454 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012455 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012456 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012457 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012458 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012459 sb.append((wtimeUsed*100)/realtimeSince);
12460 sb.append("%)");
12461 Slog.i(TAG, sb.toString());
12462 sb.setLength(0);
12463 sb.append("CPU for ");
12464 app.toShortString(sb);
12465 sb.append(": over ");
12466 TimeUtils.formatDuration(uptimeSince, sb);
12467 sb.append(" used ");
12468 TimeUtils.formatDuration(cputimeUsed, sb);
12469 sb.append(" (");
12470 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012471 sb.append("%)");
12472 Slog.i(TAG, sb.toString());
12473 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012474 // If a process has held a wake lock for more
12475 // than 50% of the time during this period,
12476 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012477 if (doWakeKills && realtimeSince > 0
12478 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12479 synchronized (stats) {
12480 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12481 realtimeSince, wtimeUsed);
12482 }
12483 Slog.w(TAG, "Excessive wake lock in " + app.processName
12484 + " (pid " + app.pid + "): held " + wtimeUsed
12485 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012486 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12487 app.processName, app.setAdj, "excessive wake lock");
12488 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012489 } else if (doCpuKills && uptimeSince > 0
12490 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12491 synchronized (stats) {
12492 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12493 uptimeSince, cputimeUsed);
12494 }
12495 Slog.w(TAG, "Excessive CPU in " + app.processName
12496 + " (pid " + app.pid + "): used " + cputimeUsed
12497 + " during " + uptimeSince);
12498 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12499 app.processName, app.setAdj, "excessive cpu");
12500 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012501 } else {
12502 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012503 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012504 }
12505 }
12506 }
12507 }
12508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 private final boolean updateOomAdjLocked(
12510 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12511 app.hiddenAdj = hiddenAdj;
12512
12513 if (app.thread == null) {
12514 return true;
12515 }
12516
Dianne Hackborn287952c2010-09-22 22:34:31 -070012517 final boolean wasKeeping = app.keeping;
12518
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012519 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012520
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012521 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 if (app.curRawAdj != app.setRawAdj) {
12523 if (app.curRawAdj > FOREGROUND_APP_ADJ
12524 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12525 // If this app is transitioning from foreground to
12526 // non-foreground, have it do a gc.
12527 scheduleAppGcLocked(app);
12528 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12529 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12530 // Likewise do a gc when an app is moving in to the
12531 // background (such as a service stopping).
12532 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012533 }
12534
12535 if (wasKeeping && !app.keeping) {
12536 // This app is no longer something we want to keep. Note
12537 // its current wake lock time to later know to kill it if
12538 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012539 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12540 synchronized (stats) {
12541 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12542 app.pid, SystemClock.elapsedRealtime());
12543 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012544 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547 app.setRawAdj = app.curRawAdj;
12548 }
12549 if (adj != app.setAdj) {
12550 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012551 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012552 TAG, "Set app " + app.processName +
12553 " oom adj to " + adj);
12554 app.setAdj = adj;
12555 } else {
12556 return false;
12557 }
12558 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012559 if (app.setSchedGroup != app.curSchedGroup) {
12560 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012561 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012562 "Setting process group of " + app.processName
12563 + " to " + app.curSchedGroup);
12564 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012565 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012566 try {
12567 Process.setProcessGroup(app.pid, app.curSchedGroup);
12568 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012569 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012570 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012571 e.printStackTrace();
12572 } finally {
12573 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012574 }
12575 }
12576 if (false) {
12577 if (app.thread != null) {
12578 try {
12579 app.thread.setSchedulingGroup(app.curSchedGroup);
12580 } catch (RemoteException e) {
12581 }
12582 }
12583 }
12584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012585 }
12586
12587 return true;
12588 }
12589
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012590 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012591 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012592 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012593 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012594 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012595 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012596 }
12597 }
12598 return resumedActivity;
12599 }
12600
12601 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012602 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12604 int curAdj = app.curAdj;
12605 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12606 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12607
12608 mAdjSeq++;
12609
12610 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12611 if (res) {
12612 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12613 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12614 if (nowHidden != wasHidden) {
12615 // Changed to/from hidden state, so apps after it in the LRU
12616 // list may also be changed.
12617 updateOomAdjLocked();
12618 }
12619 }
12620 return res;
12621 }
12622
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012623 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012624 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012625 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12627
12628 if (false) {
12629 RuntimeException e = new RuntimeException();
12630 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012631 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012632 }
12633
12634 mAdjSeq++;
12635
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012636 // Let's determine how many processes we have running vs.
12637 // how many slots we have for background processes; we may want
12638 // to put multiple processes in a slot of there are enough of
12639 // them.
12640 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12641 int factor = (mLruProcesses.size()-4)/numSlots;
12642 if (factor < 1) factor = 1;
12643 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012644 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012646 // First try updating the OOM adjustment for each of the
12647 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012648 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012649 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12650 while (i > 0) {
12651 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012652 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012653 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012655 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012657 step++;
12658 if (step >= factor) {
12659 step = 0;
12660 curHiddenAdj++;
12661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012663 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012664 if (!app.killedBackground) {
12665 numHidden++;
12666 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012667 Slog.i(TAG, "No longer want " + app.processName
12668 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012669 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12670 app.processName, app.setAdj, "too many background");
12671 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012672 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012673 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012674 }
12675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676 } else {
12677 didOomAdj = false;
12678 }
12679 }
12680
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012681 // If we return false, we will fall back on killing processes to
12682 // have a fixed limit. Do this if a limit has been requested; else
12683 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012684 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12685 }
12686
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012687 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 synchronized (this) {
12689 int i;
12690
12691 // First remove any unused application processes whose package
12692 // has been removed.
12693 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12694 final ProcessRecord app = mRemovedProcesses.get(i);
12695 if (app.activities.size() == 0
12696 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012697 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012698 TAG, "Exiting empty application process "
12699 + app.processName + " ("
12700 + (app.thread != null ? app.thread.asBinder() : null)
12701 + ")\n");
12702 if (app.pid > 0 && app.pid != MY_PID) {
12703 Process.killProcess(app.pid);
12704 } else {
12705 try {
12706 app.thread.scheduleExit();
12707 } catch (Exception e) {
12708 // Ignore exceptions.
12709 }
12710 }
12711 cleanUpApplicationRecordLocked(app, false, -1);
12712 mRemovedProcesses.remove(i);
12713
12714 if (app.persistent) {
12715 if (app.persistent) {
12716 addAppLocked(app.info);
12717 }
12718 }
12719 }
12720 }
12721
12722 // Now try updating the OOM adjustment for each of the
12723 // application processes based on their current state.
12724 // If the setOomAdj() API is not supported, then go with our
12725 // back-up plan...
12726 if (!updateOomAdjLocked()) {
12727
12728 // Count how many processes are running services.
12729 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012730 for (i=mLruProcesses.size()-1; i>=0; i--) {
12731 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012732
12733 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012734 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012735 // Don't count processes holding services against our
12736 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012737 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012738 TAG, "Not trimming app " + app + " with services: "
12739 + app.services);
12740 numServiceProcs++;
12741 }
12742 }
12743
12744 int curMaxProcs = mProcessLimit;
12745 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12746 if (mAlwaysFinishActivities) {
12747 curMaxProcs = 1;
12748 }
12749 curMaxProcs += numServiceProcs;
12750
12751 // Quit as many processes as we can to get down to the desired
12752 // process count. First remove any processes that no longer
12753 // have activites running in them.
12754 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012755 i<mLruProcesses.size()
12756 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012758 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012759 // Quit an application only if it is not currently
12760 // running any activities.
12761 if (!app.persistent && app.activities.size() == 0
12762 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012763 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 TAG, "Exiting empty application process "
12765 + app.processName + " ("
12766 + (app.thread != null ? app.thread.asBinder() : null)
12767 + ")\n");
12768 if (app.pid > 0 && app.pid != MY_PID) {
12769 Process.killProcess(app.pid);
12770 } else {
12771 try {
12772 app.thread.scheduleExit();
12773 } catch (Exception e) {
12774 // Ignore exceptions.
12775 }
12776 }
12777 // todo: For now we assume the application is not buggy
12778 // or evil, and will quit as a result of our request.
12779 // Eventually we need to drive this off of the death
12780 // notification, and kill the process if it takes too long.
12781 cleanUpApplicationRecordLocked(app, false, i);
12782 i--;
12783 }
12784 }
12785
12786 // If we still have too many processes, now from the least
12787 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012788 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012789 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012790 " of " + curMaxProcs + " processes");
12791 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012792 i<mLruProcesses.size()
12793 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012794 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012795 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012796 // Quit the application only if we have a state saved for
12797 // all of its activities.
12798 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012799 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 int NUMA = app.activities.size();
12801 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012802 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012803 TAG, "Looking to quit " + app.processName);
12804 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012805 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012806 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012807 TAG, " " + r.intent.getComponent().flattenToShortString()
12808 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12809 canQuit = (r.haveState || !r.stateNotNeeded)
12810 && !r.visible && r.stopped;
12811 }
12812 if (canQuit) {
12813 // Finish all of the activities, and then the app itself.
12814 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012815 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012816 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012817 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818 }
12819 r.resultTo = null;
12820 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012821 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012822 + app.processName + " ("
12823 + (app.thread != null ? app.thread.asBinder() : null)
12824 + ")\n");
12825 if (app.pid > 0 && app.pid != MY_PID) {
12826 Process.killProcess(app.pid);
12827 } else {
12828 try {
12829 app.thread.scheduleExit();
12830 } catch (Exception e) {
12831 // Ignore exceptions.
12832 }
12833 }
12834 // todo: For now we assume the application is not buggy
12835 // or evil, and will quit as a result of our request.
12836 // Eventually we need to drive this off of the death
12837 // notification, and kill the process if it takes too long.
12838 cleanUpApplicationRecordLocked(app, false, i);
12839 i--;
12840 //dump();
12841 }
12842 }
12843
12844 }
12845
12846 int curMaxActivities = MAX_ACTIVITIES;
12847 if (mAlwaysFinishActivities) {
12848 curMaxActivities = 1;
12849 }
12850
12851 // Finally, if there are too many activities now running, try to
12852 // finish as many as we can to get back down to the limit.
12853 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012854 i<mMainStack.mLRUActivities.size()
12855 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012857 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012858 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012859
12860 // We can finish this one if we have its icicle saved and
12861 // it is not persistent.
12862 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012863 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012864 final int origSize = mMainStack.mLRUActivities.size();
12865 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866
12867 // This will remove it from the LRU list, so keep
12868 // our index at the same value. Note that this check to
12869 // see if the size changes is just paranoia -- if
12870 // something unexpected happens, we don't want to end up
12871 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012872 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 i--;
12874 }
12875 }
12876 }
12877 }
12878 }
12879
12880 /** This method sends the specified signal to each of the persistent apps */
12881 public void signalPersistentProcesses(int sig) throws RemoteException {
12882 if (sig != Process.SIGNAL_USR1) {
12883 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12884 }
12885
12886 synchronized (this) {
12887 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12888 != PackageManager.PERMISSION_GRANTED) {
12889 throw new SecurityException("Requires permission "
12890 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12891 }
12892
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012893 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12894 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012895 if (r.thread != null && r.persistent) {
12896 Process.sendSignal(r.pid, sig);
12897 }
12898 }
12899 }
12900 }
12901
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012902 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012903 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012904
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012905 try {
12906 synchronized (this) {
12907 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12908 // its own permission.
12909 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12910 != PackageManager.PERMISSION_GRANTED) {
12911 throw new SecurityException("Requires permission "
12912 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012913 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012914
12915 if (start && fd == null) {
12916 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012917 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012918
12919 ProcessRecord proc = null;
12920 try {
12921 int pid = Integer.parseInt(process);
12922 synchronized (mPidsSelfLocked) {
12923 proc = mPidsSelfLocked.get(pid);
12924 }
12925 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012926 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012927
12928 if (proc == null) {
12929 HashMap<String, SparseArray<ProcessRecord>> all
12930 = mProcessNames.getMap();
12931 SparseArray<ProcessRecord> procs = all.get(process);
12932 if (procs != null && procs.size() > 0) {
12933 proc = procs.valueAt(0);
12934 }
12935 }
12936
12937 if (proc == null || proc.thread == null) {
12938 throw new IllegalArgumentException("Unknown process: " + process);
12939 }
12940
12941 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12942 if (isSecure) {
12943 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12944 throw new SecurityException("Process not debuggable: " + proc);
12945 }
12946 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012947
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012948 proc.thread.profilerControl(start, path, fd);
12949 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012950 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012951 }
12952 } catch (RemoteException e) {
12953 throw new IllegalStateException("Process disappeared");
12954 } finally {
12955 if (fd != null) {
12956 try {
12957 fd.close();
12958 } catch (IOException e) {
12959 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012960 }
12961 }
12962 }
Andy McFadden824c5102010-07-09 16:26:57 -070012963
12964 public boolean dumpHeap(String process, boolean managed,
12965 String path, ParcelFileDescriptor fd) throws RemoteException {
12966
12967 try {
12968 synchronized (this) {
12969 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12970 // its own permission (same as profileControl).
12971 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12972 != PackageManager.PERMISSION_GRANTED) {
12973 throw new SecurityException("Requires permission "
12974 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12975 }
12976
12977 if (fd == null) {
12978 throw new IllegalArgumentException("null fd");
12979 }
12980
12981 ProcessRecord proc = null;
12982 try {
12983 int pid = Integer.parseInt(process);
12984 synchronized (mPidsSelfLocked) {
12985 proc = mPidsSelfLocked.get(pid);
12986 }
12987 } catch (NumberFormatException e) {
12988 }
12989
12990 if (proc == null) {
12991 HashMap<String, SparseArray<ProcessRecord>> all
12992 = mProcessNames.getMap();
12993 SparseArray<ProcessRecord> procs = all.get(process);
12994 if (procs != null && procs.size() > 0) {
12995 proc = procs.valueAt(0);
12996 }
12997 }
12998
12999 if (proc == null || proc.thread == null) {
13000 throw new IllegalArgumentException("Unknown process: " + process);
13001 }
13002
13003 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
13004 if (isSecure) {
13005 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13006 throw new SecurityException("Process not debuggable: " + proc);
13007 }
13008 }
13009
13010 proc.thread.dumpHeap(managed, path, fd);
13011 fd = null;
13012 return true;
13013 }
13014 } catch (RemoteException e) {
13015 throw new IllegalStateException("Process disappeared");
13016 } finally {
13017 if (fd != null) {
13018 try {
13019 fd.close();
13020 } catch (IOException e) {
13021 }
13022 }
13023 }
13024 }
13025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013026 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13027 public void monitor() {
13028 synchronized (this) { }
13029 }
13030}