blob: 50054bdecca776743c0537e5dec97a45773ebb66 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700115import java.io.BufferedInputStream;
116import java.io.BufferedOutputStream;
117import java.io.DataInputStream;
118import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.io.File;
120import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700121import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700123import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200124import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800125import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.io.PrintWriter;
127import java.lang.IllegalStateException;
128import java.lang.ref.WeakReference;
129import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700130import java.util.Collections;
131import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132import java.util.HashMap;
133import java.util.HashSet;
134import java.util.Iterator;
135import java.util.List;
136import java.util.Locale;
137import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700138import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700139import java.util.concurrent.atomic.AtomicBoolean;
140import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700142public final class ActivityManagerService extends ActivityManagerNative
143 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 static final String TAG = "ActivityManager";
145 static final boolean DEBUG = false;
146 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
147 static final boolean DEBUG_SWITCH = localLOGV || false;
148 static final boolean DEBUG_TASKS = localLOGV || false;
149 static final boolean DEBUG_PAUSE = localLOGV || false;
150 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
151 static final boolean DEBUG_TRANSITION = localLOGV || false;
152 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700153 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700155 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 static final boolean DEBUG_VISBILITY = localLOGV || false;
157 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700158 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800159 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700161 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700162 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700163 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700164 static final boolean DEBUG_POWER = localLOGV || false;
165 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static final boolean VALIDATE_TOKENS = false;
167 static final boolean SHOW_ACTIVITY_START_TIME = true;
168
169 // Control over CPU and battery monitoring.
170 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
171 static final boolean MONITOR_CPU_USAGE = true;
172 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
173 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
174 static final boolean MONITOR_THREAD_CPU_USAGE = false;
175
Dianne Hackborn1655be42009-05-08 14:29:01 -0700176 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700177 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 private static final String SYSTEM_SECURE = "ro.secure";
180
181 // This is the maximum number of application processes we would like
182 // to have running. Due to the asynchronous nature of things, we can
183 // temporarily go beyond this limit.
184 static final int MAX_PROCESSES = 2;
185
186 // Set to false to leave processes running indefinitely, relying on
187 // the kernel killing them as resources are required.
188 static final boolean ENFORCE_PROCESS_LIMIT = false;
189
190 // This is the maximum number of activities that we would like to have
191 // running at a given time.
192 static final int MAX_ACTIVITIES = 20;
193
194 // Maximum number of recent tasks that we can remember.
195 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700196
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700197 // Amount of time after a call to stopAppSwitches() during which we will
198 // prevent further untrusted switches from happening.
199 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
201 // How long we wait for a launched process to attach to the activity manager
202 // before we decide it's never going to come up for real.
203 static final int PROC_START_TIMEOUT = 10*1000;
204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 // How long to wait after going idle before forcing apps to GC.
206 static final int GC_TIMEOUT = 5*1000;
207
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700208 // The minimum amount of time between successive GC requests for a process.
209 static final int GC_MIN_INTERVAL = 60*1000;
210
Dianne Hackborn287952c2010-09-22 22:34:31 -0700211 // The rate at which we check for apps using excessive power -- 15 mins.
212 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
213
214 // The minimum sample duration we will allow before deciding we have
215 // enough data on wake locks to start killing things.
216 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
217
218 // The minimum sample duration we will allow before deciding we have
219 // enough data on CPU usage to start killing things.
220 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 // How long we allow a receiver to run before giving up on it.
223 static final int BROADCAST_TIMEOUT = 10*1000;
224
225 // How long we wait for a service to finish executing.
226 static final int SERVICE_TIMEOUT = 20*1000;
227
228 // How long a service needs to be running until restarting its process
229 // is no longer considered to be a relaunch of the service.
230 static final int SERVICE_RESTART_DURATION = 5*1000;
231
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700232 // How long a service needs to be running until it will start back at
233 // SERVICE_RESTART_DURATION after being killed.
234 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
235
236 // Multiplying factor to increase restart duration time by, for each time
237 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
238 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
239
240 // The minimum amount of time between restarting services that we allow.
241 // That is, when multiple services are restarting, we won't allow each
242 // to restart less than this amount of time from the last one.
243 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 // Maximum amount of time for there to be no activity on a service before
246 // we consider it non-essential and allow its process to go on the
247 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700248 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249
250 // How long we wait until we timeout on key dispatching.
251 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
252
253 // The minimum time we allow between crashes, for us to consider this
254 // application to be bad and stop and its services and reject broadcasts.
255 static final int MIN_CRASH_INTERVAL = 60*1000;
256
257 // How long we wait until we timeout on key dispatching during instrumentation.
258 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
259
260 // OOM adjustments for processes in various states:
261
262 // This is a process without anything currently running in it. Definitely
263 // the first to go! Value set in system/rootdir/init.rc on startup.
264 // This value is initalized in the constructor, careful when refering to
265 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
268 // This is a process only hosting activities that are not visible,
269 // so it can be killed without any disruption. Value set in
270 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 static int HIDDEN_APP_MIN_ADJ;
273
The Android Open Source Project4df24232009-03-05 14:34:35 -0800274 // This is a process holding the home application -- we want to try
275 // avoiding killing it, even if it would normally be in the background,
276 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800277 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800278
Christopher Tate6fa95972009-06-05 18:43:55 -0700279 // This is a process currently hosting a backup operation. Killing it
280 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 // This is a process holding a secondary server -- killing it will not
284 // have much of an impact as far as the user is concerned. Value set in
285 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700288 // This is a process with a heavy-weight application. It is in the
289 // background, but we want to try to avoid killing it. Value set in
290 // system/rootdir/init.rc on startup.
291 static final int HEAVY_WEIGHT_APP_ADJ;
292
293 // This is a process only hosting components that are perceptible to the
294 // user, and we really want to avoid killing them, but they are not
295 // immediately visible. An example is background music playback. Value set in
296 // system/rootdir/init.rc on startup.
297 static final int PERCEPTIBLE_APP_ADJ;
298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 // This is a process only hosting activities that are visible to the
300 // user, so we'd prefer they don't disappear. Value set in
301 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800302 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303
304 // This is the process running the current foreground app. We'd really
305 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307
308 // This is a process running a core server, such as telephony. Definitely
309 // don't want to kill it, but doing so is not completely fatal.
310 static final int CORE_SERVER_ADJ = -12;
311
312 // The system process runs at the default adjustment.
313 static final int SYSTEM_ADJ = -16;
314
315 // Memory pages are 4K.
316 static final int PAGE_SIZE = 4*1024;
317
318 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800319 static final int EMPTY_APP_MEM;
320 static final int HIDDEN_APP_MEM;
321 static final int HOME_APP_MEM;
322 static final int BACKUP_APP_MEM;
323 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700324 static final int HEAVY_WEIGHT_APP_MEM;
325 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800326 static final int VISIBLE_APP_MEM;
327 static final int FOREGROUND_APP_MEM;
328
329 // The minimum number of hidden apps we want to be able to keep around,
330 // without empty apps being able to push them out of memory.
331 static final int MIN_HIDDEN_APPS = 2;
332
Dianne Hackborn8633e682010-04-22 16:03:41 -0700333 // The maximum number of hidden processes we will keep around before
334 // killing them; this is just a control to not let us go too crazy with
335 // keeping around processes on devices with large amounts of RAM.
336 static final int MAX_HIDDEN_APPS = 15;
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700339 // been idle for less than 15 seconds.
340 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341
342 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700343 // been idle for less than 120 seconds.
344 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800345
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700346 static int getIntProp(String name, boolean allowZero) {
347 String str = SystemProperties.get(name);
348 if (str == null) {
349 throw new IllegalArgumentException("Property not defined: " + name);
350 }
351 int val = Integer.valueOf(str);
352 if (val == 0 && !allowZero) {
353 throw new IllegalArgumentException("Property must not be zero: " + name);
354 }
355 return val;
356 }
357
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800358 static {
359 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700360 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
361 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
362 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
363 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
364 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
365 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
366 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
367 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
368 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
369 // These days we use the last empty slot for hidden apps as well.
370 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
371 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
372 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
373 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
374 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
375 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
376 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
377 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
378 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
379 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381
Dan Egnor42471dd2010-01-07 17:25:22 -0800382 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383
384 static final String[] EMPTY_STRING_ARRAY = new String[0];
385
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700386 public ActivityStack mMainStack;
387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700389 * Description of a request to start a new activity, which has been held
390 * due to app switches being disabled.
391 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700392 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700393 ActivityRecord r;
394 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700395 Uri[] grantedUriPermissions;
396 int grantedMode;
397 boolean onlyIfNeeded;
398 }
399
400 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
401 = new ArrayList<PendingActivityLaunch>();
402
403 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 * List of all active broadcasts that are to be executed immediately
405 * (without waiting for another broadcast to finish). Currently this only
406 * contains broadcasts to registered receivers, to avoid spinning up
407 * a bunch of processes to execute IntentReceiver components.
408 */
409 final ArrayList<BroadcastRecord> mParallelBroadcasts
410 = new ArrayList<BroadcastRecord>();
411
412 /**
413 * List of all active broadcasts that are to be executed one at a time.
414 * The object at the top of the list is the currently activity broadcasts;
415 * those after it are waiting for the top to finish..
416 */
417 final ArrayList<BroadcastRecord> mOrderedBroadcasts
418 = new ArrayList<BroadcastRecord>();
419
420 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800421 * Historical data of past broadcasts, for debugging.
422 */
423 static final int MAX_BROADCAST_HISTORY = 100;
424 final BroadcastRecord[] mBroadcastHistory
425 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
426
427 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 * Set when we current have a BROADCAST_INTENT_MSG in flight.
429 */
430 boolean mBroadcastsScheduled = false;
431
432 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * Activity we have told the window manager to have key focus.
434 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700435 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * List of intents that were used to start the most recent tasks.
438 */
439 final ArrayList<TaskRecord> mRecentTasks
440 = new ArrayList<TaskRecord>();
441
442 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 * All of the applications we currently have running organized by name.
444 * The keys are strings of the application package name (as
445 * returned by the package manager), and the keys are ApplicationRecord
446 * objects.
447 */
448 final ProcessMap<ProcessRecord> mProcessNames
449 = new ProcessMap<ProcessRecord>();
450
451 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700452 * The currently running heavy-weight process, if any.
453 */
454 ProcessRecord mHeavyWeightProcess = null;
455
456 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 * The last time that various processes have crashed.
458 */
459 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
460
461 /**
462 * Set of applications that we consider to be bad, and will reject
463 * incoming broadcasts from (which the user has no control over).
464 * Processes are added to this set when they have crashed twice within
465 * a minimum amount of time; they are removed from it when they are
466 * later restarted (hopefully due to some user action). The value is the
467 * time it was added to the list.
468 */
469 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
470
471 /**
472 * All of the processes we currently have running organized by pid.
473 * The keys are the pid running the application.
474 *
475 * <p>NOTE: This object is protected by its own lock, NOT the global
476 * activity manager lock!
477 */
478 final SparseArray<ProcessRecord> mPidsSelfLocked
479 = new SparseArray<ProcessRecord>();
480
481 /**
482 * All of the processes that have been forced to be foreground. The key
483 * is the pid of the caller who requested it (we hold a death
484 * link on it).
485 */
486 abstract class ForegroundToken implements IBinder.DeathRecipient {
487 int pid;
488 IBinder token;
489 }
490 final SparseArray<ForegroundToken> mForegroundProcesses
491 = new SparseArray<ForegroundToken>();
492
493 /**
494 * List of records for processes that someone had tried to start before the
495 * system was ready. We don't start them at that point, but ensure they
496 * are started by the time booting is complete.
497 */
498 final ArrayList<ProcessRecord> mProcessesOnHold
499 = new ArrayList<ProcessRecord>();
500
501 /**
502 * List of records for processes that we have started and are waiting
503 * for them to call back. This is really only needed when running in
504 * single processes mode, in which case we do not have a unique pid for
505 * each process.
506 */
507 final ArrayList<ProcessRecord> mStartingProcesses
508 = new ArrayList<ProcessRecord>();
509
510 /**
511 * List of persistent applications that are in the process
512 * of being started.
513 */
514 final ArrayList<ProcessRecord> mPersistentStartingProcesses
515 = new ArrayList<ProcessRecord>();
516
517 /**
518 * Processes that are being forcibly torn down.
519 */
520 final ArrayList<ProcessRecord> mRemovedProcesses
521 = new ArrayList<ProcessRecord>();
522
523 /**
524 * List of running applications, sorted by recent usage.
525 * The first entry in the list is the least recently used.
526 * It contains ApplicationRecord objects. This list does NOT include
527 * any persistent application records (since we never want to exit them).
528 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800529 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 = new ArrayList<ProcessRecord>();
531
532 /**
533 * List of processes that should gc as soon as things are idle.
534 */
535 final ArrayList<ProcessRecord> mProcessesToGc
536 = new ArrayList<ProcessRecord>();
537
538 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800539 * This is the process holding what we currently consider to be
540 * the "home" activity.
541 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700542 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543
544 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 * Set of PendingResultRecord objects that are currently active.
546 */
547 final HashSet mPendingResultRecords = new HashSet();
548
549 /**
550 * Set of IntentSenderRecord objects that are currently active.
551 */
552 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
553 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
554
555 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700556 * Fingerprints (String.hashCode()) of stack traces that we've
557 * already logged DropBox entries for. Guarded by itself. If
558 * something (rogue user app) forces this over
559 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
560 */
561 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
562 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
563
564 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700565 * Strict Mode background batched logging state.
566 *
567 * The string buffer is guarded by itself, and its lock is also
568 * used to determine if another batched write is already
569 * in-flight.
570 */
571 private final StringBuilder mStrictModeBuffer = new StringBuilder();
572
573 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700574 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
575 */
576 private boolean mPendingBroadcastTimeoutMessage;
577
578 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 * Intent broadcast that we have tried to start, but are
580 * waiting for its application's process to be created. We only
581 * need one (instead of a list) because we always process broadcasts
582 * one at a time, so no others can be started while waiting for this
583 * one.
584 */
585 BroadcastRecord mPendingBroadcast = null;
586
587 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700588 * The receiver index that is pending, to restart the broadcast if needed.
589 */
590 int mPendingBroadcastRecvIndex;
591
592 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 * Keeps track of all IIntentReceivers that have been registered for
594 * broadcasts. Hash keys are the receiver IBinder, hash value is
595 * a ReceiverList.
596 */
597 final HashMap mRegisteredReceivers = new HashMap();
598
599 /**
600 * Resolver for broadcast intents to registered receivers.
601 * Holds BroadcastFilter (subclass of IntentFilter).
602 */
603 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
604 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
605 @Override
606 protected boolean allowFilterResult(
607 BroadcastFilter filter, List<BroadcastFilter> dest) {
608 IBinder target = filter.receiverList.receiver.asBinder();
609 for (int i=dest.size()-1; i>=0; i--) {
610 if (dest.get(i).receiverList.receiver.asBinder() == target) {
611 return false;
612 }
613 }
614 return true;
615 }
616 };
617
618 /**
619 * State of all active sticky broadcasts. Keys are the action of the
620 * sticky Intent, values are an ArrayList of all broadcasted intents with
621 * that action (which should usually be one).
622 */
623 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
624 new HashMap<String, ArrayList<Intent>>();
625
626 /**
627 * All currently running services.
628 */
629 final HashMap<ComponentName, ServiceRecord> mServices =
630 new HashMap<ComponentName, ServiceRecord>();
631
632 /**
633 * All currently running services indexed by the Intent used to start them.
634 */
635 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
636 new HashMap<Intent.FilterComparison, ServiceRecord>();
637
638 /**
639 * All currently bound service connections. Keys are the IBinder of
640 * the client's IServiceConnection.
641 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700642 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
643 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644
645 /**
646 * List of services that we have been asked to start,
647 * but haven't yet been able to. It is used to hold start requests
648 * while waiting for their corresponding application thread to get
649 * going.
650 */
651 final ArrayList<ServiceRecord> mPendingServices
652 = new ArrayList<ServiceRecord>();
653
654 /**
655 * List of services that are scheduled to restart following a crash.
656 */
657 final ArrayList<ServiceRecord> mRestartingServices
658 = new ArrayList<ServiceRecord>();
659
660 /**
661 * List of services that are in the process of being stopped.
662 */
663 final ArrayList<ServiceRecord> mStoppingServices
664 = new ArrayList<ServiceRecord>();
665
666 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700667 * Backup/restore process management
668 */
669 String mBackupAppName = null;
670 BackupRecord mBackupTarget = null;
671
672 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 * List of PendingThumbnailsRecord objects of clients who are still
674 * waiting to receive all of the thumbnails for a task.
675 */
676 final ArrayList mPendingThumbnails = new ArrayList();
677
678 /**
679 * List of HistoryRecord objects that have been finished and must
680 * still report back to a pending thumbnail receiver.
681 */
682 final ArrayList mCancelledThumbnails = new ArrayList();
683
684 /**
685 * All of the currently running global content providers. Keys are a
686 * string containing the provider name and values are a
687 * ContentProviderRecord object containing the data about it. Note
688 * that a single provider may be published under multiple names, so
689 * there may be multiple entries here for a single one in mProvidersByClass.
690 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700691 final HashMap<String, ContentProviderRecord> mProvidersByName
692 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693
694 /**
695 * All of the currently running global content providers. Keys are a
696 * string containing the provider's implementation class and values are a
697 * ContentProviderRecord object containing the data about it.
698 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700699 final HashMap<String, ContentProviderRecord> mProvidersByClass
700 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701
702 /**
703 * List of content providers who have clients waiting for them. The
704 * application is currently being launched and the provider will be
705 * removed from this list once it is published.
706 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700707 final ArrayList<ContentProviderRecord> mLaunchingProviders
708 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
710 /**
711 * Global set of specific Uri permissions that have been granted.
712 */
713 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
714 = new SparseArray<HashMap<Uri, UriPermission>>();
715
716 /**
717 * Thread-local storage used to carry caller permissions over through
718 * indirect content-provider access.
719 * @see #ActivityManagerService.openContentUri()
720 */
721 private class Identity {
722 public int pid;
723 public int uid;
724
725 Identity(int _pid, int _uid) {
726 pid = _pid;
727 uid = _uid;
728 }
729 }
730 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
731
732 /**
733 * All information we have collected about the runtime performance of
734 * any user id that can impact battery performance.
735 */
736 final BatteryStatsService mBatteryStatsService;
737
738 /**
739 * information about component usage
740 */
741 final UsageStatsService mUsageStatsService;
742
743 /**
744 * Current configuration information. HistoryRecord objects are given
745 * a reference to this object to indicate which configuration they are
746 * currently running in, so this object must be kept immutable.
747 */
748 Configuration mConfiguration = new Configuration();
749
750 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800751 * Current sequencing integer of the configuration, for skipping old
752 * configurations.
753 */
754 int mConfigurationSeq = 0;
755
756 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700757 * Hardware-reported OpenGLES version.
758 */
759 final int GL_ES_VERSION;
760
761 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 * List of initialization arguments to pass to all processes when binding applications to them.
763 * For example, references to the commonly used services.
764 */
765 HashMap<String, IBinder> mAppBindArgs;
766
767 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700768 * Temporary to avoid allocations. Protected by main lock.
769 */
770 final StringBuilder mStringBuilder = new StringBuilder(256);
771
772 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 * Used to control how we initialize the service.
774 */
775 boolean mStartRunning = false;
776 ComponentName mTopComponent;
777 String mTopAction;
778 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700779 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 boolean mSystemReady = false;
781 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700782 boolean mWaitingUpdate = false;
783 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700784 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700785 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786
787 Context mContext;
788
789 int mFactoryTest;
790
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700791 boolean mCheckedForSetup;
792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700794 * The time at which we will allow normal application switches again,
795 * after a call to {@link #stopAppSwitches()}.
796 */
797 long mAppSwitchesAllowedTime;
798
799 /**
800 * This is set to true after the first switch after mAppSwitchesAllowedTime
801 * is set; any switches after that will clear the time.
802 */
803 boolean mDidAppSwitch;
804
805 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700806 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700807 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700808 long mLastPowerCheckRealtime;
809
810 /**
811 * Last time (in uptime) at which we checked for power usage.
812 */
813 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700814
815 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 * Set while we are wanting to sleep, to prevent any
817 * activities from being started/resumed.
818 */
819 boolean mSleeping = false;
820
821 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700822 * Set if we are shutting down the system, similar to sleeping.
823 */
824 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825
826 /**
827 * Task identifier that activities are currently being started
828 * in. Incremented each time a new task is created.
829 * todo: Replace this with a TokenSpace class that generates non-repeating
830 * integers that won't wrap.
831 */
832 int mCurTask = 1;
833
834 /**
835 * Current sequence id for oom_adj computation traversal.
836 */
837 int mAdjSeq = 0;
838
839 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700840 * Current sequence id for process LRU updating.
841 */
842 int mLruSeq = 0;
843
844 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
846 * is set, indicating the user wants processes started in such a way
847 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
848 * running in each process (thus no pre-initialized process, etc).
849 */
850 boolean mSimpleProcessManagement = false;
851
852 /**
853 * System monitoring: number of processes that died since the last
854 * N procs were started.
855 */
856 int[] mProcDeaths = new int[20];
857
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700858 /**
859 * This is set if we had to do a delayed dexopt of an app before launching
860 * it, to increasing the ANR timeouts in that case.
861 */
862 boolean mDidDexOpt;
863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 String mDebugApp = null;
865 boolean mWaitForDebugger = false;
866 boolean mDebugTransient = false;
867 String mOrigDebugApp = null;
868 boolean mOrigWaitForDebugger = false;
869 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700870 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700872 final RemoteCallbackList<IActivityWatcher> mWatchers
873 = new RemoteCallbackList<IActivityWatcher>();
874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 /**
876 * Callback of last caller to {@link #requestPss}.
877 */
878 Runnable mRequestPssCallback;
879
880 /**
881 * Remaining processes for which we are waiting results from the last
882 * call to {@link #requestPss}.
883 */
884 final ArrayList<ProcessRecord> mRequestPssList
885 = new ArrayList<ProcessRecord>();
886
887 /**
888 * Runtime statistics collection thread. This object's lock is used to
889 * protect all related state.
890 */
891 final Thread mProcessStatsThread;
892
893 /**
894 * Used to collect process stats when showing not responding dialog.
895 * Protected by mProcessStatsThread.
896 */
897 final ProcessStats mProcessStats = new ProcessStats(
898 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700899 final AtomicLong mLastCpuTime = new AtomicLong(0);
900 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 long mLastWriteTime = 0;
903
904 /**
905 * Set to true after the system has finished booting.
906 */
907 boolean mBooted = false;
908
909 int mProcessLimit = 0;
910
911 WindowManagerService mWindowManager;
912
913 static ActivityManagerService mSelf;
914 static ActivityThread mSystemThread;
915
916 private final class AppDeathRecipient implements IBinder.DeathRecipient {
917 final ProcessRecord mApp;
918 final int mPid;
919 final IApplicationThread mAppThread;
920
921 AppDeathRecipient(ProcessRecord app, int pid,
922 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800923 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 TAG, "New death recipient " + this
925 + " for thread " + thread.asBinder());
926 mApp = app;
927 mPid = pid;
928 mAppThread = thread;
929 }
930
931 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800932 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 TAG, "Death received in " + this
934 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 synchronized(ActivityManagerService.this) {
936 appDiedLocked(mApp, mPid, mAppThread);
937 }
938 }
939 }
940
941 static final int SHOW_ERROR_MSG = 1;
942 static final int SHOW_NOT_RESPONDING_MSG = 2;
943 static final int SHOW_FACTORY_ERROR_MSG = 3;
944 static final int UPDATE_CONFIGURATION_MSG = 4;
945 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
946 static final int WAIT_FOR_DEBUGGER_MSG = 6;
947 static final int BROADCAST_INTENT_MSG = 7;
948 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 static final int SERVICE_TIMEOUT_MSG = 12;
950 static final int UPDATE_TIME_ZONE = 13;
951 static final int SHOW_UID_ERROR_MSG = 14;
952 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700954 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700955 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800956 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700957 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
958 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700959 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700960 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961
962 AlertDialog mUidAlert;
963
964 final Handler mHandler = new Handler() {
965 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800966 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 //}
968
969 public void handleMessage(Message msg) {
970 switch (msg.what) {
971 case SHOW_ERROR_MSG: {
972 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 synchronized (ActivityManagerService.this) {
974 ProcessRecord proc = (ProcessRecord)data.get("app");
975 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800976 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 return;
978 }
979 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700980 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800981 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 d.show();
983 proc.crashDialog = d;
984 } else {
985 // The device is asleep, so just pretend that the user
986 // saw a crash dialog and hit "force quit".
987 res.set(0);
988 }
989 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700990
991 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 } break;
993 case SHOW_NOT_RESPONDING_MSG: {
994 synchronized (ActivityManagerService.this) {
995 HashMap data = (HashMap) msg.obj;
996 ProcessRecord proc = (ProcessRecord)data.get("app");
997 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800998 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 return;
1000 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001001
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001002 Intent intent = new Intent("android.intent.action.ANR");
1003 if (!mProcessesReady) {
1004 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1005 }
1006 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001007 null, null, 0, null, null, null,
1008 false, false, MY_PID, Process.SYSTEM_UID);
1009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001011 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 d.show();
1013 proc.anrDialog = d;
1014 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001015
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001016 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001018 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1019 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1020 synchronized (ActivityManagerService.this) {
1021 ProcessRecord proc = (ProcessRecord) data.get("app");
1022 if (proc == null) {
1023 Slog.e(TAG, "App not found when showing strict mode dialog.");
1024 break;
1025 }
1026 if (proc.crashDialog != null) {
1027 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1028 return;
1029 }
1030 AppErrorResult res = (AppErrorResult) data.get("result");
1031 if (!mSleeping && !mShuttingDown) {
1032 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1033 d.show();
1034 proc.crashDialog = d;
1035 } else {
1036 // The device is asleep, so just pretend that the user
1037 // saw a crash dialog and hit "force quit".
1038 res.set(0);
1039 }
1040 }
1041 ensureBootCompleted();
1042 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 case SHOW_FACTORY_ERROR_MSG: {
1044 Dialog d = new FactoryErrorDialog(
1045 mContext, msg.getData().getCharSequence("msg"));
1046 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001047 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 } break;
1049 case UPDATE_CONFIGURATION_MSG: {
1050 final ContentResolver resolver = mContext.getContentResolver();
1051 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1052 } break;
1053 case GC_BACKGROUND_PROCESSES_MSG: {
1054 synchronized (ActivityManagerService.this) {
1055 performAppGcsIfAppropriateLocked();
1056 }
1057 } break;
1058 case WAIT_FOR_DEBUGGER_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 ProcessRecord app = (ProcessRecord)msg.obj;
1061 if (msg.arg1 != 0) {
1062 if (!app.waitedForDebugger) {
1063 Dialog d = new AppWaitingForDebuggerDialog(
1064 ActivityManagerService.this,
1065 mContext, app);
1066 app.waitDialog = d;
1067 app.waitedForDebugger = true;
1068 d.show();
1069 }
1070 } else {
1071 if (app.waitDialog != null) {
1072 app.waitDialog.dismiss();
1073 app.waitDialog = null;
1074 }
1075 }
1076 }
1077 } break;
1078 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001079 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 TAG, "Received BROADCAST_INTENT_MSG");
1081 processNextBroadcast(true);
1082 } break;
1083 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001084 synchronized (ActivityManagerService.this) {
1085 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001089 if (mDidDexOpt) {
1090 mDidDexOpt = false;
1091 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1092 nmsg.obj = msg.obj;
1093 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1094 return;
1095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 serviceTimeout((ProcessRecord)msg.obj);
1097 } break;
1098 case UPDATE_TIME_ZONE: {
1099 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001100 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1101 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 if (r.thread != null) {
1103 try {
1104 r.thread.updateTimeZone();
1105 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001106 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 }
1108 }
1109 }
1110 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001111 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 case SHOW_UID_ERROR_MSG: {
1113 // XXX This is a temporary dialog, no need to localize.
1114 AlertDialog d = new BaseErrorDialog(mContext);
1115 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1116 d.setCancelable(false);
1117 d.setTitle("System UIDs Inconsistent");
1118 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1119 d.setButton("I'm Feeling Lucky",
1120 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1121 mUidAlert = d;
1122 d.show();
1123 } break;
1124 case IM_FEELING_LUCKY_MSG: {
1125 if (mUidAlert != null) {
1126 mUidAlert.dismiss();
1127 mUidAlert = null;
1128 }
1129 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001131 if (mDidDexOpt) {
1132 mDidDexOpt = false;
1133 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1134 nmsg.obj = msg.obj;
1135 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1136 return;
1137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 ProcessRecord app = (ProcessRecord)msg.obj;
1139 synchronized (ActivityManagerService.this) {
1140 processStartTimedOutLocked(app);
1141 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001142 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001143 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1144 synchronized (ActivityManagerService.this) {
1145 doPendingActivityLaunchesLocked(true);
1146 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001147 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001148 case KILL_APPLICATION_MSG: {
1149 synchronized (ActivityManagerService.this) {
1150 int uid = msg.arg1;
1151 boolean restart = (msg.arg2 == 1);
1152 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001153 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001154 }
1155 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001156 case FINALIZE_PENDING_INTENT_MSG: {
1157 ((PendingIntentRecord)msg.obj).completeFinalize();
1158 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001159 case POST_HEAVY_NOTIFICATION_MSG: {
1160 INotificationManager inm = NotificationManager.getService();
1161 if (inm == null) {
1162 return;
1163 }
1164
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001165 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001166 ProcessRecord process = root.app;
1167 if (process == null) {
1168 return;
1169 }
1170
1171 try {
1172 Context context = mContext.createPackageContext(process.info.packageName, 0);
1173 String text = mContext.getString(R.string.heavy_weight_notification,
1174 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1175 Notification notification = new Notification();
1176 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1177 notification.when = 0;
1178 notification.flags = Notification.FLAG_ONGOING_EVENT;
1179 notification.tickerText = text;
1180 notification.defaults = 0; // please be quiet
1181 notification.sound = null;
1182 notification.vibrate = null;
1183 notification.setLatestEventInfo(context, text,
1184 mContext.getText(R.string.heavy_weight_notification_detail),
1185 PendingIntent.getActivity(mContext, 0, root.intent,
1186 PendingIntent.FLAG_CANCEL_CURRENT));
1187
1188 try {
1189 int[] outId = new int[1];
1190 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1191 notification, outId);
1192 } catch (RuntimeException e) {
1193 Slog.w(ActivityManagerService.TAG,
1194 "Error showing notification for heavy-weight app", e);
1195 } catch (RemoteException e) {
1196 }
1197 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001198 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001199 }
1200 } break;
1201 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1202 INotificationManager inm = NotificationManager.getService();
1203 if (inm == null) {
1204 return;
1205 }
1206 try {
1207 inm.cancelNotification("android",
1208 R.string.heavy_weight_notification);
1209 } catch (RuntimeException e) {
1210 Slog.w(ActivityManagerService.TAG,
1211 "Error canceling notification for service", e);
1212 } catch (RemoteException e) {
1213 }
1214 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001215 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1216 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001217 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001218 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001219 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1220 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001221 }
1222 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 }
1224 }
1225 };
1226
1227 public static void setSystemProcess() {
1228 try {
1229 ActivityManagerService m = mSelf;
1230
1231 ServiceManager.addService("activity", m);
1232 ServiceManager.addService("meminfo", new MemBinder(m));
1233 if (MONITOR_CPU_USAGE) {
1234 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 ServiceManager.addService("permission", new PermissionController(m));
1237
1238 ApplicationInfo info =
1239 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001240 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001241 mSystemThread.installSystemApplicationInfo(info);
1242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 synchronized (mSelf) {
1244 ProcessRecord app = mSelf.newProcessRecordLocked(
1245 mSystemThread.getApplicationThread(), info,
1246 info.processName);
1247 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001248 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 app.maxAdj = SYSTEM_ADJ;
1250 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1251 synchronized (mSelf.mPidsSelfLocked) {
1252 mSelf.mPidsSelfLocked.put(app.pid, app);
1253 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001254 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 }
1256 } catch (PackageManager.NameNotFoundException e) {
1257 throw new RuntimeException(
1258 "Unable to find android system package", e);
1259 }
1260 }
1261
1262 public void setWindowManager(WindowManagerService wm) {
1263 mWindowManager = wm;
1264 }
1265
1266 public static final Context main(int factoryTest) {
1267 AThread thr = new AThread();
1268 thr.start();
1269
1270 synchronized (thr) {
1271 while (thr.mService == null) {
1272 try {
1273 thr.wait();
1274 } catch (InterruptedException e) {
1275 }
1276 }
1277 }
1278
1279 ActivityManagerService m = thr.mService;
1280 mSelf = m;
1281 ActivityThread at = ActivityThread.systemMain();
1282 mSystemThread = at;
1283 Context context = at.getSystemContext();
1284 m.mContext = context;
1285 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001286 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287
1288 m.mBatteryStatsService.publish(context);
1289 m.mUsageStatsService.publish(context);
1290
1291 synchronized (thr) {
1292 thr.mReady = true;
1293 thr.notifyAll();
1294 }
1295
1296 m.startRunning(null, null, null, null);
1297
1298 return context;
1299 }
1300
1301 public static ActivityManagerService self() {
1302 return mSelf;
1303 }
1304
1305 static class AThread extends Thread {
1306 ActivityManagerService mService;
1307 boolean mReady = false;
1308
1309 public AThread() {
1310 super("ActivityManager");
1311 }
1312
1313 public void run() {
1314 Looper.prepare();
1315
1316 android.os.Process.setThreadPriority(
1317 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001318 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319
1320 ActivityManagerService m = new ActivityManagerService();
1321
1322 synchronized (this) {
1323 mService = m;
1324 notifyAll();
1325 }
1326
1327 synchronized (this) {
1328 while (!mReady) {
1329 try {
1330 wait();
1331 } catch (InterruptedException e) {
1332 }
1333 }
1334 }
1335
1336 Looper.loop();
1337 }
1338 }
1339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 static class MemBinder extends Binder {
1341 ActivityManagerService mActivityManagerService;
1342 MemBinder(ActivityManagerService activityManagerService) {
1343 mActivityManagerService = activityManagerService;
1344 }
1345
1346 @Override
1347 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1348 ActivityManagerService service = mActivityManagerService;
1349 ArrayList<ProcessRecord> procs;
1350 synchronized (mActivityManagerService) {
1351 if (args != null && args.length > 0
1352 && args[0].charAt(0) != '-') {
1353 procs = new ArrayList<ProcessRecord>();
1354 int pid = -1;
1355 try {
1356 pid = Integer.parseInt(args[0]);
1357 } catch (NumberFormatException e) {
1358
1359 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001360 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1361 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 if (proc.pid == pid) {
1363 procs.add(proc);
1364 } else if (proc.processName.equals(args[0])) {
1365 procs.add(proc);
1366 }
1367 }
1368 if (procs.size() <= 0) {
1369 pw.println("No process found for: " + args[0]);
1370 return;
1371 }
1372 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001373 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
1375 }
1376 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1377 }
1378 }
1379
1380 static class CpuBinder extends Binder {
1381 ActivityManagerService mActivityManagerService;
1382 CpuBinder(ActivityManagerService activityManagerService) {
1383 mActivityManagerService = activityManagerService;
1384 }
1385
1386 @Override
1387 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1388 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001389 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1390 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1391 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393 }
1394 }
1395
1396 private ActivityManagerService() {
1397 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1398 if (v != null && Integer.getInteger(v) != 0) {
1399 mSimpleProcessManagement = true;
1400 }
1401 v = System.getenv("ANDROID_DEBUG_APP");
1402 if (v != null) {
1403 mSimpleProcessManagement = true;
1404 }
1405
Joe Onorato8a9b2202010-02-26 18:56:32 -08001406 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 File dataDir = Environment.getDataDirectory();
1409 File systemDir = new File(dataDir, "system");
1410 systemDir.mkdirs();
1411 mBatteryStatsService = new BatteryStatsService(new File(
1412 systemDir, "batterystats.bin").toString());
1413 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001414 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001415 mOnBattery = DEBUG_POWER ? true
1416 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001417 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001419 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001420 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421
Jack Palevichb90d28c2009-07-22 15:35:24 -07001422 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1423 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1424
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001425 mConfiguration.setToDefaults();
1426 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 mProcessStats.init();
1428
1429 // Add ourself to the Watchdog monitors.
1430 Watchdog.getInstance().addMonitor(this);
1431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 mProcessStatsThread = new Thread("ProcessStats") {
1433 public void run() {
1434 while (true) {
1435 try {
1436 try {
1437 synchronized(this) {
1438 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001439 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 // + ", write delay=" + nextWriteDelay);
1443 if (nextWriteDelay < nextCpuDelay) {
1444 nextCpuDelay = nextWriteDelay;
1445 }
1446 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001447 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 this.wait(nextCpuDelay);
1449 }
1450 }
1451 } catch (InterruptedException e) {
1452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 updateCpuStatsNow();
1454 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 }
1457 }
1458 }
1459 };
1460 mProcessStatsThread.start();
1461 }
1462
1463 @Override
1464 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1465 throws RemoteException {
1466 try {
1467 return super.onTransact(code, data, reply, flags);
1468 } catch (RuntimeException e) {
1469 // The activity manager only throws security exceptions, so let's
1470 // log all others.
1471 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001472 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 }
1474 throw e;
1475 }
1476 }
1477
1478 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001479 final long now = SystemClock.uptimeMillis();
1480 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1481 return;
1482 }
1483 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1484 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 mProcessStatsThread.notify();
1486 }
1487 }
1488 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 void updateCpuStatsNow() {
1491 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001492 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 final long now = SystemClock.uptimeMillis();
1494 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001497 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1498 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 haveNewCpuStats = true;
1500 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001501 //Slog.i(TAG, mProcessStats.printCurrentState());
1502 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 // + mProcessStats.getTotalCpuPercent() + "%");
1504
Joe Onorato8a9b2202010-02-26 18:56:32 -08001505 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 if ("true".equals(SystemProperties.get("events.cpu"))) {
1507 int user = mProcessStats.getLastUserTime();
1508 int system = mProcessStats.getLastSystemTime();
1509 int iowait = mProcessStats.getLastIoWaitTime();
1510 int irq = mProcessStats.getLastIrqTime();
1511 int softIrq = mProcessStats.getLastSoftIrqTime();
1512 int idle = mProcessStats.getLastIdleTime();
1513
1514 int total = user + system + iowait + irq + softIrq + idle;
1515 if (total == 0) total = 1;
1516
Doug Zongker2bec3d42009-12-04 12:52:44 -08001517 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 ((user+system+iowait+irq+softIrq) * 100) / total,
1519 (user * 100) / total,
1520 (system * 100) / total,
1521 (iowait * 100) / total,
1522 (irq * 100) / total,
1523 (softIrq * 100) / total);
1524 }
1525 }
1526
Amith Yamasanie43530a2009-08-21 13:11:37 -07001527 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001528 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001529 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 synchronized(mPidsSelfLocked) {
1531 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001532 if (mOnBattery) {
1533 int perc = bstats.startAddingCpuLocked();
1534 int totalUTime = 0;
1535 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001536 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001538 ProcessStats.Stats st = mProcessStats.getStats(i);
1539 if (!st.working) {
1540 continue;
1541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001543 int otherUTime = (st.rel_utime*perc)/100;
1544 int otherSTime = (st.rel_stime*perc)/100;
1545 totalUTime += otherUTime;
1546 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 if (pr != null) {
1548 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001549 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1550 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001551 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001552 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001553 } else {
1554 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001555 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001556 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001557 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1558 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001559 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 }
1562 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001563 bstats.finishAddingCpuLocked(perc, totalUTime,
1564 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 }
1566 }
1567 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1570 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001571 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 }
1573 }
1574 }
1575 }
1576
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001577 @Override
1578 public void batteryNeedsCpuUpdate() {
1579 updateCpuStatsNow();
1580 }
1581
1582 @Override
1583 public void batteryPowerChanged(boolean onBattery) {
1584 // When plugging in, update the CPU stats first before changing
1585 // the plug state.
1586 updateCpuStatsNow();
1587 synchronized (this) {
1588 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001589 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001590 }
1591 }
1592 }
1593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 /**
1595 * Initialize the application bind args. These are passed to each
1596 * process when the bindApplication() IPC is sent to the process. They're
1597 * lazily setup to make sure the services are running when they're asked for.
1598 */
1599 private HashMap<String, IBinder> getCommonServicesLocked() {
1600 if (mAppBindArgs == null) {
1601 mAppBindArgs = new HashMap<String, IBinder>();
1602
1603 // Setup the application init args
1604 mAppBindArgs.put("package", ServiceManager.getService("package"));
1605 mAppBindArgs.put("window", ServiceManager.getService("window"));
1606 mAppBindArgs.put(Context.ALARM_SERVICE,
1607 ServiceManager.getService(Context.ALARM_SERVICE));
1608 }
1609 return mAppBindArgs;
1610 }
1611
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001612 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 if (mFocusedActivity != r) {
1614 mFocusedActivity = r;
1615 mWindowManager.setFocusedApp(r, true);
1616 }
1617 }
1618
Dianne Hackborn906497c2010-05-10 15:57:38 -07001619 private final void updateLruProcessInternalLocked(ProcessRecord app,
1620 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001622 int lrui = mLruProcesses.indexOf(app);
1623 if (lrui >= 0) mLruProcesses.remove(lrui);
1624
1625 int i = mLruProcesses.size()-1;
1626 int skipTop = 0;
1627
Dianne Hackborn906497c2010-05-10 15:57:38 -07001628 app.lruSeq = mLruSeq;
1629
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001630 // compute the new weight for this process.
1631 if (updateActivityTime) {
1632 app.lastActivityTime = SystemClock.uptimeMillis();
1633 }
1634 if (app.activities.size() > 0) {
1635 // If this process has activities, we more strongly want to keep
1636 // it around.
1637 app.lruWeight = app.lastActivityTime;
1638 } else if (app.pubProviders.size() > 0) {
1639 // If this process contains content providers, we want to keep
1640 // it a little more strongly.
1641 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1642 // Also don't let it kick out the first few "real" hidden processes.
1643 skipTop = MIN_HIDDEN_APPS;
1644 } else {
1645 // If this process doesn't have activities, we less strongly
1646 // want to keep it around, and generally want to avoid getting
1647 // in front of any very recently used activities.
1648 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1649 // Also don't let it kick out the first few "real" hidden processes.
1650 skipTop = MIN_HIDDEN_APPS;
1651 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001652
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001653 while (i >= 0) {
1654 ProcessRecord p = mLruProcesses.get(i);
1655 // If this app shouldn't be in front of the first N background
1656 // apps, then skip over that many that are currently hidden.
1657 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1658 skipTop--;
1659 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001660 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001661 mLruProcesses.add(i+1, app);
1662 break;
1663 }
1664 i--;
1665 }
1666 if (i < 0) {
1667 mLruProcesses.add(0, app);
1668 }
1669
Dianne Hackborn906497c2010-05-10 15:57:38 -07001670 // If the app is currently using a content provider or service,
1671 // bump those processes as well.
1672 if (app.connections.size() > 0) {
1673 for (ConnectionRecord cr : app.connections) {
1674 if (cr.binding != null && cr.binding.service != null
1675 && cr.binding.service.app != null
1676 && cr.binding.service.app.lruSeq != mLruSeq) {
1677 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1678 updateActivityTime, i+1);
1679 }
1680 }
1681 }
1682 if (app.conProviders.size() > 0) {
1683 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1684 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1685 updateLruProcessInternalLocked(cpr.app, oomAdj,
1686 updateActivityTime, i+1);
1687 }
1688 }
1689 }
1690
Joe Onorato8a9b2202010-02-26 18:56:32 -08001691 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 if (oomAdj) {
1693 updateOomAdjLocked();
1694 }
1695 }
1696
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001697 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001698 boolean oomAdj, boolean updateActivityTime) {
1699 mLruSeq++;
1700 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1701 }
1702
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001703 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 String processName, int uid) {
1705 if (uid == Process.SYSTEM_UID) {
1706 // The system gets to run in any process. If there are multiple
1707 // processes with the same uid, just pick the first (this
1708 // should never happen).
1709 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1710 processName);
1711 return procs != null ? procs.valueAt(0) : null;
1712 }
1713 ProcessRecord proc = mProcessNames.get(processName, uid);
1714 return proc;
1715 }
1716
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001717 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001718 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001719 try {
1720 if (pm.performDexOpt(packageName)) {
1721 mDidDexOpt = true;
1722 }
1723 } catch (RemoteException e) {
1724 }
1725 }
1726
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001727 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 int transit = mWindowManager.getPendingAppTransition();
1729 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1730 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1731 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1732 }
1733
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001734 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001736 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1738 // We don't have to do anything more if:
1739 // (1) There is an existing application record; and
1740 // (2) The caller doesn't think it is dead, OR there is no thread
1741 // object attached to it so we know it couldn't have crashed; and
1742 // (3) There is a pid assigned to it, so it is either starting or
1743 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001744 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 + " app=" + app + " knownToBeDead=" + knownToBeDead
1746 + " thread=" + (app != null ? app.thread : null)
1747 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001748 if (app != null && app.pid > 0) {
1749 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001750 // We already have the app running, or are waiting for it to
1751 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001752 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001753 return app;
1754 } else {
1755 // An application record is attached to a previous process,
1756 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001757 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001758 handleAppDiedLocked(app, true);
1759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 String hostingNameStr = hostingName != null
1763 ? hostingName.flattenToShortString() : null;
1764
1765 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1766 // If we are in the background, then check to see if this process
1767 // is bad. If so, we will just silently fail.
1768 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001769 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1770 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 return null;
1772 }
1773 } else {
1774 // When the user is explicitly starting a process, then clear its
1775 // crash count so that we won't make it bad until they see at
1776 // least one crash dialog again, and make the process good again
1777 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001778 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1779 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 mProcessCrashTimes.remove(info.processName, info.uid);
1781 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001782 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 info.processName);
1784 mBadProcesses.remove(info.processName, info.uid);
1785 if (app != null) {
1786 app.bad = false;
1787 }
1788 }
1789 }
1790
1791 if (app == null) {
1792 app = newProcessRecordLocked(null, info, processName);
1793 mProcessNames.put(processName, info.uid, app);
1794 } else {
1795 // If this is a new package in the process, add the package to the list
1796 app.addPackage(info.packageName);
1797 }
1798
1799 // If the system is not ready yet, then hold off on starting this
1800 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001802 && !isAllowedWhileBooting(info)
1803 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 if (!mProcessesOnHold.contains(app)) {
1805 mProcessesOnHold.add(app);
1806 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001807 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 return app;
1809 }
1810
1811 startProcessLocked(app, hostingType, hostingNameStr);
1812 return (app.pid != 0) ? app : null;
1813 }
1814
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001815 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1816 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1817 }
1818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 private final void startProcessLocked(ProcessRecord app,
1820 String hostingType, String hostingNameStr) {
1821 if (app.pid > 0 && app.pid != MY_PID) {
1822 synchronized (mPidsSelfLocked) {
1823 mPidsSelfLocked.remove(app.pid);
1824 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1825 }
1826 app.pid = 0;
1827 }
1828
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001829 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1830 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 mProcessesOnHold.remove(app);
1832
1833 updateCpuStats();
1834
1835 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1836 mProcDeaths[0] = 0;
1837
1838 try {
1839 int uid = app.info.uid;
1840 int[] gids = null;
1841 try {
1842 gids = mContext.getPackageManager().getPackageGids(
1843 app.info.packageName);
1844 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001845 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 }
1847 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1848 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1849 && mTopComponent != null
1850 && app.processName.equals(mTopComponent.getPackageName())) {
1851 uid = 0;
1852 }
1853 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1854 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1855 uid = 0;
1856 }
1857 }
1858 int debugFlags = 0;
1859 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1860 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1861 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001862 // Run the app in safe mode if its manifest requests so or the
1863 // system is booted in safe mode.
1864 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1865 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001866 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1869 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1870 }
1871 if ("1".equals(SystemProperties.get("debug.assert"))) {
1872 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1873 }
1874 int pid = Process.start("android.app.ActivityThread",
1875 mSimpleProcessManagement ? app.processName : null, uid, uid,
1876 gids, debugFlags, null);
1877 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1878 synchronized (bs) {
1879 if (bs.isOnBattery()) {
1880 app.batteryStats.incStartsLocked();
1881 }
1882 }
1883
Doug Zongker2bec3d42009-12-04 12:52:44 -08001884 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 app.processName, hostingType,
1886 hostingNameStr != null ? hostingNameStr : "");
1887
1888 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001889 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 }
1891
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001892 StringBuilder buf = mStringBuilder;
1893 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 buf.append("Start proc ");
1895 buf.append(app.processName);
1896 buf.append(" for ");
1897 buf.append(hostingType);
1898 if (hostingNameStr != null) {
1899 buf.append(" ");
1900 buf.append(hostingNameStr);
1901 }
1902 buf.append(": pid=");
1903 buf.append(pid);
1904 buf.append(" uid=");
1905 buf.append(uid);
1906 buf.append(" gids={");
1907 if (gids != null) {
1908 for (int gi=0; gi<gids.length; gi++) {
1909 if (gi != 0) buf.append(", ");
1910 buf.append(gids[gi]);
1911
1912 }
1913 }
1914 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001915 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 if (pid == 0 || pid == MY_PID) {
1917 // Processes are being emulated with threads.
1918 app.pid = MY_PID;
1919 app.removed = false;
1920 mStartingProcesses.add(app);
1921 } else if (pid > 0) {
1922 app.pid = pid;
1923 app.removed = false;
1924 synchronized (mPidsSelfLocked) {
1925 this.mPidsSelfLocked.put(pid, app);
1926 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1927 msg.obj = app;
1928 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1929 }
1930 } else {
1931 app.pid = 0;
1932 RuntimeException e = new RuntimeException(
1933 "Failure starting process " + app.processName
1934 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001935 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 }
1937 } catch (RuntimeException e) {
1938 // XXX do better error recovery.
1939 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001940 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 }
1942 }
1943
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001944 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 if (resumed) {
1946 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1947 } else {
1948 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1949 }
1950 }
1951
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001952 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001953 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1954 && mTopAction == null) {
1955 // We are running in factory test mode, but unable to find
1956 // the factory test app, so just sit around displaying the
1957 // error message and don't try to start anything.
1958 return false;
1959 }
1960 Intent intent = new Intent(
1961 mTopAction,
1962 mTopData != null ? Uri.parse(mTopData) : null);
1963 intent.setComponent(mTopComponent);
1964 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1965 intent.addCategory(Intent.CATEGORY_HOME);
1966 }
1967 ActivityInfo aInfo =
1968 intent.resolveActivityInfo(mContext.getPackageManager(),
1969 STOCK_PM_FLAGS);
1970 if (aInfo != null) {
1971 intent.setComponent(new ComponentName(
1972 aInfo.applicationInfo.packageName, aInfo.name));
1973 // Don't do this if the home app is currently being
1974 // instrumented.
1975 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1976 aInfo.applicationInfo.uid);
1977 if (app == null || app.instrumentationClass == null) {
1978 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001979 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001980 null, null, 0, 0, 0, false, false);
1981 }
1982 }
1983
1984
1985 return true;
1986 }
1987
1988 /**
1989 * Starts the "new version setup screen" if appropriate.
1990 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001991 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001992 // Only do this once per boot.
1993 if (mCheckedForSetup) {
1994 return;
1995 }
1996
1997 // We will show this screen if the current one is a different
1998 // version than the last one shown, and we are not running in
1999 // low-level factory test mode.
2000 final ContentResolver resolver = mContext.getContentResolver();
2001 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2002 Settings.Secure.getInt(resolver,
2003 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2004 mCheckedForSetup = true;
2005
2006 // See if we should be showing the platform update setup UI.
2007 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2008 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2009 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2010
2011 // We don't allow third party apps to replace this.
2012 ResolveInfo ri = null;
2013 for (int i=0; ris != null && i<ris.size(); i++) {
2014 if ((ris.get(i).activityInfo.applicationInfo.flags
2015 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2016 ri = ris.get(i);
2017 break;
2018 }
2019 }
2020
2021 if (ri != null) {
2022 String vers = ri.activityInfo.metaData != null
2023 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2024 : null;
2025 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2026 vers = ri.activityInfo.applicationInfo.metaData.getString(
2027 Intent.METADATA_SETUP_VERSION);
2028 }
2029 String lastVers = Settings.Secure.getString(
2030 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2031 if (vers != null && !vers.equals(lastVers)) {
2032 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2033 intent.setComponent(new ComponentName(
2034 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002035 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002036 null, null, 0, 0, 0, false, false);
2037 }
2038 }
2039 }
2040 }
2041
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002042 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002043 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002044
2045 final int identHash = System.identityHashCode(r);
2046 updateUsageStats(r, true);
2047
2048 int i = mWatchers.beginBroadcast();
2049 while (i > 0) {
2050 i--;
2051 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2052 if (w != null) {
2053 try {
2054 w.activityResuming(identHash);
2055 } catch (RemoteException e) {
2056 }
2057 }
2058 }
2059 mWatchers.finishBroadcast();
2060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002062 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002063 final int N = mPendingActivityLaunches.size();
2064 if (N <= 0) {
2065 return;
2066 }
2067 for (int i=0; i<N; i++) {
2068 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002069 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002070 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2071 doResume && i == (N-1));
2072 }
2073 mPendingActivityLaunches.clear();
2074 }
2075
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002076 public final int startActivity(IApplicationThread caller,
2077 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2078 int grantedMode, IBinder resultTo,
2079 String resultWho, int requestCode, boolean onlyIfNeeded,
2080 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002081 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002082 grantedUriPermissions, grantedMode, resultTo, resultWho,
2083 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002084 }
2085
2086 public final WaitResult startActivityAndWait(IApplicationThread caller,
2087 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2088 int grantedMode, IBinder resultTo,
2089 String resultWho, int requestCode, boolean onlyIfNeeded,
2090 boolean debug) {
2091 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002092 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002093 grantedUriPermissions, grantedMode, resultTo, resultWho,
2094 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002095 return res;
2096 }
2097
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002098 public final int startActivityWithConfig(IApplicationThread caller,
2099 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2100 int grantedMode, IBinder resultTo,
2101 String resultWho, int requestCode, boolean onlyIfNeeded,
2102 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002103 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002104 grantedUriPermissions, grantedMode, resultTo, resultWho,
2105 requestCode, onlyIfNeeded, debug, null, config);
2106 }
2107
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002108 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002109 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002110 IBinder resultTo, String resultWho, int requestCode,
2111 int flagsMask, int flagsValues) {
2112 // Refuse possible leaked file descriptors
2113 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2114 throw new IllegalArgumentException("File descriptors passed in Intent");
2115 }
2116
2117 IIntentSender sender = intent.getTarget();
2118 if (!(sender instanceof PendingIntentRecord)) {
2119 throw new IllegalArgumentException("Bad PendingIntent object");
2120 }
2121
2122 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002123
2124 synchronized (this) {
2125 // If this is coming from the currently resumed activity, it is
2126 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002127 if (mMainStack.mResumedActivity != null
2128 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002129 Binder.getCallingUid()) {
2130 mAppSwitchesAllowedTime = 0;
2131 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002132 }
2133
2134 return pir.sendInner(0, fillInIntent, resolvedType,
2135 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2136 }
2137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 public boolean startNextMatchingActivity(IBinder callingActivity,
2139 Intent intent) {
2140 // Refuse possible leaked file descriptors
2141 if (intent != null && intent.hasFileDescriptors() == true) {
2142 throw new IllegalArgumentException("File descriptors passed in Intent");
2143 }
2144
2145 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002146 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 if (index < 0) {
2148 return false;
2149 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002150 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 if (r.app == null || r.app.thread == null) {
2152 // The caller is not running... d'oh!
2153 return false;
2154 }
2155 intent = new Intent(intent);
2156 // The caller is not allowed to change the data.
2157 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2158 // And we are resetting to find the next component...
2159 intent.setComponent(null);
2160
2161 ActivityInfo aInfo = null;
2162 try {
2163 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002164 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002166 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167
2168 // Look for the original activity in the list...
2169 final int N = resolves != null ? resolves.size() : 0;
2170 for (int i=0; i<N; i++) {
2171 ResolveInfo rInfo = resolves.get(i);
2172 if (rInfo.activityInfo.packageName.equals(r.packageName)
2173 && rInfo.activityInfo.name.equals(r.info.name)) {
2174 // We found the current one... the next matching is
2175 // after it.
2176 i++;
2177 if (i<N) {
2178 aInfo = resolves.get(i).activityInfo;
2179 }
2180 break;
2181 }
2182 }
2183 } catch (RemoteException e) {
2184 }
2185
2186 if (aInfo == null) {
2187 // Nobody who is next!
2188 return false;
2189 }
2190
2191 intent.setComponent(new ComponentName(
2192 aInfo.applicationInfo.packageName, aInfo.name));
2193 intent.setFlags(intent.getFlags()&~(
2194 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2195 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2196 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2197 Intent.FLAG_ACTIVITY_NEW_TASK));
2198
2199 // Okay now we need to start the new activity, replacing the
2200 // currently running activity. This is a little tricky because
2201 // we want to start the new one as if the current one is finished,
2202 // but not finish the current one first so that there is no flicker.
2203 // And thus...
2204 final boolean wasFinishing = r.finishing;
2205 r.finishing = true;
2206
2207 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002208 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 final String resultWho = r.resultWho;
2210 final int requestCode = r.requestCode;
2211 r.resultTo = null;
2212 if (resultTo != null) {
2213 resultTo.removeResultsLocked(r, resultWho, requestCode);
2214 }
2215
2216 final long origId = Binder.clearCallingIdentity();
2217 // XXX we are not dealing with propagating grantedUriPermissions...
2218 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002219 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002221 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 Binder.restoreCallingIdentity(origId);
2223
2224 r.finishing = wasFinishing;
2225 if (res != START_SUCCESS) {
2226 return false;
2227 }
2228 return true;
2229 }
2230 }
2231
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002232 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 Intent intent, String resolvedType, IBinder resultTo,
2234 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002235
2236 // This is so super not safe, that only the system (or okay root)
2237 // can do it.
2238 final int callingUid = Binder.getCallingUid();
2239 if (callingUid != 0 && callingUid != Process.myUid()) {
2240 throw new SecurityException(
2241 "startActivityInPackage only available to the system");
2242 }
2243
The Android Open Source Project4df24232009-03-05 14:34:35 -08002244 final boolean componentSpecified = intent.getComponent() != null;
2245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 // Don't modify the client's object!
2247 intent = new Intent(intent);
2248
2249 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 ActivityInfo aInfo;
2251 try {
2252 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002253 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002255 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 aInfo = rInfo != null ? rInfo.activityInfo : null;
2257 } catch (RemoteException e) {
2258 aInfo = null;
2259 }
2260
2261 if (aInfo != null) {
2262 // Store the found target back into the intent, because now that
2263 // we have it we never want to do this again. For example, if the
2264 // user navigates back to this point in the history, we should
2265 // always restart the exact same activity.
2266 intent.setComponent(new ComponentName(
2267 aInfo.applicationInfo.packageName, aInfo.name));
2268 }
2269
2270 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002271 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002273 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 }
2275 }
2276
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002277 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 // Remove any existing entries that are the same kind of task.
2279 int N = mRecentTasks.size();
2280 for (int i=0; i<N; i++) {
2281 TaskRecord tr = mRecentTasks.get(i);
2282 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2283 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2284 mRecentTasks.remove(i);
2285 i--;
2286 N--;
2287 if (task.intent == null) {
2288 // If the new recent task we are adding is not fully
2289 // specified, then replace it with the existing recent task.
2290 task = tr;
2291 }
2292 }
2293 }
2294 if (N >= MAX_RECENT_TASKS) {
2295 mRecentTasks.remove(N-1);
2296 }
2297 mRecentTasks.add(0, task);
2298 }
2299
2300 public void setRequestedOrientation(IBinder token,
2301 int requestedOrientation) {
2302 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002303 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 if (index < 0) {
2305 return;
2306 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002307 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 final long origId = Binder.clearCallingIdentity();
2309 mWindowManager.setAppOrientation(r, requestedOrientation);
2310 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002311 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 r.mayFreezeScreenLocked(r.app) ? r : null);
2313 if (config != null) {
2314 r.frozenBeforeDestroy = true;
2315 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002316 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 }
2318 }
2319 Binder.restoreCallingIdentity(origId);
2320 }
2321 }
2322
2323 public int getRequestedOrientation(IBinder token) {
2324 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002325 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 if (index < 0) {
2327 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2328 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002329 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330 return mWindowManager.getAppOrientation(r);
2331 }
2332 }
2333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 /**
2335 * This is the internal entry point for handling Activity.finish().
2336 *
2337 * @param token The Binder token referencing the Activity we want to finish.
2338 * @param resultCode Result code, if any, from this Activity.
2339 * @param resultData Result data (Intent), if any, from this Activity.
2340 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002341 * @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 -08002342 */
2343 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2344 // Refuse possible leaked file descriptors
2345 if (resultData != null && resultData.hasFileDescriptors() == true) {
2346 throw new IllegalArgumentException("File descriptors passed in Intent");
2347 }
2348
2349 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002350 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002352 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 if (next != null) {
2354 // ask watcher if this is allowed
2355 boolean resumeOK = true;
2356 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002357 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002359 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
2361
2362 if (!resumeOK) {
2363 return false;
2364 }
2365 }
2366 }
2367 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 resultData, "app-request");
2370 Binder.restoreCallingIdentity(origId);
2371 return res;
2372 }
2373 }
2374
Dianne Hackborn860755f2010-06-03 18:47:52 -07002375 public final void finishHeavyWeightApp() {
2376 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2377 != PackageManager.PERMISSION_GRANTED) {
2378 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2379 + Binder.getCallingPid()
2380 + ", uid=" + Binder.getCallingUid()
2381 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2382 Slog.w(TAG, msg);
2383 throw new SecurityException(msg);
2384 }
2385
2386 synchronized(this) {
2387 if (mHeavyWeightProcess == null) {
2388 return;
2389 }
2390
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002391 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002392 mHeavyWeightProcess.activities);
2393 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002394 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002395 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002396 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002397 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002398 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002399 null, "finish-heavy");
2400 }
2401 }
2402 }
2403
2404 mHeavyWeightProcess = null;
2405 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2406 }
2407 }
2408
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002409 public void crashApplication(int uid, int initialPid, String packageName,
2410 String message) {
2411 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2412 != PackageManager.PERMISSION_GRANTED) {
2413 String msg = "Permission Denial: crashApplication() from pid="
2414 + Binder.getCallingPid()
2415 + ", uid=" + Binder.getCallingUid()
2416 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2417 Slog.w(TAG, msg);
2418 throw new SecurityException(msg);
2419 }
2420
2421 synchronized(this) {
2422 ProcessRecord proc = null;
2423
2424 // Figure out which process to kill. We don't trust that initialPid
2425 // still has any relation to current pids, so must scan through the
2426 // list.
2427 synchronized (mPidsSelfLocked) {
2428 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2429 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2430 if (p.info.uid != uid) {
2431 continue;
2432 }
2433 if (p.pid == initialPid) {
2434 proc = p;
2435 break;
2436 }
2437 for (String str : p.pkgList) {
2438 if (str.equals(packageName)) {
2439 proc = p;
2440 }
2441 }
2442 }
2443 }
2444
2445 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002446 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002447 + " initialPid=" + initialPid
2448 + " packageName=" + packageName);
2449 return;
2450 }
2451
2452 if (proc.thread != null) {
2453 long ident = Binder.clearCallingIdentity();
2454 try {
2455 proc.thread.scheduleCrash(message);
2456 } catch (RemoteException e) {
2457 }
2458 Binder.restoreCallingIdentity(ident);
2459 }
2460 }
2461 }
2462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 public final void finishSubActivity(IBinder token, String resultWho,
2464 int requestCode) {
2465 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002466 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 if (index < 0) {
2468 return;
2469 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002470 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471
2472 final long origId = Binder.clearCallingIdentity();
2473
2474 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002475 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2476 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 if (r.resultTo == self && r.requestCode == requestCode) {
2478 if ((r.resultWho == null && resultWho == null) ||
2479 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002480 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 Activity.RESULT_CANCELED, null, "request-sub");
2482 }
2483 }
2484 }
2485
2486 Binder.restoreCallingIdentity(origId);
2487 }
2488 }
2489
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002490 public boolean willActivityBeVisible(IBinder token) {
2491 synchronized(this) {
2492 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002493 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2494 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002495 if (r == token) {
2496 return true;
2497 }
2498 if (r.fullscreen && !r.finishing) {
2499 return false;
2500 }
2501 }
2502 return true;
2503 }
2504 }
2505
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002506 public void overridePendingTransition(IBinder token, String packageName,
2507 int enterAnim, int exitAnim) {
2508 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002509 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002510 if (index < 0) {
2511 return;
2512 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002514
2515 final long origId = Binder.clearCallingIdentity();
2516
2517 if (self.state == ActivityState.RESUMED
2518 || self.state == ActivityState.PAUSING) {
2519 mWindowManager.overridePendingAppTransition(packageName,
2520 enterAnim, exitAnim);
2521 }
2522
2523 Binder.restoreCallingIdentity(origId);
2524 }
2525 }
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 * Main function for removing an existing process from the activity manager
2529 * as a result of that process going away. Clears out all connections
2530 * to the process.
2531 */
2532 private final void handleAppDiedLocked(ProcessRecord app,
2533 boolean restarting) {
2534 cleanUpApplicationRecordLocked(app, restarting, -1);
2535 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002536 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 }
2538
2539 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2541 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2542 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002544 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2545 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 }
2547
2548 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002549 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550
2551 boolean atTop = true;
2552 boolean hasVisibleActivities = false;
2553
2554 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002555 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002556 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 TAG, "Removing app " + app + " from history with " + i + " entries");
2558 while (i > 0) {
2559 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2563 if (r.app == app) {
2564 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002565 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 TAG, "Removing this entry! frozen=" + r.haveState
2567 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002568 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569
2570 r.inHistory = false;
2571 mWindowManager.removeAppToken(r);
2572 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002573 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002575 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576
2577 } else {
2578 // We have the current state for this activity, so
2579 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002580 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 TAG, "Keeping entry, setting app to null");
2582 if (r.visible) {
2583 hasVisibleActivities = true;
2584 }
2585 r.app = null;
2586 r.nowVisible = false;
2587 if (!r.haveState) {
2588 r.icicle = null;
2589 }
2590 }
2591
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002592 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 r.state = ActivityState.STOPPED;
2594 }
2595 atTop = false;
2596 }
2597
2598 app.activities.clear();
2599
2600 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002601 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 + " running instrumentation " + app.instrumentationClass);
2603 Bundle info = new Bundle();
2604 info.putString("shortMsg", "Process crashed.");
2605 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2606 }
2607
2608 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002609 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 // If there was nothing to resume, and we are not already
2611 // restarting this process, but there is a visible activity that
2612 // is hosted by the process... then make sure all visible
2613 // activities are running, taking care of restarting this
2614 // process.
2615 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002616 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 }
2618 }
2619 }
2620 }
2621
2622 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2623 IBinder threadBinder = thread.asBinder();
2624
2625 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002626 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2627 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2629 return i;
2630 }
2631 }
2632 return -1;
2633 }
2634
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002635 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 IApplicationThread thread) {
2637 if (thread == null) {
2638 return null;
2639 }
2640
2641 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002642 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 }
2644
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002645 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 IApplicationThread thread) {
2647
2648 mProcDeaths[0]++;
2649
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002650 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2651 synchronized (stats) {
2652 stats.noteProcessDiedLocked(app.info.uid, pid);
2653 }
2654
Magnus Edlund7bb25812010-02-24 15:45:06 +01002655 // Clean up already done if the process has been re-started.
2656 if (app.pid == pid && app.thread != null &&
2657 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002658 if (!app.killedBackground) {
2659 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2660 + ") has died.");
2661 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002662 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002663 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 TAG, "Dying app: " + app + ", pid: " + pid
2665 + ", thread: " + thread.asBinder());
2666 boolean doLowMem = app.instrumentationClass == null;
2667 handleAppDiedLocked(app, false);
2668
2669 if (doLowMem) {
2670 // If there are no longer any background processes running,
2671 // and the app that died was not running instrumentation,
2672 // then tell everyone we are now low on memory.
2673 boolean haveBg = false;
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.setAdj >= HIDDEN_APP_MIN_ADJ) {
2677 haveBg = true;
2678 break;
2679 }
2680 }
2681
2682 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002683 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002684 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002685 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002686 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2687 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002688 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002689 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2690 // The low memory report is overriding any current
2691 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002692 // heavy/important/visible/foreground processes first.
2693 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002694 rec.lastRequestedGc = 0;
2695 } else {
2696 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002698 rec.reportLowMemory = true;
2699 rec.lastLowMemory = now;
2700 mProcessesToGc.remove(rec);
2701 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
2703 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002704 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 }
2706 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002707 } else if (app.pid != pid) {
2708 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002709 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002710 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002711 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002712 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002713 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 + thread.asBinder());
2715 }
2716 }
2717
Dan Egnor42471dd2010-01-07 17:25:22 -08002718 /**
2719 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002720 * @param clearTraces causes the dump file to be erased prior to the new
2721 * traces being written, if true; when false, the new traces will be
2722 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002723 * @param firstPids of dalvik VM processes to dump stack traces for first
2724 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002725 * @return file containing stack traces, or null if no dump file is configured
2726 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002727 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2728 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002729 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2730 if (tracesPath == null || tracesPath.length() == 0) {
2731 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002733
2734 File tracesFile = new File(tracesPath);
2735 try {
2736 File tracesDir = tracesFile.getParentFile();
2737 if (!tracesDir.exists()) tracesFile.mkdirs();
2738 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2739
Christopher Tate6ee412d2010-05-28 12:01:56 -07002740 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002741 tracesFile.createNewFile();
2742 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2743 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002744 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002745 return null;
2746 }
2747
2748 // Use a FileObserver to detect when traces finish writing.
2749 // The order of traces is considered important to maintain for legibility.
2750 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2751 public synchronized void onEvent(int event, String path) { notify(); }
2752 };
2753
2754 try {
2755 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002756
2757 // First collect all of the stacks of the most important pids.
2758 try {
2759 int num = firstPids.size();
2760 for (int i = 0; i < num; i++) {
2761 synchronized (observer) {
2762 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2763 observer.wait(200); // Wait for write-close, give up after 200msec
2764 }
2765 }
2766 } catch (InterruptedException e) {
2767 Log.wtf(TAG, e);
2768 }
2769
2770 // Next measure CPU usage.
2771 if (processStats != null) {
2772 processStats.init();
2773 System.gc();
2774 processStats.update();
2775 try {
2776 synchronized (processStats) {
2777 processStats.wait(500); // measure over 1/2 second.
2778 }
2779 } catch (InterruptedException e) {
2780 }
2781 processStats.update();
2782
2783 // We'll take the stack crawls of just the top apps using CPU.
2784 final int N = processStats.countWorkingStats();
2785 int numProcs = 0;
2786 for (int i=0; i<N && numProcs<5; i++) {
2787 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2788 if (lastPids.indexOfKey(stats.pid) >= 0) {
2789 numProcs++;
2790 try {
2791 synchronized (observer) {
2792 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2793 observer.wait(200); // Wait for write-close, give up after 200msec
2794 }
2795 } catch (InterruptedException e) {
2796 Log.wtf(TAG, e);
2797 }
2798
2799 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002800 }
2801 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002802
2803 return tracesFile;
2804
Dan Egnor42471dd2010-01-07 17:25:22 -08002805 } finally {
2806 observer.stopWatching();
2807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 }
2809
Jeff Brown4d94a762010-09-23 11:33:28 -07002810 private final class AppNotResponding implements Runnable {
2811 private final ProcessRecord mApp;
2812 private final String mAnnotation;
2813
2814 public AppNotResponding(ProcessRecord app, String annotation) {
2815 mApp = app;
2816 mAnnotation = annotation;
2817 }
2818
2819 @Override
2820 public void run() {
2821 appNotResponding(mApp, null, null, mAnnotation);
2822 }
2823 }
2824
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002825 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2826 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002827 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2828 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2829
Dianne Hackborn287952c2010-09-22 22:34:31 -07002830 if (mController != null) {
2831 try {
2832 // 0 == continue, -1 = kill process immediately
2833 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2834 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2835 } catch (RemoteException e) {
2836 mController = null;
2837 }
2838 }
2839
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002840 long anrTime = SystemClock.uptimeMillis();
2841 if (MONITOR_CPU_USAGE) {
2842 updateCpuStatsNow();
2843 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002844
2845 synchronized (this) {
2846 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2847 if (mShuttingDown) {
2848 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2849 return;
2850 } else if (app.notResponding) {
2851 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2852 return;
2853 } else if (app.crashing) {
2854 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2855 return;
2856 }
2857
2858 // In case we come through here for the same app before completing
2859 // this one, mark as anring now so we will bail out.
2860 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002861
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002862 // Log the ANR to the event log.
2863 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2864 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002865
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002866 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002867 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002868
2869 int parentPid = app.pid;
2870 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002871 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002872
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002873 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002874
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002875 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2876 ProcessRecord r = mLruProcesses.get(i);
2877 if (r != null && r.thread != null) {
2878 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002879 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2880 if (r.persistent) {
2881 firstPids.add(pid);
2882 } else {
2883 lastPids.put(pid, Boolean.TRUE);
2884 }
2885 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 }
2888 }
2889
Dan Egnor42471dd2010-01-07 17:25:22 -08002890 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002891 StringBuilder info = mStringBuilder;
2892 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002893 info.append("ANR in ").append(app.processName);
2894 if (activity != null && activity.shortComponentName != null) {
2895 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002896 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002897 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002899 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002901 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002902 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904
Dianne Hackborn287952c2010-09-22 22:34:31 -07002905 final ProcessStats processStats = new ProcessStats(true);
2906
2907 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2908
Dan Egnor42471dd2010-01-07 17:25:22 -08002909 String cpuInfo = null;
2910 if (MONITOR_CPU_USAGE) {
2911 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002912 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002913 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002914 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002915 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002916 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 }
2918
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002919 info.append(processStats.printCurrentState(anrTime));
2920
Joe Onorato8a9b2202010-02-26 18:56:32 -08002921 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002922 if (tracesFile == null) {
2923 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2924 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2925 }
2926
2927 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2928
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002929 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002931 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2932 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002934 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2935 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002938 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 }
2940 }
2941
Dan Egnor42471dd2010-01-07 17:25:22 -08002942 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2943 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2944 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002945
2946 synchronized (this) {
2947 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2948 Process.killProcess(app.pid);
2949 return;
2950 }
2951
2952 // Set the app's notResponding state, and look up the errorReportReceiver
2953 makeAppNotRespondingLocked(app,
2954 activity != null ? activity.shortComponentName : null,
2955 annotation != null ? "ANR " + annotation : "ANR",
2956 info.toString());
2957
2958 // Bring up the infamous App Not Responding dialog
2959 Message msg = Message.obtain();
2960 HashMap map = new HashMap();
2961 msg.what = SHOW_NOT_RESPONDING_MSG;
2962 msg.obj = map;
2963 map.put("app", app);
2964 if (activity != null) {
2965 map.put("activity", activity);
2966 }
2967
2968 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 }
2971
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002972 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2973 if (!mLaunchWarningShown) {
2974 mLaunchWarningShown = true;
2975 mHandler.post(new Runnable() {
2976 @Override
2977 public void run() {
2978 synchronized (ActivityManagerService.this) {
2979 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2980 d.show();
2981 mHandler.postDelayed(new Runnable() {
2982 @Override
2983 public void run() {
2984 synchronized (ActivityManagerService.this) {
2985 d.dismiss();
2986 mLaunchWarningShown = false;
2987 }
2988 }
2989 }, 4000);
2990 }
2991 }
2992 });
2993 }
2994 }
2995
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002996 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 app.persistentActivities--;
2998 if (app.persistentActivities > 0) {
2999 // Still more of 'em...
3000 return;
3001 }
3002 if (app.persistent) {
3003 // Ah, but the application itself is persistent. Whatever!
3004 return;
3005 }
3006
3007 // App is no longer persistent... make sure it and the ones
3008 // following it in the LRU list have the correc oom_adj.
3009 updateOomAdjLocked();
3010 }
3011
3012 public void setPersistent(IBinder token, boolean isPersistent) {
3013 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
3014 != PackageManager.PERMISSION_GRANTED) {
3015 String msg = "Permission Denial: setPersistent() from pid="
3016 + Binder.getCallingPid()
3017 + ", uid=" + Binder.getCallingUid()
3018 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003019 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003020 throw new SecurityException(msg);
3021 }
3022
3023 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003024 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 if (index < 0) {
3026 return;
3027 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003028 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 ProcessRecord app = r.app;
3030
Joe Onorato8a9b2202010-02-26 18:56:32 -08003031 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 TAG, "Setting persistence " + isPersistent + ": " + r);
3033
3034 if (isPersistent) {
3035 if (r.persistent) {
3036 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003037 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 return;
3039 }
3040 r.persistent = true;
3041 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003042 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 if (app.persistentActivities > 1) {
3044 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003045 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 return;
3047 }
3048 if (app.persistent) {
3049 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003050 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 return;
3052 }
3053
3054 // App is now persistent... make sure it and the ones
3055 // following it now have the correct oom_adj.
3056 final long origId = Binder.clearCallingIdentity();
3057 updateOomAdjLocked();
3058 Binder.restoreCallingIdentity(origId);
3059
3060 } else {
3061 if (!r.persistent) {
3062 // Okay okay, I heard you already!
3063 return;
3064 }
3065 r.persistent = false;
3066 final long origId = Binder.clearCallingIdentity();
3067 decPersistentCountLocked(app);
3068 Binder.restoreCallingIdentity(origId);
3069
3070 }
3071 }
3072 }
3073
3074 public boolean clearApplicationUserData(final String packageName,
3075 final IPackageDataObserver observer) {
3076 int uid = Binder.getCallingUid();
3077 int pid = Binder.getCallingPid();
3078 long callingId = Binder.clearCallingIdentity();
3079 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003080 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 int pkgUid = -1;
3082 synchronized(this) {
3083 try {
3084 pkgUid = pm.getPackageUid(packageName);
3085 } catch (RemoteException e) {
3086 }
3087 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003088 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 return false;
3090 }
3091 if (uid == pkgUid || checkComponentPermission(
3092 android.Manifest.permission.CLEAR_APP_USER_DATA,
3093 pid, uid, -1)
3094 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003095 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 } else {
3097 throw new SecurityException(pid+" does not have permission:"+
3098 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3099 "for process:"+packageName);
3100 }
3101 }
3102
3103 try {
3104 //clear application user data
3105 pm.clearApplicationUserData(packageName, observer);
3106 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3107 Uri.fromParts("package", packageName, null));
3108 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003109 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3110 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 } catch (RemoteException e) {
3112 }
3113 } finally {
3114 Binder.restoreCallingIdentity(callingId);
3115 }
3116 return true;
3117 }
3118
Dianne Hackborn03abb812010-01-04 18:43:19 -08003119 public void killBackgroundProcesses(final String packageName) {
3120 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3121 != PackageManager.PERMISSION_GRANTED &&
3122 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3123 != PackageManager.PERMISSION_GRANTED) {
3124 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 + Binder.getCallingPid()
3126 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003127 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003128 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 throw new SecurityException(msg);
3130 }
3131
3132 long callingId = Binder.clearCallingIdentity();
3133 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003134 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 int pkgUid = -1;
3136 synchronized(this) {
3137 try {
3138 pkgUid = pm.getPackageUid(packageName);
3139 } catch (RemoteException e) {
3140 }
3141 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003142 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 return;
3144 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003145 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003146 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003147 }
3148 } finally {
3149 Binder.restoreCallingIdentity(callingId);
3150 }
3151 }
3152
3153 public void forceStopPackage(final String packageName) {
3154 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3155 != PackageManager.PERMISSION_GRANTED) {
3156 String msg = "Permission Denial: forceStopPackage() from pid="
3157 + Binder.getCallingPid()
3158 + ", uid=" + Binder.getCallingUid()
3159 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003160 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003161 throw new SecurityException(msg);
3162 }
3163
3164 long callingId = Binder.clearCallingIdentity();
3165 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003166 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003167 int pkgUid = -1;
3168 synchronized(this) {
3169 try {
3170 pkgUid = pm.getPackageUid(packageName);
3171 } catch (RemoteException e) {
3172 }
3173 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003174 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003175 return;
3176 }
3177 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 }
3179 } finally {
3180 Binder.restoreCallingIdentity(callingId);
3181 }
3182 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003183
3184 /*
3185 * The pkg name and uid have to be specified.
3186 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3187 */
3188 public void killApplicationWithUid(String pkg, int uid) {
3189 if (pkg == null) {
3190 return;
3191 }
3192 // Make sure the uid is valid.
3193 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003194 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003195 return;
3196 }
3197 int callerUid = Binder.getCallingUid();
3198 // Only the system server can kill an application
3199 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003200 // Post an aysnc message to kill the application
3201 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3202 msg.arg1 = uid;
3203 msg.arg2 = 0;
3204 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003205 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003206 } else {
3207 throw new SecurityException(callerUid + " cannot kill pkg: " +
3208 pkg);
3209 }
3210 }
3211
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003212 public void closeSystemDialogs(String reason) {
3213 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003214 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003215 if (reason != null) {
3216 intent.putExtra("reason", reason);
3217 }
3218
3219 final int uid = Binder.getCallingUid();
3220 final long origId = Binder.clearCallingIdentity();
3221 synchronized (this) {
3222 int i = mWatchers.beginBroadcast();
3223 while (i > 0) {
3224 i--;
3225 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3226 if (w != null) {
3227 try {
3228 w.closingSystemDialogs(reason);
3229 } catch (RemoteException e) {
3230 }
3231 }
3232 }
3233 mWatchers.finishBroadcast();
3234
Dianne Hackbornffa42482009-09-23 22:20:11 -07003235 mWindowManager.closeSystemDialogs(reason);
3236
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003237 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3238 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003239 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003240 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003241 Activity.RESULT_CANCELED, null, "close-sys");
3242 }
3243 }
3244
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003245 broadcastIntentLocked(null, null, intent, null,
3246 null, 0, null, null, null, false, false, -1, uid);
3247 }
3248 Binder.restoreCallingIdentity(origId);
3249 }
3250
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003251 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003252 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003253 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3254 for (int i=pids.length-1; i>=0; i--) {
3255 infos[i] = new Debug.MemoryInfo();
3256 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003257 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003258 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003259 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003260
3261 public void killApplicationProcess(String processName, int uid) {
3262 if (processName == null) {
3263 return;
3264 }
3265
3266 int callerUid = Binder.getCallingUid();
3267 // Only the system server can kill an application
3268 if (callerUid == Process.SYSTEM_UID) {
3269 synchronized (this) {
3270 ProcessRecord app = getProcessRecordLocked(processName, uid);
3271 if (app != null) {
3272 try {
3273 app.thread.scheduleSuicide();
3274 } catch (RemoteException e) {
3275 // If the other end already died, then our work here is done.
3276 }
3277 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003278 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003279 + processName + " / " + uid);
3280 }
3281 }
3282 } else {
3283 throw new SecurityException(callerUid + " cannot kill app process: " +
3284 processName);
3285 }
3286 }
3287
Dianne Hackborn03abb812010-01-04 18:43:19 -08003288 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003289 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3291 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003292 if (!mProcessesReady) {
3293 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 intent.putExtra(Intent.EXTRA_UID, uid);
3296 broadcastIntentLocked(null, null, intent,
3297 null, null, 0, null, null, null,
3298 false, false, MY_PID, Process.SYSTEM_UID);
3299 }
3300
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003301 private final boolean killPackageProcessesLocked(String packageName, int uid,
3302 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003303 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304
Dianne Hackborn03abb812010-01-04 18:43:19 -08003305 // Remove all processes this package may have touched: all with the
3306 // same UID (except for the system or root user), and all whose name
3307 // matches the package name.
3308 final String procNamePrefix = packageName + ":";
3309 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3310 final int NA = apps.size();
3311 for (int ia=0; ia<NA; ia++) {
3312 ProcessRecord app = apps.valueAt(ia);
3313 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003314 if (doit) {
3315 procs.add(app);
3316 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003317 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3318 || app.processName.equals(packageName)
3319 || app.processName.startsWith(procNamePrefix)) {
3320 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003321 if (!doit) {
3322 return true;
3323 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003324 app.removed = true;
3325 procs.add(app);
3326 }
3327 }
3328 }
3329 }
3330
3331 int N = procs.size();
3332 for (int i=0; i<N; i++) {
3333 removeProcessLocked(procs.get(i), callerWillRestart);
3334 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003335 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003336 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003337
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003338 private final boolean forceStopPackageLocked(String name, int uid,
3339 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 int i, N;
3341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 if (uid < 0) {
3343 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003344 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 } catch (RemoteException e) {
3346 }
3347 }
3348
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003349 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003350 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003351
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003352 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3353 while (badApps.hasNext()) {
3354 SparseArray<Long> ba = badApps.next();
3355 if (ba.get(uid) != null) {
3356 badApps.remove();
3357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 }
3359 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003360
3361 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3362 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003364 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3365 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003367 if (!doit) {
3368 return true;
3369 }
3370 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003371 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 if (r.app != null) {
3373 r.app.removed = true;
3374 }
3375 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003376 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 }
3378 }
3379
3380 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3381 for (ServiceRecord service : mServices.values()) {
3382 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003383 if (!doit) {
3384 return true;
3385 }
3386 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003387 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 if (service.app != null) {
3389 service.app.removed = true;
3390 }
3391 service.app = null;
3392 services.add(service);
3393 }
3394 }
3395
3396 N = services.size();
3397 for (i=0; i<N; i++) {
3398 bringDownServiceLocked(services.get(i), true);
3399 }
3400
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003401 if (doit) {
3402 if (purgeCache) {
3403 AttributeCache ac = AttributeCache.instance();
3404 if (ac != null) {
3405 ac.removePackage(name);
3406 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003407 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003408 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003409 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003410
3411 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 }
3413
3414 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3415 final String name = app.processName;
3416 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003417 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 TAG, "Force removing process " + app + " (" + name
3419 + "/" + uid + ")");
3420
3421 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003422 if (mHeavyWeightProcess == app) {
3423 mHeavyWeightProcess = null;
3424 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 boolean needRestart = false;
3427 if (app.pid > 0 && app.pid != MY_PID) {
3428 int pid = app.pid;
3429 synchronized (mPidsSelfLocked) {
3430 mPidsSelfLocked.remove(pid);
3431 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3432 }
3433 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003434 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 Process.killProcess(pid);
3436
3437 if (app.persistent) {
3438 if (!callerWillRestart) {
3439 addAppLocked(app.info);
3440 } else {
3441 needRestart = true;
3442 }
3443 }
3444 } else {
3445 mRemovedProcesses.add(app);
3446 }
3447
3448 return needRestart;
3449 }
3450
3451 private final void processStartTimedOutLocked(ProcessRecord app) {
3452 final int pid = app.pid;
3453 boolean gone = false;
3454 synchronized (mPidsSelfLocked) {
3455 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3456 if (knownApp != null && knownApp.thread == null) {
3457 mPidsSelfLocked.remove(pid);
3458 gone = true;
3459 }
3460 }
3461
3462 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003464 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003465 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003467 if (mHeavyWeightProcess == app) {
3468 mHeavyWeightProcess = null;
3469 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3470 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003471 // Take care of any launching providers waiting for this process.
3472 checkAppInLaunchingProvidersLocked(app, true);
3473 // Take care of any services that are waiting for the process.
3474 for (int i=0; i<mPendingServices.size(); i++) {
3475 ServiceRecord sr = mPendingServices.get(i);
3476 if (app.info.uid == sr.appInfo.uid
3477 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003478 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003479 mPendingServices.remove(i);
3480 i--;
3481 bringDownServiceLocked(sr, true);
3482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003484 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003485 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003486 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003487 try {
3488 IBackupManager bm = IBackupManager.Stub.asInterface(
3489 ServiceManager.getService(Context.BACKUP_SERVICE));
3490 bm.agentDisconnected(app.info.packageName);
3491 } catch (RemoteException e) {
3492 // Can't happen; the backup manager is local
3493 }
3494 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003495 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003497 mPendingBroadcast.state = BroadcastRecord.IDLE;
3498 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003499 mPendingBroadcast = null;
3500 scheduleBroadcastsLocked();
3501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003503 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 }
3505 }
3506
3507 private final boolean attachApplicationLocked(IApplicationThread thread,
3508 int pid) {
3509
3510 // Find the application record that is being attached... either via
3511 // the pid if we are running in multiple processes, or just pull the
3512 // next app record if we are emulating process with anonymous threads.
3513 ProcessRecord app;
3514 if (pid != MY_PID && pid >= 0) {
3515 synchronized (mPidsSelfLocked) {
3516 app = mPidsSelfLocked.get(pid);
3517 }
3518 } else if (mStartingProcesses.size() > 0) {
3519 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003520 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 } else {
3522 app = null;
3523 }
3524
3525 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003526 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003528 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 if (pid > 0 && pid != MY_PID) {
3530 Process.killProcess(pid);
3531 } else {
3532 try {
3533 thread.scheduleExit();
3534 } catch (Exception e) {
3535 // Ignore exceptions.
3536 }
3537 }
3538 return false;
3539 }
3540
3541 // If this application record is still attached to a previous
3542 // process, clean it up now.
3543 if (app.thread != null) {
3544 handleAppDiedLocked(app, true);
3545 }
3546
3547 // Tell the process all about itself.
3548
Joe Onorato8a9b2202010-02-26 18:56:32 -08003549 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 TAG, "Binding process pid " + pid + " to record " + app);
3551
3552 String processName = app.processName;
3553 try {
3554 thread.asBinder().linkToDeath(new AppDeathRecipient(
3555 app, pid, thread), 0);
3556 } catch (RemoteException e) {
3557 app.resetPackageList();
3558 startProcessLocked(app, "link fail", processName);
3559 return false;
3560 }
3561
Doug Zongker2bec3d42009-12-04 12:52:44 -08003562 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563
3564 app.thread = thread;
3565 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003566 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3567 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 app.forcingToForeground = null;
3569 app.foregroundServices = false;
3570 app.debugging = false;
3571
3572 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3573
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003574 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003575 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003577 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003578 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003579 }
3580
Joe Onorato8a9b2202010-02-26 18:56:32 -08003581 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 TAG, "New app record " + app
3583 + " thread=" + thread.asBinder() + " pid=" + pid);
3584 try {
3585 int testMode = IApplicationThread.DEBUG_OFF;
3586 if (mDebugApp != null && mDebugApp.equals(processName)) {
3587 testMode = mWaitForDebugger
3588 ? IApplicationThread.DEBUG_WAIT
3589 : IApplicationThread.DEBUG_ON;
3590 app.debugging = true;
3591 if (mDebugTransient) {
3592 mDebugApp = mOrigDebugApp;
3593 mWaitForDebugger = mOrigWaitForDebugger;
3594 }
3595 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003596
Christopher Tate181fafa2009-05-14 11:12:14 -07003597 // If the app is being launched for restore or full backup, set it up specially
3598 boolean isRestrictedBackupMode = false;
3599 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3600 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3601 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3602 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003603
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003604 ensurePackageDexOpt(app.instrumentationInfo != null
3605 ? app.instrumentationInfo.packageName
3606 : app.info.packageName);
3607 if (app.instrumentationClass != null) {
3608 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003609 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003610 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003611 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003612 thread.bindApplication(processName, app.instrumentationInfo != null
3613 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 app.instrumentationClass, app.instrumentationProfileFile,
3615 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003616 isRestrictedBackupMode || !normalMode,
3617 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003618 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003619 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 } catch (Exception e) {
3621 // todo: Yikes! What should we do? For now we will try to
3622 // start another process, but that could easily get us in
3623 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003624 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625
3626 app.resetPackageList();
3627 startProcessLocked(app, "bind fail", processName);
3628 return false;
3629 }
3630
3631 // Remove this record from the list of starting applications.
3632 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003633 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3634 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 mProcessesOnHold.remove(app);
3636
3637 boolean badApp = false;
3638 boolean didSomething = false;
3639
3640 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003641 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003642 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3644 && processName.equals(hr.processName)) {
3645 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003646 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 didSomething = true;
3648 }
3649 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003650 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 + hr.intent.getComponent().flattenToShortString(), e);
3652 badApp = true;
3653 }
3654 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003655 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 }
3657 }
3658
3659 // Find any services that should be running in this process...
3660 if (!badApp && mPendingServices.size() > 0) {
3661 ServiceRecord sr = null;
3662 try {
3663 for (int i=0; i<mPendingServices.size(); i++) {
3664 sr = mPendingServices.get(i);
3665 if (app.info.uid != sr.appInfo.uid
3666 || !processName.equals(sr.processName)) {
3667 continue;
3668 }
3669
3670 mPendingServices.remove(i);
3671 i--;
3672 realStartServiceLocked(sr, app);
3673 didSomething = true;
3674 }
3675 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003676 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 + sr.shortName, e);
3678 badApp = true;
3679 }
3680 }
3681
3682 // Check if the next broadcast receiver is in this process...
3683 BroadcastRecord br = mPendingBroadcast;
3684 if (!badApp && br != null && br.curApp == app) {
3685 try {
3686 mPendingBroadcast = null;
3687 processCurBroadcastLocked(br, app);
3688 didSomething = true;
3689 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003690 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 + br.curComponent.flattenToShortString(), e);
3692 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003693 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3695 br.resultExtras, br.resultAbort, true);
3696 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003697 // We need to reset the state if we fails to start the receiver.
3698 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 }
3700 }
3701
Christopher Tate181fafa2009-05-14 11:12:14 -07003702 // Check whether the next backup agent is in this process...
3703 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003704 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003705 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003706 try {
3707 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3708 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003709 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003710 e.printStackTrace();
3711 }
3712 }
3713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 if (badApp) {
3715 // todo: Also need to kill application to deal with all
3716 // kinds of exceptions.
3717 handleAppDiedLocked(app, false);
3718 return false;
3719 }
3720
3721 if (!didSomething) {
3722 updateOomAdjLocked();
3723 }
3724
3725 return true;
3726 }
3727
3728 public final void attachApplication(IApplicationThread thread) {
3729 synchronized (this) {
3730 int callingPid = Binder.getCallingPid();
3731 final long origId = Binder.clearCallingIdentity();
3732 attachApplicationLocked(thread, callingPid);
3733 Binder.restoreCallingIdentity(origId);
3734 }
3735 }
3736
Dianne Hackborne88846e2009-09-30 21:34:25 -07003737 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003739 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 Binder.restoreCallingIdentity(origId);
3741 }
3742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003744 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003745 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 mWindowManager.enableScreenAfterBoot();
3747 }
3748
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003749 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003750 IntentFilter pkgFilter = new IntentFilter();
3751 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3752 pkgFilter.addDataScheme("package");
3753 mContext.registerReceiver(new BroadcastReceiver() {
3754 @Override
3755 public void onReceive(Context context, Intent intent) {
3756 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3757 if (pkgs != null) {
3758 for (String pkg : pkgs) {
3759 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3760 setResultCode(Activity.RESULT_OK);
3761 return;
3762 }
3763 }
3764 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003765 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003766 }, pkgFilter);
3767
3768 synchronized (this) {
3769 // Ensure that any processes we had put on hold are now started
3770 // up.
3771 final int NP = mProcessesOnHold.size();
3772 if (NP > 0) {
3773 ArrayList<ProcessRecord> procs =
3774 new ArrayList<ProcessRecord>(mProcessesOnHold);
3775 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003776 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3777 + procs.get(ip));
3778 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003779 }
3780 }
3781
3782 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003783 // Start looking for apps that are abusing wake locks.
3784 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003785 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003786 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003787 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003788 broadcastIntentLocked(null, null,
3789 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3790 null, null, 0, null, null,
3791 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3792 false, false, MY_PID, Process.SYSTEM_UID);
3793 }
3794 }
3795 }
3796
3797 final void ensureBootCompleted() {
3798 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003799 boolean enableScreen;
3800 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003801 booting = mBooting;
3802 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003803 enableScreen = !mBooted;
3804 mBooted = true;
3805 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003806
3807 if (booting) {
3808 finishBooting();
3809 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003810
3811 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003812 enableScreenAfterBoot();
3813 }
3814 }
3815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 public final void activityPaused(IBinder token, Bundle icicle) {
3817 // Refuse possible leaked file descriptors
3818 if (icicle != null && icicle.hasFileDescriptors()) {
3819 throw new IllegalArgumentException("File descriptors passed in Bundle");
3820 }
3821
3822 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 Binder.restoreCallingIdentity(origId);
3825 }
3826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 public final void activityStopped(IBinder token, Bitmap thumbnail,
3828 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003829 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 TAG, "Activity stopped: token=" + token);
3831
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003832 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833
3834 final long origId = Binder.clearCallingIdentity();
3835
3836 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003837 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003839 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 r.thumbnail = thumbnail;
3841 r.description = description;
3842 r.stopped = true;
3843 r.state = ActivityState.STOPPED;
3844 if (!r.finishing) {
3845 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003846 r.stack.destroyActivityLocked(r, true);
3847 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 }
3849 }
3850 }
3851 }
3852
3853 if (r != null) {
3854 sendPendingThumbnail(r, null, null, null, false);
3855 }
3856
3857 trimApplications();
3858
3859 Binder.restoreCallingIdentity(origId);
3860 }
3861
3862 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003863 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003864 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 }
3866
3867 public String getCallingPackage(IBinder token) {
3868 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003869 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003870 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 }
3872 }
3873
3874 public ComponentName getCallingActivity(IBinder token) {
3875 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003876 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 return r != null ? r.intent.getComponent() : null;
3878 }
3879 }
3880
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003881 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003882 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003884 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 if (r != null) {
3886 return r.resultTo;
3887 }
3888 }
3889 return null;
3890 }
3891
3892 public ComponentName getActivityClassForToken(IBinder token) {
3893 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003894 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003896 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 return r.intent.getComponent();
3898 }
3899 return null;
3900 }
3901 }
3902
3903 public String getPackageForToken(IBinder token) {
3904 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003905 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003907 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003908 return r.packageName;
3909 }
3910 return null;
3911 }
3912 }
3913
3914 public IIntentSender getIntentSender(int type,
3915 String packageName, IBinder token, String resultWho,
3916 int requestCode, Intent intent, String resolvedType, int flags) {
3917 // Refuse possible leaked file descriptors
3918 if (intent != null && intent.hasFileDescriptors() == true) {
3919 throw new IllegalArgumentException("File descriptors passed in Intent");
3920 }
3921
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003922 if (type == INTENT_SENDER_BROADCAST) {
3923 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3924 throw new IllegalArgumentException(
3925 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3926 }
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,
3948 token, resultWho, requestCode, intent, resolvedType, flags);
3949
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,
3958 int requestCode, Intent intent, String resolvedType, 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,
3979 requestCode, intent, resolvedType, flags);
3980 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) {
3986 rec.key.requestIntent.replaceExtras(intent);
3987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 return rec;
3989 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003990 rec.canceled = true;
3991 mIntentSenderRecords.remove(key);
3992 }
3993 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 return rec;
3995 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003996 rec = new PendingIntentRecord(this, key, callingUid);
3997 mIntentSenderRecords.put(key, rec.ref);
3998 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3999 if (activity.pendingResults == null) {
4000 activity.pendingResults
4001 = new HashSet<WeakReference<PendingIntentRecord>>();
4002 }
4003 activity.pendingResults.add(rec.ref);
4004 }
4005 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 }
4007
4008 public void cancelIntentSender(IIntentSender sender) {
4009 if (!(sender instanceof PendingIntentRecord)) {
4010 return;
4011 }
4012 synchronized(this) {
4013 PendingIntentRecord rec = (PendingIntentRecord)sender;
4014 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004015 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 .getPackageUid(rec.key.packageName);
4017 if (uid != Binder.getCallingUid()) {
4018 String msg = "Permission Denial: cancelIntentSender() from pid="
4019 + Binder.getCallingPid()
4020 + ", uid=" + Binder.getCallingUid()
4021 + " is not allowed to cancel packges "
4022 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004023 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 throw new SecurityException(msg);
4025 }
4026 } catch (RemoteException e) {
4027 throw new SecurityException(e);
4028 }
4029 cancelIntentSenderLocked(rec, true);
4030 }
4031 }
4032
4033 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4034 rec.canceled = true;
4035 mIntentSenderRecords.remove(rec.key);
4036 if (cleanActivity && rec.key.activity != null) {
4037 rec.key.activity.pendingResults.remove(rec.ref);
4038 }
4039 }
4040
4041 public String getPackageForIntentSender(IIntentSender pendingResult) {
4042 if (!(pendingResult instanceof PendingIntentRecord)) {
4043 return null;
4044 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004045 try {
4046 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4047 return res.key.packageName;
4048 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 }
4050 return null;
4051 }
4052
4053 public void setProcessLimit(int max) {
4054 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4055 "setProcessLimit()");
4056 mProcessLimit = max;
4057 }
4058
4059 public int getProcessLimit() {
4060 return mProcessLimit;
4061 }
4062
4063 void foregroundTokenDied(ForegroundToken token) {
4064 synchronized (ActivityManagerService.this) {
4065 synchronized (mPidsSelfLocked) {
4066 ForegroundToken cur
4067 = mForegroundProcesses.get(token.pid);
4068 if (cur != token) {
4069 return;
4070 }
4071 mForegroundProcesses.remove(token.pid);
4072 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4073 if (pr == null) {
4074 return;
4075 }
4076 pr.forcingToForeground = null;
4077 pr.foregroundServices = false;
4078 }
4079 updateOomAdjLocked();
4080 }
4081 }
4082
4083 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4084 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4085 "setProcessForeground()");
4086 synchronized(this) {
4087 boolean changed = false;
4088
4089 synchronized (mPidsSelfLocked) {
4090 ProcessRecord pr = mPidsSelfLocked.get(pid);
4091 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 return;
4094 }
4095 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4096 if (oldToken != null) {
4097 oldToken.token.unlinkToDeath(oldToken, 0);
4098 mForegroundProcesses.remove(pid);
4099 pr.forcingToForeground = null;
4100 changed = true;
4101 }
4102 if (isForeground && token != null) {
4103 ForegroundToken newToken = new ForegroundToken() {
4104 public void binderDied() {
4105 foregroundTokenDied(this);
4106 }
4107 };
4108 newToken.pid = pid;
4109 newToken.token = token;
4110 try {
4111 token.linkToDeath(newToken, 0);
4112 mForegroundProcesses.put(pid, newToken);
4113 pr.forcingToForeground = token;
4114 changed = true;
4115 } catch (RemoteException e) {
4116 // If the process died while doing this, we will later
4117 // do the cleanup with the process death link.
4118 }
4119 }
4120 }
4121
4122 if (changed) {
4123 updateOomAdjLocked();
4124 }
4125 }
4126 }
4127
4128 // =========================================================
4129 // PERMISSIONS
4130 // =========================================================
4131
4132 static class PermissionController extends IPermissionController.Stub {
4133 ActivityManagerService mActivityManagerService;
4134 PermissionController(ActivityManagerService activityManagerService) {
4135 mActivityManagerService = activityManagerService;
4136 }
4137
4138 public boolean checkPermission(String permission, int pid, int uid) {
4139 return mActivityManagerService.checkPermission(permission, pid,
4140 uid) == PackageManager.PERMISSION_GRANTED;
4141 }
4142 }
4143
4144 /**
4145 * This can be called with or without the global lock held.
4146 */
4147 int checkComponentPermission(String permission, int pid, int uid,
4148 int reqUid) {
4149 // We might be performing an operation on behalf of an indirect binder
4150 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4151 // client identity accordingly before proceeding.
4152 Identity tlsIdentity = sCallerIdentity.get();
4153 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004154 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4156 uid = tlsIdentity.uid;
4157 pid = tlsIdentity.pid;
4158 }
4159
4160 // Root, system server and our own process get to do everything.
4161 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4162 !Process.supportsProcesses()) {
4163 return PackageManager.PERMISSION_GRANTED;
4164 }
4165 // If the target requires a specific UID, always fail for others.
4166 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004167 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 return PackageManager.PERMISSION_DENIED;
4169 }
4170 if (permission == null) {
4171 return PackageManager.PERMISSION_GRANTED;
4172 }
4173 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004174 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 .checkUidPermission(permission, uid);
4176 } catch (RemoteException e) {
4177 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004178 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 }
4180 return PackageManager.PERMISSION_DENIED;
4181 }
4182
4183 /**
4184 * As the only public entry point for permissions checking, this method
4185 * can enforce the semantic that requesting a check on a null global
4186 * permission is automatically denied. (Internally a null permission
4187 * string is used when calling {@link #checkComponentPermission} in cases
4188 * when only uid-based security is needed.)
4189 *
4190 * This can be called with or without the global lock held.
4191 */
4192 public int checkPermission(String permission, int pid, int uid) {
4193 if (permission == null) {
4194 return PackageManager.PERMISSION_DENIED;
4195 }
4196 return checkComponentPermission(permission, pid, uid, -1);
4197 }
4198
4199 /**
4200 * Binder IPC calls go through the public entry point.
4201 * This can be called with or without the global lock held.
4202 */
4203 int checkCallingPermission(String permission) {
4204 return checkPermission(permission,
4205 Binder.getCallingPid(),
4206 Binder.getCallingUid());
4207 }
4208
4209 /**
4210 * This can be called with or without the global lock held.
4211 */
4212 void enforceCallingPermission(String permission, String func) {
4213 if (checkCallingPermission(permission)
4214 == PackageManager.PERMISSION_GRANTED) {
4215 return;
4216 }
4217
4218 String msg = "Permission Denial: " + func + " from pid="
4219 + Binder.getCallingPid()
4220 + ", uid=" + Binder.getCallingUid()
4221 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004222 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 throw new SecurityException(msg);
4224 }
4225
4226 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004227 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4228 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4229 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4230 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4231 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004233 // Is the component private from the target uid?
4234 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4235
4236 // Acceptable if the there is no read permission needed from the
4237 // target or the target is holding the read permission.
4238 if (!readPerm) {
4239 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004241 == PackageManager.PERMISSION_GRANTED)) {
4242 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 }
4244 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004245
4246 // Acceptable if the there is no write permission needed from the
4247 // target or the target is holding the read permission.
4248 if (!writePerm) {
4249 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004251 == PackageManager.PERMISSION_GRANTED)) {
4252 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 }
4254 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004255
4256 // Acceptable if there is a path permission matching the URI that
4257 // the target holds the permission on.
4258 PathPermission[] pps = pi.pathPermissions;
4259 if (pps != null && (!readPerm || !writePerm)) {
4260 final String path = uri.getPath();
4261 int i = pps.length;
4262 while (i > 0 && (!readPerm || !writePerm)) {
4263 i--;
4264 PathPermission pp = pps[i];
4265 if (!readPerm) {
4266 final String pprperm = pp.getReadPermission();
4267 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4268 + pprperm + " for " + pp.getPath()
4269 + ": match=" + pp.match(path)
4270 + " check=" + pm.checkUidPermission(pprperm, uid));
4271 if (pprperm != null && pp.match(path) &&
4272 (pm.checkUidPermission(pprperm, uid)
4273 == PackageManager.PERMISSION_GRANTED)) {
4274 readPerm = true;
4275 }
4276 }
4277 if (!writePerm) {
4278 final String ppwperm = pp.getWritePermission();
4279 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4280 + ppwperm + " for " + pp.getPath()
4281 + ": match=" + pp.match(path)
4282 + " check=" + pm.checkUidPermission(ppwperm, uid));
4283 if (ppwperm != null && pp.match(path) &&
4284 (pm.checkUidPermission(ppwperm, uid)
4285 == PackageManager.PERMISSION_GRANTED)) {
4286 writePerm = true;
4287 }
4288 }
4289 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 } catch (RemoteException e) {
4292 return false;
4293 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004294
4295 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 }
4297
4298 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4299 int modeFlags) {
4300 // Root gets to do everything.
4301 if (uid == 0 || !Process.supportsProcesses()) {
4302 return true;
4303 }
4304 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4305 if (perms == null) return false;
4306 UriPermission perm = perms.get(uri);
4307 if (perm == null) return false;
4308 return (modeFlags&perm.modeFlags) == modeFlags;
4309 }
4310
4311 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4312 // Another redirected-binder-call permissions check as in
4313 // {@link checkComponentPermission}.
4314 Identity tlsIdentity = sCallerIdentity.get();
4315 if (tlsIdentity != null) {
4316 uid = tlsIdentity.uid;
4317 pid = tlsIdentity.pid;
4318 }
4319
4320 // Our own process gets to do everything.
4321 if (pid == MY_PID) {
4322 return PackageManager.PERMISSION_GRANTED;
4323 }
4324 synchronized(this) {
4325 return checkUriPermissionLocked(uri, uid, modeFlags)
4326 ? PackageManager.PERMISSION_GRANTED
4327 : PackageManager.PERMISSION_DENIED;
4328 }
4329 }
4330
Dianne Hackborn39792d22010-08-19 18:01:52 -07004331 /**
4332 * Check if the targetPkg can be granted permission to access uri by
4333 * the callingUid using the given modeFlags. Throws a security exception
4334 * if callingUid is not allowed to do this. Returns the uid of the target
4335 * if the URI permission grant should be performed; returns -1 if it is not
4336 * needed (for example targetPkg already has permission to access the URI).
4337 */
4338 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4339 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4341 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4342 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004343 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
4345
Joe Onorato8a9b2202010-02-26 18:56:32 -08004346 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004347 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004348
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004349 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350
4351 // If this is not a content: uri, we can't do anything with it.
4352 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004353 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004354 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004355 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 }
4357
4358 String name = uri.getAuthority();
4359 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004360 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 if (cpr != null) {
4362 pi = cpr.info;
4363 } else {
4364 try {
4365 pi = pm.resolveContentProvider(name,
4366 PackageManager.GET_URI_PERMISSION_PATTERNS);
4367 } catch (RemoteException ex) {
4368 }
4369 }
4370 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004371 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004372 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 }
4374
4375 int targetUid;
4376 try {
4377 targetUid = pm.getPackageUid(targetPkg);
4378 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004379 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004380 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004381 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 }
4383 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004384 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 }
4386
4387 // First... does the target actually need this permission?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004388 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004389 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004390 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004391 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004392 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 }
4394
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004395 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 if (!pi.grantUriPermissions) {
4397 throw new SecurityException("Provider " + pi.packageName
4398 + "/" + pi.name
4399 + " does not allow granting of Uri permissions (uri "
4400 + uri + ")");
4401 }
4402 if (pi.uriPermissionPatterns != null) {
4403 final int N = pi.uriPermissionPatterns.length;
4404 boolean allowed = false;
4405 for (int i=0; i<N; i++) {
4406 if (pi.uriPermissionPatterns[i] != null
4407 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4408 allowed = true;
4409 break;
4410 }
4411 }
4412 if (!allowed) {
4413 throw new SecurityException("Provider " + pi.packageName
4414 + "/" + pi.name
4415 + " does not allow granting of permission to path of Uri "
4416 + uri);
4417 }
4418 }
4419
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004420 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 // this uri?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004422 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4424 throw new SecurityException("Uid " + callingUid
4425 + " does not have permission to uri " + uri);
4426 }
4427 }
4428
Dianne Hackborn39792d22010-08-19 18:01:52 -07004429 return targetUid;
4430 }
4431
4432 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4433 Uri uri, int modeFlags, UriPermissionOwner owner) {
4434 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4435 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4436 if (modeFlags == 0) {
4437 return;
4438 }
4439
4440 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 // to the uri, and the target doesn't. Let's now give this to
4442 // the target.
4443
Joe Onorato8a9b2202010-02-26 18:56:32 -08004444 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004445 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 HashMap<Uri, UriPermission> targetUris
4448 = mGrantedUriPermissions.get(targetUid);
4449 if (targetUris == null) {
4450 targetUris = new HashMap<Uri, UriPermission>();
4451 mGrantedUriPermissions.put(targetUid, targetUris);
4452 }
4453
4454 UriPermission perm = targetUris.get(uri);
4455 if (perm == null) {
4456 perm = new UriPermission(targetUid, uri);
4457 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004461 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 perm.globalModeFlags |= modeFlags;
4463 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004464 perm.readOwners.add(owner);
4465 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004467 perm.writeOwners.add(owner);
4468 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 }
4470 }
4471
Dianne Hackborn39792d22010-08-19 18:01:52 -07004472 void grantUriPermissionLocked(int callingUid,
4473 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4474 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4475 if (targetUid < 0) {
4476 return;
4477 }
4478
4479 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4480 }
4481
4482 /**
4483 * Like checkGrantUriPermissionLocked, but takes an Intent.
4484 */
4485 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4486 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004487 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004489 + " from " + intent + "; flags=0x"
4490 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004493 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 }
4495 Uri data = intent.getData();
4496 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004497 return -1;
4498 }
4499 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4500 intent.getFlags());
4501 }
4502
4503 /**
4504 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4505 */
4506 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4507 String targetPkg, Intent intent, UriPermissionOwner owner) {
4508 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4509 intent.getFlags(), owner);
4510 }
4511
4512 void grantUriPermissionFromIntentLocked(int callingUid,
4513 String targetPkg, Intent intent, UriPermissionOwner owner) {
4514 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4515 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 return;
4517 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004518
4519 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 }
4521
4522 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4523 Uri uri, int modeFlags) {
4524 synchronized(this) {
4525 final ProcessRecord r = getRecordForAppLocked(caller);
4526 if (r == null) {
4527 throw new SecurityException("Unable to find app for caller "
4528 + caller
4529 + " when granting permission to uri " + uri);
4530 }
4531 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004532 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 }
4534 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004535 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
4537
4538 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4539 null);
4540 }
4541 }
4542
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004543 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4545 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4546 HashMap<Uri, UriPermission> perms
4547 = mGrantedUriPermissions.get(perm.uid);
4548 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004549 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004550 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 perms.remove(perm.uri);
4552 if (perms.size() == 0) {
4553 mGrantedUriPermissions.remove(perm.uid);
4554 }
4555 }
4556 }
4557 }
4558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4560 int modeFlags) {
4561 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4562 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4563 if (modeFlags == 0) {
4564 return;
4565 }
4566
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004568 "Revoking all granted permissions to " + uri);
4569
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004570 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571
4572 final String authority = uri.getAuthority();
4573 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004574 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 if (cpr != null) {
4576 pi = cpr.info;
4577 } else {
4578 try {
4579 pi = pm.resolveContentProvider(authority,
4580 PackageManager.GET_URI_PERMISSION_PATTERNS);
4581 } catch (RemoteException ex) {
4582 }
4583 }
4584 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004585 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 return;
4587 }
4588
4589 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004590 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 // Right now, if you are not the original owner of the permission,
4592 // you are not allowed to revoke it.
4593 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4594 throw new SecurityException("Uid " + callingUid
4595 + " does not have permission to uri " + uri);
4596 //}
4597 }
4598
4599 // Go through all of the permissions and remove any that match.
4600 final List<String> SEGMENTS = uri.getPathSegments();
4601 if (SEGMENTS != null) {
4602 final int NS = SEGMENTS.size();
4603 int N = mGrantedUriPermissions.size();
4604 for (int i=0; i<N; i++) {
4605 HashMap<Uri, UriPermission> perms
4606 = mGrantedUriPermissions.valueAt(i);
4607 Iterator<UriPermission> it = perms.values().iterator();
4608 toploop:
4609 while (it.hasNext()) {
4610 UriPermission perm = it.next();
4611 Uri targetUri = perm.uri;
4612 if (!authority.equals(targetUri.getAuthority())) {
4613 continue;
4614 }
4615 List<String> targetSegments = targetUri.getPathSegments();
4616 if (targetSegments == null) {
4617 continue;
4618 }
4619 if (targetSegments.size() < NS) {
4620 continue;
4621 }
4622 for (int j=0; j<NS; j++) {
4623 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4624 continue toploop;
4625 }
4626 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004628 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 perm.clearModes(modeFlags);
4630 if (perm.modeFlags == 0) {
4631 it.remove();
4632 }
4633 }
4634 if (perms.size() == 0) {
4635 mGrantedUriPermissions.remove(
4636 mGrantedUriPermissions.keyAt(i));
4637 N--;
4638 i--;
4639 }
4640 }
4641 }
4642 }
4643
4644 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4645 int modeFlags) {
4646 synchronized(this) {
4647 final ProcessRecord r = getRecordForAppLocked(caller);
4648 if (r == null) {
4649 throw new SecurityException("Unable to find app for caller "
4650 + caller
4651 + " when revoking permission to uri " + uri);
4652 }
4653 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004654 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 return;
4656 }
4657
4658 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4659 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4660 if (modeFlags == 0) {
4661 return;
4662 }
4663
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004664 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665
4666 final String authority = uri.getAuthority();
4667 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004668 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 if (cpr != null) {
4670 pi = cpr.info;
4671 } else {
4672 try {
4673 pi = pm.resolveContentProvider(authority,
4674 PackageManager.GET_URI_PERMISSION_PATTERNS);
4675 } catch (RemoteException ex) {
4676 }
4677 }
4678 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004679 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 return;
4681 }
4682
4683 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4684 }
4685 }
4686
Dianne Hackborn7e269642010-08-25 19:50:20 -07004687 @Override
4688 public IBinder newUriPermissionOwner(String name) {
4689 synchronized(this) {
4690 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4691 return owner.getExternalTokenLocked();
4692 }
4693 }
4694
4695 @Override
4696 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4697 Uri uri, int modeFlags) {
4698 synchronized(this) {
4699 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4700 if (owner == null) {
4701 throw new IllegalArgumentException("Unknown owner: " + token);
4702 }
4703 if (fromUid != Binder.getCallingUid()) {
4704 if (Binder.getCallingUid() != Process.myUid()) {
4705 // Only system code can grant URI permissions on behalf
4706 // of other users.
4707 throw new SecurityException("nice try");
4708 }
4709 }
4710 if (targetPkg == null) {
4711 throw new IllegalArgumentException("null target");
4712 }
4713 if (uri == null) {
4714 throw new IllegalArgumentException("null uri");
4715 }
4716
4717 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4718 }
4719 }
4720
4721 @Override
4722 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4723 synchronized(this) {
4724 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4725 if (owner == null) {
4726 throw new IllegalArgumentException("Unknown owner: " + token);
4727 }
4728
4729 if (uri == null) {
4730 owner.removeUriPermissionsLocked(mode);
4731 } else {
4732 owner.removeUriPermissionLocked(uri, mode);
4733 }
4734 }
4735 }
4736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4738 synchronized (this) {
4739 ProcessRecord app =
4740 who != null ? getRecordForAppLocked(who) : null;
4741 if (app == null) return;
4742
4743 Message msg = Message.obtain();
4744 msg.what = WAIT_FOR_DEBUGGER_MSG;
4745 msg.obj = app;
4746 msg.arg1 = waiting ? 1 : 0;
4747 mHandler.sendMessage(msg);
4748 }
4749 }
4750
4751 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4752 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004753 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004755 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 }
4757
4758 // =========================================================
4759 // TASK MANAGEMENT
4760 // =========================================================
4761
4762 public List getTasks(int maxNum, int flags,
4763 IThumbnailReceiver receiver) {
4764 ArrayList list = new ArrayList();
4765
4766 PendingThumbnailsRecord pending = null;
4767 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004768 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769
4770 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004771 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004772 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4773 + ", receiver=" + receiver);
4774
4775 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4776 != PackageManager.PERMISSION_GRANTED) {
4777 if (receiver != null) {
4778 // If the caller wants to wait for pending thumbnails,
4779 // it ain't gonna get them.
4780 try {
4781 receiver.finished();
4782 } catch (RemoteException ex) {
4783 }
4784 }
4785 String msg = "Permission Denial: getTasks() from pid="
4786 + Binder.getCallingPid()
4787 + ", uid=" + Binder.getCallingUid()
4788 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004789 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 throw new SecurityException(msg);
4791 }
4792
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004793 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004794 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004795 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004796 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 CharSequence topDescription = null;
4798 TaskRecord curTask = null;
4799 int numActivities = 0;
4800 int numRunning = 0;
4801 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004802 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004804 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004805
4806 // Initialize state for next task if needed.
4807 if (top == null ||
4808 (top.state == ActivityState.INITIALIZING
4809 && top.task == r.task)) {
4810 top = r;
4811 topDescription = r.description;
4812 curTask = r.task;
4813 numActivities = numRunning = 0;
4814 }
4815
4816 // Add 'r' into the current task.
4817 numActivities++;
4818 if (r.app != null && r.app.thread != null) {
4819 numRunning++;
4820 }
4821 if (topDescription == null) {
4822 topDescription = r.description;
4823 }
4824
Joe Onorato8a9b2202010-02-26 18:56:32 -08004825 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 TAG, r.intent.getComponent().flattenToShortString()
4827 + ": task=" + r.task);
4828
4829 // If the next one is a different task, generate a new
4830 // TaskInfo entry for what we have.
4831 if (next == null || next.task != curTask) {
4832 ActivityManager.RunningTaskInfo ci
4833 = new ActivityManager.RunningTaskInfo();
4834 ci.id = curTask.taskId;
4835 ci.baseActivity = r.intent.getComponent();
4836 ci.topActivity = top.intent.getComponent();
4837 ci.thumbnail = top.thumbnail;
4838 ci.description = topDescription;
4839 ci.numActivities = numActivities;
4840 ci.numRunning = numRunning;
4841 //System.out.println(
4842 // "#" + maxNum + ": " + " descr=" + ci.description);
4843 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 TAG, "State=" + top.state + "Idle=" + top.idle
4846 + " app=" + top.app
4847 + " thr=" + (top.app != null ? top.app.thread : null));
4848 if (top.state == ActivityState.RESUMED
4849 || top.state == ActivityState.PAUSING) {
4850 if (top.idle && top.app != null
4851 && top.app.thread != null) {
4852 topRecord = top;
4853 topThumbnail = top.app.thread;
4854 } else {
4855 top.thumbnailNeeded = true;
4856 }
4857 }
4858 if (pending == null) {
4859 pending = new PendingThumbnailsRecord(receiver);
4860 }
4861 pending.pendingRecords.add(top);
4862 }
4863 list.add(ci);
4864 maxNum--;
4865 top = null;
4866 }
4867 }
4868
4869 if (pending != null) {
4870 mPendingThumbnails.add(pending);
4871 }
4872 }
4873
Joe Onorato8a9b2202010-02-26 18:56:32 -08004874 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004875
4876 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004877 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 try {
4879 topThumbnail.requestThumbnail(topRecord);
4880 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004881 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 sendPendingThumbnail(null, topRecord, null, null, true);
4883 }
4884 }
4885
4886 if (pending == null && receiver != null) {
4887 // In this case all thumbnails were available and the client
4888 // is being asked to be told when the remaining ones come in...
4889 // which is unusually, since the top-most currently running
4890 // activity should never have a canned thumbnail! Oh well.
4891 try {
4892 receiver.finished();
4893 } catch (RemoteException ex) {
4894 }
4895 }
4896
4897 return list;
4898 }
4899
4900 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4901 int flags) {
4902 synchronized (this) {
4903 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4904 "getRecentTasks()");
4905
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004906 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 final int N = mRecentTasks.size();
4909 ArrayList<ActivityManager.RecentTaskInfo> res
4910 = new ArrayList<ActivityManager.RecentTaskInfo>(
4911 maxNum < N ? maxNum : N);
4912 for (int i=0; i<N && maxNum > 0; i++) {
4913 TaskRecord tr = mRecentTasks.get(i);
4914 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4915 || (tr.intent == null)
4916 || ((tr.intent.getFlags()
4917 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4918 ActivityManager.RecentTaskInfo rti
4919 = new ActivityManager.RecentTaskInfo();
4920 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4921 rti.baseIntent = new Intent(
4922 tr.intent != null ? tr.intent : tr.affinityIntent);
4923 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004924
4925 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4926 // Check whether this activity is currently available.
4927 try {
4928 if (rti.origActivity != null) {
4929 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4930 continue;
4931 }
4932 } else if (rti.baseIntent != null) {
4933 if (pm.queryIntentActivities(rti.baseIntent,
4934 null, 0) == null) {
4935 continue;
4936 }
4937 }
4938 } catch (RemoteException e) {
4939 // Will never happen.
4940 }
4941 }
4942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 res.add(rti);
4944 maxNum--;
4945 }
4946 }
4947 return res;
4948 }
4949 }
4950
4951 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4952 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004953 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 TaskRecord jt = startTask;
4955
4956 // First look backwards
4957 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004958 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 if (r.task != jt) {
4960 jt = r.task;
4961 if (affinity.equals(jt.affinity)) {
4962 return j;
4963 }
4964 }
4965 }
4966
4967 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004968 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 jt = startTask;
4970 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004971 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 if (r.task != jt) {
4973 if (affinity.equals(jt.affinity)) {
4974 return j;
4975 }
4976 jt = r.task;
4977 }
4978 }
4979
4980 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004981 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 return N-1;
4983 }
4984
4985 return -1;
4986 }
4987
4988 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004989 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 */
4991 public void moveTaskToFront(int task) {
4992 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4993 "moveTaskToFront()");
4994
4995 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004996 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4997 Binder.getCallingUid(), "Task to front")) {
4998 return;
4999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 final long origId = Binder.clearCallingIdentity();
5001 try {
5002 int N = mRecentTasks.size();
5003 for (int i=0; i<N; i++) {
5004 TaskRecord tr = mRecentTasks.get(i);
5005 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005006 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 return;
5008 }
5009 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005010 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5011 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005013 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 return;
5015 }
5016 }
5017 } finally {
5018 Binder.restoreCallingIdentity(origId);
5019 }
5020 }
5021 }
5022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 public void moveTaskToBack(int task) {
5024 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5025 "moveTaskToBack()");
5026
5027 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005028 if (mMainStack.mResumedActivity != null
5029 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005030 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5031 Binder.getCallingUid(), "Task to back")) {
5032 return;
5033 }
5034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005036 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 Binder.restoreCallingIdentity(origId);
5038 }
5039 }
5040
5041 /**
5042 * Moves an activity, and all of the other activities within the same task, to the bottom
5043 * of the history stack. The activity's order within the task is unchanged.
5044 *
5045 * @param token A reference to the activity we wish to move
5046 * @param nonRoot If false then this only works if the activity is the root
5047 * of a task; if true it will work for any activity in a task.
5048 * @return Returns true if the move completed, false if not.
5049 */
5050 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5051 synchronized(this) {
5052 final long origId = Binder.clearCallingIdentity();
5053 int taskId = getTaskForActivityLocked(token, !nonRoot);
5054 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005055 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 }
5057 Binder.restoreCallingIdentity(origId);
5058 }
5059 return false;
5060 }
5061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 public void moveTaskBackwards(int task) {
5063 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5064 "moveTaskBackwards()");
5065
5066 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005067 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5068 Binder.getCallingUid(), "Task backwards")) {
5069 return;
5070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 final long origId = Binder.clearCallingIdentity();
5072 moveTaskBackwardsLocked(task);
5073 Binder.restoreCallingIdentity(origId);
5074 }
5075 }
5076
5077 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005078 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 }
5080
5081 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5082 synchronized(this) {
5083 return getTaskForActivityLocked(token, onlyRoot);
5084 }
5085 }
5086
5087 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005088 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 TaskRecord lastTask = null;
5090 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005091 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 if (r == token) {
5093 if (!onlyRoot || lastTask != r.task) {
5094 return r.task.taskId;
5095 }
5096 return -1;
5097 }
5098 lastTask = r.task;
5099 }
5100
5101 return -1;
5102 }
5103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 public void finishOtherInstances(IBinder token, ComponentName className) {
5105 synchronized(this) {
5106 final long origId = Binder.clearCallingIdentity();
5107
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005108 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 TaskRecord lastTask = null;
5110 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005111 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 if (r.realActivity.equals(className)
5113 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005114 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 null, "others")) {
5116 i--;
5117 N--;
5118 }
5119 }
5120 lastTask = r.task;
5121 }
5122
5123 Binder.restoreCallingIdentity(origId);
5124 }
5125 }
5126
5127 // =========================================================
5128 // THUMBNAILS
5129 // =========================================================
5130
5131 public void reportThumbnail(IBinder token,
5132 Bitmap thumbnail, CharSequence description) {
5133 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5134 final long origId = Binder.clearCallingIdentity();
5135 sendPendingThumbnail(null, token, thumbnail, description, true);
5136 Binder.restoreCallingIdentity(origId);
5137 }
5138
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005139 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 Bitmap thumbnail, CharSequence description, boolean always) {
5141 TaskRecord task = null;
5142 ArrayList receivers = null;
5143
5144 //System.out.println("Send pending thumbnail: " + r);
5145
5146 synchronized(this) {
5147 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005148 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 if (index < 0) {
5150 return;
5151 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005152 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
5154 if (thumbnail == null) {
5155 thumbnail = r.thumbnail;
5156 description = r.description;
5157 }
5158 if (thumbnail == null && !always) {
5159 // If there is no thumbnail, and this entry is not actually
5160 // going away, then abort for now and pick up the next
5161 // thumbnail we get.
5162 return;
5163 }
5164 task = r.task;
5165
5166 int N = mPendingThumbnails.size();
5167 int i=0;
5168 while (i<N) {
5169 PendingThumbnailsRecord pr =
5170 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5171 //System.out.println("Looking in " + pr.pendingRecords);
5172 if (pr.pendingRecords.remove(r)) {
5173 if (receivers == null) {
5174 receivers = new ArrayList();
5175 }
5176 receivers.add(pr);
5177 if (pr.pendingRecords.size() == 0) {
5178 pr.finished = true;
5179 mPendingThumbnails.remove(i);
5180 N--;
5181 continue;
5182 }
5183 }
5184 i++;
5185 }
5186 }
5187
5188 if (receivers != null) {
5189 final int N = receivers.size();
5190 for (int i=0; i<N; i++) {
5191 try {
5192 PendingThumbnailsRecord pr =
5193 (PendingThumbnailsRecord)receivers.get(i);
5194 pr.receiver.newThumbnail(
5195 task != null ? task.taskId : -1, thumbnail, description);
5196 if (pr.finished) {
5197 pr.receiver.finished();
5198 }
5199 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005200 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 }
5202 }
5203 }
5204 }
5205
5206 // =========================================================
5207 // CONTENT PROVIDERS
5208 // =========================================================
5209
5210 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5211 List providers = null;
5212 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005213 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005215 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 } catch (RemoteException ex) {
5217 }
5218 if (providers != null) {
5219 final int N = providers.size();
5220 for (int i=0; i<N; i++) {
5221 ProviderInfo cpi =
5222 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005223 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 if (cpr == null) {
5225 cpr = new ContentProviderRecord(cpi, app.info);
5226 mProvidersByClass.put(cpi.name, cpr);
5227 }
5228 app.pubProviders.put(cpi.name, cpr);
5229 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005230 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 }
5232 }
5233 return providers;
5234 }
5235
5236 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005237 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5239 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5240 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5241 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005242 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 return null;
5244 }
5245 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5246 cpi.exported ? -1 : cpi.applicationInfo.uid)
5247 == PackageManager.PERMISSION_GRANTED) {
5248 return null;
5249 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005250
5251 PathPermission[] pps = cpi.pathPermissions;
5252 if (pps != null) {
5253 int i = pps.length;
5254 while (i > 0) {
5255 i--;
5256 PathPermission pp = pps[i];
5257 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5258 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005259 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005260 return null;
5261 }
5262 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5263 cpi.exported ? -1 : cpi.applicationInfo.uid)
5264 == PackageManager.PERMISSION_GRANTED) {
5265 return null;
5266 }
5267 }
5268 }
5269
Dianne Hackbornb424b632010-08-18 15:59:05 -07005270 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5271 if (perms != null) {
5272 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5273 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5274 return null;
5275 }
5276 }
5277 }
5278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 String msg = "Permission Denial: opening provider " + cpi.name
5280 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5281 + ", uid=" + callingUid + ") requires "
5282 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005283 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 return msg;
5285 }
5286
5287 private final ContentProviderHolder getContentProviderImpl(
5288 IApplicationThread caller, String name) {
5289 ContentProviderRecord cpr;
5290 ProviderInfo cpi = null;
5291
5292 synchronized(this) {
5293 ProcessRecord r = null;
5294 if (caller != null) {
5295 r = getRecordForAppLocked(caller);
5296 if (r == null) {
5297 throw new SecurityException(
5298 "Unable to find app for caller " + caller
5299 + " (pid=" + Binder.getCallingPid()
5300 + ") when getting content provider " + name);
5301 }
5302 }
5303
5304 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005305 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 if (cpr != null) {
5307 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005308 String msg;
5309 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5310 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 }
5312
5313 if (r != null && cpr.canRunHere(r)) {
5314 // This provider has been published or is in the process
5315 // of being published... but it is also allowed to run
5316 // in the caller's process, so don't make a connection
5317 // and just let the caller instantiate its own instance.
5318 if (cpr.provider != null) {
5319 // don't give caller the provider object, it needs
5320 // to make its own.
5321 cpr = new ContentProviderRecord(cpr);
5322 }
5323 return cpr;
5324 }
5325
5326 final long origId = Binder.clearCallingIdentity();
5327
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005328 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 // return it right away.
5330 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005331 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005332 "Adding provider requested by "
5333 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005334 + cpr.info.processName);
5335 Integer cnt = r.conProviders.get(cpr);
5336 if (cnt == null) {
5337 r.conProviders.put(cpr, new Integer(1));
5338 } else {
5339 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005342 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5343 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005344 // make sure to count it as being accessed and thus
5345 // back up on the LRU list. This is good because
5346 // content providers are often expensive to start.
5347 updateLruProcessLocked(cpr.app, false, true);
5348 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005349 } else {
5350 cpr.externals++;
5351 }
5352
5353 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 updateOomAdjLocked(cpr.app);
5355 }
5356
5357 Binder.restoreCallingIdentity(origId);
5358
5359 } else {
5360 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005361 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005362 resolveContentProvider(name,
5363 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 } catch (RemoteException ex) {
5365 }
5366 if (cpi == null) {
5367 return null;
5368 }
5369
Dianne Hackbornb424b632010-08-18 15:59:05 -07005370 String msg;
5371 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5372 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 }
5374
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005375 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005376 && !cpi.processName.equals("system")) {
5377 // If this content provider does not run in the system
5378 // process, and the system is not yet ready to run other
5379 // processes, then fail fast instead of hanging.
5380 throw new IllegalArgumentException(
5381 "Attempt to launch content provider before system ready");
5382 }
5383
Dianne Hackborn860755f2010-06-03 18:47:52 -07005384 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 final boolean firstClass = cpr == null;
5386 if (firstClass) {
5387 try {
5388 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005389 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 getApplicationInfo(
5391 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005392 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005394 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 + cpi.name);
5396 return null;
5397 }
5398 cpr = new ContentProviderRecord(cpi, ai);
5399 } catch (RemoteException ex) {
5400 // pm is in same process, this will never happen.
5401 }
5402 }
5403
5404 if (r != null && cpr.canRunHere(r)) {
5405 // If this is a multiprocess provider, then just return its
5406 // info and allow the caller to instantiate it. Only do
5407 // this if the provider is the same user as the caller's
5408 // process, or can run as root (so can be in any process).
5409 return cpr;
5410 }
5411
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005412 if (DEBUG_PROVIDER) {
5413 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005414 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005415 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 }
5417
5418 // This is single process, and our app is now connecting to it.
5419 // See if we are already in the process of launching this
5420 // provider.
5421 final int N = mLaunchingProviders.size();
5422 int i;
5423 for (i=0; i<N; i++) {
5424 if (mLaunchingProviders.get(i) == cpr) {
5425 break;
5426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 }
5428
5429 // If the provider is not already being launched, then get it
5430 // started.
5431 if (i >= N) {
5432 final long origId = Binder.clearCallingIdentity();
5433 ProcessRecord proc = startProcessLocked(cpi.processName,
5434 cpr.appInfo, false, 0, "content provider",
5435 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005436 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005438 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 + cpi.applicationInfo.packageName + "/"
5440 + cpi.applicationInfo.uid + " for provider "
5441 + name + ": process is bad");
5442 return null;
5443 }
5444 cpr.launchingApp = proc;
5445 mLaunchingProviders.add(cpr);
5446 Binder.restoreCallingIdentity(origId);
5447 }
5448
5449 // Make sure the provider is published (the same provider class
5450 // may be published under multiple names).
5451 if (firstClass) {
5452 mProvidersByClass.put(cpi.name, cpr);
5453 }
5454 mProvidersByName.put(name, cpr);
5455
5456 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005457 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005458 "Adding provider requested by "
5459 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005460 + cpr.info.processName);
5461 Integer cnt = r.conProviders.get(cpr);
5462 if (cnt == null) {
5463 r.conProviders.put(cpr, new Integer(1));
5464 } else {
5465 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 cpr.clients.add(r);
5468 } else {
5469 cpr.externals++;
5470 }
5471 }
5472 }
5473
5474 // Wait for the provider to be published...
5475 synchronized (cpr) {
5476 while (cpr.provider == null) {
5477 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005478 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 + cpi.applicationInfo.packageName + "/"
5480 + cpi.applicationInfo.uid + " for provider "
5481 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005482 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 cpi.applicationInfo.packageName,
5484 cpi.applicationInfo.uid, name);
5485 return null;
5486 }
5487 try {
5488 cpr.wait();
5489 } catch (InterruptedException ex) {
5490 }
5491 }
5492 }
5493 return cpr;
5494 }
5495
5496 public final ContentProviderHolder getContentProvider(
5497 IApplicationThread caller, String name) {
5498 if (caller == null) {
5499 String msg = "null IApplicationThread when getting content provider "
5500 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005501 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 throw new SecurityException(msg);
5503 }
5504
5505 return getContentProviderImpl(caller, name);
5506 }
5507
5508 private ContentProviderHolder getContentProviderExternal(String name) {
5509 return getContentProviderImpl(null, name);
5510 }
5511
5512 /**
5513 * Drop a content provider from a ProcessRecord's bookkeeping
5514 * @param cpr
5515 */
5516 public void removeContentProvider(IApplicationThread caller, String name) {
5517 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005518 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005520 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005521 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005522 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 return;
5524 }
5525 final ProcessRecord r = getRecordForAppLocked(caller);
5526 if (r == null) {
5527 throw new SecurityException(
5528 "Unable to find app for caller " + caller +
5529 " when removing content provider " + name);
5530 }
5531 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005532 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005533 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005534 + r.info.processName + " from process "
5535 + localCpr.appInfo.processName);
5536 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005538 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005539 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 return;
5541 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005542 Integer cnt = r.conProviders.get(localCpr);
5543 if (cnt == null || cnt.intValue() <= 1) {
5544 localCpr.clients.remove(r);
5545 r.conProviders.remove(localCpr);
5546 } else {
5547 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 }
5550 updateOomAdjLocked();
5551 }
5552 }
5553
5554 private void removeContentProviderExternal(String name) {
5555 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005556 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005557 if(cpr == null) {
5558 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005559 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 return;
5561 }
5562
5563 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005564 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 localCpr.externals--;
5566 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005567 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 }
5569 updateOomAdjLocked();
5570 }
5571 }
5572
5573 public final void publishContentProviders(IApplicationThread caller,
5574 List<ContentProviderHolder> providers) {
5575 if (providers == null) {
5576 return;
5577 }
5578
5579 synchronized(this) {
5580 final ProcessRecord r = getRecordForAppLocked(caller);
5581 if (r == null) {
5582 throw new SecurityException(
5583 "Unable to find app for caller " + caller
5584 + " (pid=" + Binder.getCallingPid()
5585 + ") when publishing content providers");
5586 }
5587
5588 final long origId = Binder.clearCallingIdentity();
5589
5590 final int N = providers.size();
5591 for (int i=0; i<N; i++) {
5592 ContentProviderHolder src = providers.get(i);
5593 if (src == null || src.info == null || src.provider == null) {
5594 continue;
5595 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005596 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 if (dst != null) {
5598 mProvidersByClass.put(dst.info.name, dst);
5599 String names[] = dst.info.authority.split(";");
5600 for (int j = 0; j < names.length; j++) {
5601 mProvidersByName.put(names[j], dst);
5602 }
5603
5604 int NL = mLaunchingProviders.size();
5605 int j;
5606 for (j=0; j<NL; j++) {
5607 if (mLaunchingProviders.get(j) == dst) {
5608 mLaunchingProviders.remove(j);
5609 j--;
5610 NL--;
5611 }
5612 }
5613 synchronized (dst) {
5614 dst.provider = src.provider;
5615 dst.app = r;
5616 dst.notifyAll();
5617 }
5618 updateOomAdjLocked(r);
5619 }
5620 }
5621
5622 Binder.restoreCallingIdentity(origId);
5623 }
5624 }
5625
5626 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005627 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005628 synchronized (mSelf) {
5629 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5630 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005631 if (providers != null) {
5632 for (int i=providers.size()-1; i>=0; i--) {
5633 ProviderInfo pi = (ProviderInfo)providers.get(i);
5634 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5635 Slog.w(TAG, "Not installing system proc provider " + pi.name
5636 + ": not system .apk");
5637 providers.remove(i);
5638 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005639 }
5640 }
5641 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005642 if (providers != null) {
5643 mSystemThread.installSystemProviders(providers);
5644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 }
5646
Dianne Hackborn8313fc72010-09-26 18:34:53 -07005647 /**
5648 * Allows app to retrieve the MIME type of a URI without having permission
5649 * to access its content provider.
5650 *
5651 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5652 *
5653 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5654 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5655 */
5656 public String getProviderMimeType(Uri uri) {
5657 final String name = uri.getAuthority();
5658 final long ident = Binder.clearCallingIdentity();
5659 ContentProviderHolder holder = null;
5660
5661 try {
5662 holder = getContentProviderExternal(name);
5663 if (holder != null) {
5664 return holder.provider.getType(uri);
5665 }
5666 } catch (RemoteException e) {
5667 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5668 return null;
5669 } finally {
5670 if (holder != null) {
5671 removeContentProviderExternal(name);
5672 }
5673 Binder.restoreCallingIdentity(ident);
5674 }
5675
5676 return null;
5677 }
5678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 // =========================================================
5680 // GLOBAL MANAGEMENT
5681 // =========================================================
5682
5683 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5684 ApplicationInfo info, String customProcess) {
5685 String proc = customProcess != null ? customProcess : info.processName;
5686 BatteryStatsImpl.Uid.Proc ps = null;
5687 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5688 synchronized (stats) {
5689 ps = stats.getProcessStatsLocked(info.uid, proc);
5690 }
5691 return new ProcessRecord(ps, thread, info, proc);
5692 }
5693
5694 final ProcessRecord addAppLocked(ApplicationInfo info) {
5695 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5696
5697 if (app == null) {
5698 app = newProcessRecordLocked(null, info, null);
5699 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005700 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 }
5702
5703 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5704 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5705 app.persistent = true;
5706 app.maxAdj = CORE_SERVER_ADJ;
5707 }
5708 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5709 mPersistentStartingProcesses.add(app);
5710 startProcessLocked(app, "added application", app.processName);
5711 }
5712
5713 return app;
5714 }
5715
5716 public void unhandledBack() {
5717 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5718 "unhandledBack()");
5719
5720 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005721 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005722 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 TAG, "Performing unhandledBack(): stack size = " + count);
5724 if (count > 1) {
5725 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005726 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5728 Binder.restoreCallingIdentity(origId);
5729 }
5730 }
5731 }
5732
5733 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5734 String name = uri.getAuthority();
5735 ContentProviderHolder cph = getContentProviderExternal(name);
5736 ParcelFileDescriptor pfd = null;
5737 if (cph != null) {
5738 // We record the binder invoker's uid in thread-local storage before
5739 // going to the content provider to open the file. Later, in the code
5740 // that handles all permissions checks, we look for this uid and use
5741 // that rather than the Activity Manager's own uid. The effect is that
5742 // we do the check against the caller's permissions even though it looks
5743 // to the content provider like the Activity Manager itself is making
5744 // the request.
5745 sCallerIdentity.set(new Identity(
5746 Binder.getCallingPid(), Binder.getCallingUid()));
5747 try {
5748 pfd = cph.provider.openFile(uri, "r");
5749 } catch (FileNotFoundException e) {
5750 // do nothing; pfd will be returned null
5751 } finally {
5752 // Ensure that whatever happens, we clean up the identity state
5753 sCallerIdentity.remove();
5754 }
5755
5756 // We've got the fd now, so we're done with the provider.
5757 removeContentProviderExternal(name);
5758 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005759 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 }
5761 return pfd;
5762 }
5763
5764 public void goingToSleep() {
5765 synchronized(this) {
5766 mSleeping = true;
5767 mWindowManager.setEventDispatching(false);
5768
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005769 if (mMainStack.mResumedActivity != null) {
5770 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005772 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005773 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005774
5775 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005776 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005777 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5778 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005779 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 }
5781 }
5782
Dianne Hackborn55280a92009-05-07 15:53:46 -07005783 public boolean shutdown(int timeout) {
5784 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5785 != PackageManager.PERMISSION_GRANTED) {
5786 throw new SecurityException("Requires permission "
5787 + android.Manifest.permission.SHUTDOWN);
5788 }
5789
5790 boolean timedout = false;
5791
5792 synchronized(this) {
5793 mShuttingDown = true;
5794 mWindowManager.setEventDispatching(false);
5795
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005796 if (mMainStack.mResumedActivity != null) {
5797 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005798 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005799 while (mMainStack.mResumedActivity != null
5800 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005801 long delay = endTime - System.currentTimeMillis();
5802 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005803 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005804 timedout = true;
5805 break;
5806 }
5807 try {
5808 this.wait();
5809 } catch (InterruptedException e) {
5810 }
5811 }
5812 }
5813 }
5814
5815 mUsageStatsService.shutdown();
5816 mBatteryStatsService.shutdown();
5817
5818 return timedout;
5819 }
5820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 public void wakingUp() {
5822 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005823 if (mMainStack.mGoingToSleep.isHeld()) {
5824 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005825 }
5826 mWindowManager.setEventDispatching(true);
5827 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005828 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 }
5830 }
5831
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005832 public void stopAppSwitches() {
5833 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5834 != PackageManager.PERMISSION_GRANTED) {
5835 throw new SecurityException("Requires permission "
5836 + android.Manifest.permission.STOP_APP_SWITCHES);
5837 }
5838
5839 synchronized(this) {
5840 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5841 + APP_SWITCH_DELAY_TIME;
5842 mDidAppSwitch = false;
5843 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5844 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5845 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5846 }
5847 }
5848
5849 public void resumeAppSwitches() {
5850 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5851 != PackageManager.PERMISSION_GRANTED) {
5852 throw new SecurityException("Requires permission "
5853 + android.Manifest.permission.STOP_APP_SWITCHES);
5854 }
5855
5856 synchronized(this) {
5857 // Note that we don't execute any pending app switches... we will
5858 // let those wait until either the timeout, or the next start
5859 // activity request.
5860 mAppSwitchesAllowedTime = 0;
5861 }
5862 }
5863
5864 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5865 String name) {
5866 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5867 return true;
5868 }
5869
5870 final int perm = checkComponentPermission(
5871 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5872 callingUid, -1);
5873 if (perm == PackageManager.PERMISSION_GRANTED) {
5874 return true;
5875 }
5876
Joe Onorato8a9b2202010-02-26 18:56:32 -08005877 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005878 return false;
5879 }
5880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 public void setDebugApp(String packageName, boolean waitForDebugger,
5882 boolean persistent) {
5883 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5884 "setDebugApp()");
5885
5886 // Note that this is not really thread safe if there are multiple
5887 // callers into it at the same time, but that's not a situation we
5888 // care about.
5889 if (persistent) {
5890 final ContentResolver resolver = mContext.getContentResolver();
5891 Settings.System.putString(
5892 resolver, Settings.System.DEBUG_APP,
5893 packageName);
5894 Settings.System.putInt(
5895 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5896 waitForDebugger ? 1 : 0);
5897 }
5898
5899 synchronized (this) {
5900 if (!persistent) {
5901 mOrigDebugApp = mDebugApp;
5902 mOrigWaitForDebugger = mWaitForDebugger;
5903 }
5904 mDebugApp = packageName;
5905 mWaitForDebugger = waitForDebugger;
5906 mDebugTransient = !persistent;
5907 if (packageName != null) {
5908 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005909 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 Binder.restoreCallingIdentity(origId);
5911 }
5912 }
5913 }
5914
5915 public void setAlwaysFinish(boolean enabled) {
5916 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5917 "setAlwaysFinish()");
5918
5919 Settings.System.putInt(
5920 mContext.getContentResolver(),
5921 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5922
5923 synchronized (this) {
5924 mAlwaysFinishActivities = enabled;
5925 }
5926 }
5927
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005928 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005930 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005932 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 }
5934 }
5935
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005936 public boolean isUserAMonkey() {
5937 // For now the fact that there is a controller implies
5938 // we have a monkey.
5939 synchronized (this) {
5940 return mController != null;
5941 }
5942 }
5943
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005944 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005945 synchronized (this) {
5946 mWatchers.register(watcher);
5947 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005948 }
5949
5950 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005951 synchronized (this) {
5952 mWatchers.unregister(watcher);
5953 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005954 }
5955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 public final void enterSafeMode() {
5957 synchronized(this) {
5958 // It only makes sense to do this before the system is ready
5959 // and started launching other packages.
5960 if (!mSystemReady) {
5961 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005962 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 } catch (RemoteException e) {
5964 }
5965
5966 View v = LayoutInflater.from(mContext).inflate(
5967 com.android.internal.R.layout.safe_mode, null);
5968 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5969 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5970 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5971 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5972 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5973 lp.format = v.getBackground().getOpacity();
5974 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5975 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5976 ((WindowManager)mContext.getSystemService(
5977 Context.WINDOW_SERVICE)).addView(v, lp);
5978 }
5979 }
5980 }
5981
5982 public void noteWakeupAlarm(IIntentSender sender) {
5983 if (!(sender instanceof PendingIntentRecord)) {
5984 return;
5985 }
5986 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5987 synchronized (stats) {
5988 if (mBatteryStatsService.isOnBattery()) {
5989 mBatteryStatsService.enforceCallingPermission();
5990 PendingIntentRecord rec = (PendingIntentRecord)sender;
5991 int MY_UID = Binder.getCallingUid();
5992 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5993 BatteryStatsImpl.Uid.Pkg pkg =
5994 stats.getPackageStatsLocked(uid, rec.key.packageName);
5995 pkg.incWakeupsLocked();
5996 }
5997 }
5998 }
5999
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006000 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006001 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006002 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006004 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006005 // XXX Note: don't acquire main activity lock here, because the window
6006 // manager calls in with its locks held.
6007
6008 boolean killed = false;
6009 synchronized (mPidsSelfLocked) {
6010 int[] types = new int[pids.length];
6011 int worstType = 0;
6012 for (int i=0; i<pids.length; i++) {
6013 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6014 if (proc != null) {
6015 int type = proc.setAdj;
6016 types[i] = type;
6017 if (type > worstType) {
6018 worstType = type;
6019 }
6020 }
6021 }
6022
6023 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6024 // then constrain it so we will kill all hidden procs.
6025 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6026 worstType = HIDDEN_APP_MIN_ADJ;
6027 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006028 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 for (int i=0; i<pids.length; i++) {
6030 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6031 if (proc == null) {
6032 continue;
6033 }
6034 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006035 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006036 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006037 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6038 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006040 proc.killedBackground = true;
6041 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 }
6043 }
6044 }
6045 return killed;
6046 }
6047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 public final void startRunning(String pkg, String cls, String action,
6049 String data) {
6050 synchronized(this) {
6051 if (mStartRunning) {
6052 return;
6053 }
6054 mStartRunning = true;
6055 mTopComponent = pkg != null && cls != null
6056 ? new ComponentName(pkg, cls) : null;
6057 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6058 mTopData = data;
6059 if (!mSystemReady) {
6060 return;
6061 }
6062 }
6063
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006064 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 }
6066
6067 private void retrieveSettings() {
6068 final ContentResolver resolver = mContext.getContentResolver();
6069 String debugApp = Settings.System.getString(
6070 resolver, Settings.System.DEBUG_APP);
6071 boolean waitForDebugger = Settings.System.getInt(
6072 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6073 boolean alwaysFinishActivities = Settings.System.getInt(
6074 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6075
6076 Configuration configuration = new Configuration();
6077 Settings.System.getConfiguration(resolver, configuration);
6078
6079 synchronized (this) {
6080 mDebugApp = mOrigDebugApp = debugApp;
6081 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6082 mAlwaysFinishActivities = alwaysFinishActivities;
6083 // This happens before any activities are started, so we can
6084 // change mConfiguration in-place.
6085 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006086 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006087 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088 }
6089 }
6090
6091 public boolean testIsSystemReady() {
6092 // no need to synchronize(this) just to read & return the value
6093 return mSystemReady;
6094 }
6095
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006096 private static File getCalledPreBootReceiversFile() {
6097 File dataDir = Environment.getDataDirectory();
6098 File systemDir = new File(dataDir, "system");
6099 File fname = new File(systemDir, "called_pre_boots.dat");
6100 return fname;
6101 }
6102
6103 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6104 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6105 File file = getCalledPreBootReceiversFile();
6106 FileInputStream fis = null;
6107 try {
6108 fis = new FileInputStream(file);
6109 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6110 int vers = dis.readInt();
6111 String codename = dis.readUTF();
6112 if (vers == android.os.Build.VERSION.SDK_INT
6113 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6114 int num = dis.readInt();
6115 while (num > 0) {
6116 num--;
6117 String pkg = dis.readUTF();
6118 String cls = dis.readUTF();
6119 lastDoneReceivers.add(new ComponentName(pkg, cls));
6120 }
6121 }
6122 } catch (FileNotFoundException e) {
6123 } catch (IOException e) {
6124 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6125 } finally {
6126 if (fis != null) {
6127 try {
6128 fis.close();
6129 } catch (IOException e) {
6130 }
6131 }
6132 }
6133 return lastDoneReceivers;
6134 }
6135
6136 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6137 File file = getCalledPreBootReceiversFile();
6138 FileOutputStream fos = null;
6139 DataOutputStream dos = null;
6140 try {
6141 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6142 fos = new FileOutputStream(file);
6143 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6144 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6145 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6146 dos.writeInt(list.size());
6147 for (int i=0; i<list.size(); i++) {
6148 dos.writeUTF(list.get(i).getPackageName());
6149 dos.writeUTF(list.get(i).getClassName());
6150 }
6151 } catch (IOException e) {
6152 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6153 file.delete();
6154 } finally {
6155 if (dos != null) {
6156 try {
6157 dos.close();
6158 } catch (IOException e) {
6159 // TODO Auto-generated catch block
6160 e.printStackTrace();
6161 }
6162 }
6163 }
6164 }
6165
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006166 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 // In the simulator, startRunning will never have been called, which
6168 // normally sets a few crucial variables. Do it here instead.
6169 if (!Process.supportsProcesses()) {
6170 mStartRunning = true;
6171 mTopAction = Intent.ACTION_MAIN;
6172 }
6173
6174 synchronized(this) {
6175 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006176 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 return;
6178 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006179
6180 // Check to see if there are any update receivers to run.
6181 if (!mDidUpdate) {
6182 if (mWaitingUpdate) {
6183 return;
6184 }
6185 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6186 List<ResolveInfo> ris = null;
6187 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006188 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006189 intent, null, 0);
6190 } catch (RemoteException e) {
6191 }
6192 if (ris != null) {
6193 for (int i=ris.size()-1; i>=0; i--) {
6194 if ((ris.get(i).activityInfo.applicationInfo.flags
6195 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6196 ris.remove(i);
6197 }
6198 }
6199 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006200
6201 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6202
6203 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006204 for (int i=0; i<ris.size(); i++) {
6205 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006206 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6207 if (lastDoneReceivers.contains(comp)) {
6208 ris.remove(i);
6209 i--;
6210 }
6211 }
6212
6213 for (int i=0; i<ris.size(); i++) {
6214 ActivityInfo ai = ris.get(i).activityInfo;
6215 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6216 doneReceivers.add(comp);
6217 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006218 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006219 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006220 finisher = new IIntentReceiver.Stub() {
6221 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006222 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006223 boolean sticky) {
6224 // The raw IIntentReceiver interface is called
6225 // with the AM lock held, so redispatch to
6226 // execute our code without the lock.
6227 mHandler.post(new Runnable() {
6228 public void run() {
6229 synchronized (ActivityManagerService.this) {
6230 mDidUpdate = true;
6231 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006232 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006233 systemReady(goingCallback);
6234 }
6235 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006236 }
6237 };
6238 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006239 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006240 broadcastIntentLocked(null, null, intent, null, finisher,
6241 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006242 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006243 mWaitingUpdate = true;
6244 }
6245 }
6246 }
6247 if (mWaitingUpdate) {
6248 return;
6249 }
6250 mDidUpdate = true;
6251 }
6252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 mSystemReady = true;
6254 if (!mStartRunning) {
6255 return;
6256 }
6257 }
6258
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006259 ArrayList<ProcessRecord> procsToKill = null;
6260 synchronized(mPidsSelfLocked) {
6261 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6262 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6263 if (!isAllowedWhileBooting(proc.info)){
6264 if (procsToKill == null) {
6265 procsToKill = new ArrayList<ProcessRecord>();
6266 }
6267 procsToKill.add(proc);
6268 }
6269 }
6270 }
6271
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006272 synchronized(this) {
6273 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006274 for (int i=procsToKill.size()-1; i>=0; i--) {
6275 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006276 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006277 removeProcessLocked(proc, true);
6278 }
6279 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006280
6281 // Now that we have cleaned up any update processes, we
6282 // are ready to start launching real processes and know that
6283 // we won't trample on them any more.
6284 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006285 }
6286
Joe Onorato8a9b2202010-02-26 18:56:32 -08006287 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006288 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 SystemClock.uptimeMillis());
6290
6291 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006292 // Make sure we have no pre-ready processes sitting around.
6293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6295 ResolveInfo ri = mContext.getPackageManager()
6296 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006297 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 CharSequence errorMsg = null;
6299 if (ri != null) {
6300 ActivityInfo ai = ri.activityInfo;
6301 ApplicationInfo app = ai.applicationInfo;
6302 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6303 mTopAction = Intent.ACTION_FACTORY_TEST;
6304 mTopData = null;
6305 mTopComponent = new ComponentName(app.packageName,
6306 ai.name);
6307 } else {
6308 errorMsg = mContext.getResources().getText(
6309 com.android.internal.R.string.factorytest_not_system);
6310 }
6311 } else {
6312 errorMsg = mContext.getResources().getText(
6313 com.android.internal.R.string.factorytest_no_action);
6314 }
6315 if (errorMsg != null) {
6316 mTopAction = null;
6317 mTopData = null;
6318 mTopComponent = null;
6319 Message msg = Message.obtain();
6320 msg.what = SHOW_FACTORY_ERROR_MSG;
6321 msg.getData().putCharSequence("msg", errorMsg);
6322 mHandler.sendMessage(msg);
6323 }
6324 }
6325 }
6326
6327 retrieveSettings();
6328
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006329 if (goingCallback != null) goingCallback.run();
6330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 synchronized (this) {
6332 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6333 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006334 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006335 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 if (apps != null) {
6337 int N = apps.size();
6338 int i;
6339 for (i=0; i<N; i++) {
6340 ApplicationInfo info
6341 = (ApplicationInfo)apps.get(i);
6342 if (info != null &&
6343 !info.packageName.equals("android")) {
6344 addAppLocked(info);
6345 }
6346 }
6347 }
6348 } catch (RemoteException ex) {
6349 // pm is in same process, this will never happen.
6350 }
6351 }
6352
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006353 // Start up initial activity.
6354 mBooting = true;
6355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006357 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 Message msg = Message.obtain();
6359 msg.what = SHOW_UID_ERROR_MSG;
6360 mHandler.sendMessage(msg);
6361 }
6362 } catch (RemoteException e) {
6363 }
6364
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006365 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 }
6367 }
6368
Dan Egnorb7f03672009-12-09 16:22:32 -08006369 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006370 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006372 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006373 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 startAppProblemLocked(app);
6375 app.stopFreezingAllLocked();
6376 return handleAppCrashLocked(app);
6377 }
6378
Dan Egnorb7f03672009-12-09 16:22:32 -08006379 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006380 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006382 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006383 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6384 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 startAppProblemLocked(app);
6386 app.stopFreezingAllLocked();
6387 }
6388
6389 /**
6390 * Generate a process error record, suitable for attachment to a ProcessRecord.
6391 *
6392 * @param app The ProcessRecord in which the error occurred.
6393 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6394 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006395 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 * @param shortMsg Short message describing the crash.
6397 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006398 * @param stackTrace Full crash stack trace, may be null.
6399 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 * @return Returns a fully-formed AppErrorStateInfo record.
6401 */
6402 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006403 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 report.condition = condition;
6407 report.processName = app.processName;
6408 report.pid = app.pid;
6409 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006410 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 report.shortMsg = shortMsg;
6412 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006413 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414
6415 return report;
6416 }
6417
Dan Egnor42471dd2010-01-07 17:25:22 -08006418 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 synchronized (this) {
6420 app.crashing = false;
6421 app.crashingReport = null;
6422 app.notResponding = false;
6423 app.notRespondingReport = null;
6424 if (app.anrDialog == fromDialog) {
6425 app.anrDialog = null;
6426 }
6427 if (app.waitDialog == fromDialog) {
6428 app.waitDialog = null;
6429 }
6430 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006431 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006432 Slog.i(ActivityManagerService.TAG, "Killing "
6433 + app.processName + " (pid=" + app.pid + "): user's request");
6434 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6435 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 Process.killProcess(app.pid);
6437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 }
6439 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006440
Dan Egnorb7f03672009-12-09 16:22:32 -08006441 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 long now = SystemClock.uptimeMillis();
6443
6444 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6445 app.info.uid);
6446 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6447 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006450 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 app.info.processName, app.info.uid);
6452 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006453 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6454 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006456 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006458 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 }
6460 }
6461 if (!app.persistent) {
6462 // We don't want to start this process again until the user
6463 // explicitly does so... but for persistent process, we really
6464 // need to keep it running. If a persistent process is actually
6465 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006466 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 app.info.processName);
6468 mBadProcesses.put(app.info.processName, app.info.uid, now);
6469 app.bad = true;
6470 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6471 app.removed = true;
6472 removeProcessLocked(app, false);
6473 return false;
6474 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006475 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006476 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006477 if (r.app == app) {
6478 // If the top running activity is from this crashing
6479 // process, then terminate it to avoid getting in a loop.
6480 Slog.w(TAG, " Force finishing activity "
6481 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006482 int index = mMainStack.indexOfTokenLocked(r);
6483 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006484 Activity.RESULT_CANCELED, null, "crashed");
6485 // Also terminate an activities below it that aren't yet
6486 // stopped, to avoid a situation where one will get
6487 // re-start our crashing activity once it gets resumed again.
6488 index--;
6489 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006490 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006491 if (r.state == ActivityState.RESUMED
6492 || r.state == ActivityState.PAUSING
6493 || r.state == ActivityState.PAUSED) {
6494 if (!r.isHomeActivity) {
6495 Slog.w(TAG, " Force finishing activity "
6496 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006497 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006498 Activity.RESULT_CANCELED, null, "crashed");
6499 }
6500 }
6501 }
6502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 }
6504
6505 // Bump up the crash count of any services currently running in the proc.
6506 if (app.services.size() != 0) {
6507 // Any services running in the application need to be placed
6508 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006509 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006511 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 sr.crashCount++;
6513 }
6514 }
6515
6516 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6517 return true;
6518 }
6519
6520 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006521 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6522 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 skipCurrentReceiverLocked(app);
6524 }
6525
6526 void skipCurrentReceiverLocked(ProcessRecord app) {
6527 boolean reschedule = false;
6528 BroadcastRecord r = app.curReceiver;
6529 if (r != null) {
6530 // The current broadcast is waiting for this app's receiver
6531 // to be finished. Looks like that's not going to happen, so
6532 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006533 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6535 r.resultExtras, r.resultAbort, true);
6536 reschedule = true;
6537 }
6538 r = mPendingBroadcast;
6539 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006540 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006541 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006542 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006543 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6544 r.resultExtras, r.resultAbort, true);
6545 reschedule = true;
6546 }
6547 if (reschedule) {
6548 scheduleBroadcastsLocked();
6549 }
6550 }
6551
Dan Egnor60d87622009-12-16 16:32:58 -08006552 /**
6553 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6554 * The application process will exit immediately after this call returns.
6555 * @param app object of the crashing app, null for the system server
6556 * @param crashInfo describing the exception
6557 */
6558 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6559 ProcessRecord r = findAppProcess(app);
6560
6561 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6562 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006563 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006564 crashInfo.exceptionClassName,
6565 crashInfo.exceptionMessage,
6566 crashInfo.throwFileName,
6567 crashInfo.throwLineNumber);
6568
Dan Egnor42471dd2010-01-07 17:25:22 -08006569 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006570
6571 crashApplication(r, crashInfo);
6572 }
6573
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006574 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006575 IBinder app,
6576 int violationMask,
6577 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006578 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006579
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006580 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006581 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006582 boolean logIt = true;
6583 synchronized (mAlreadyLoggedViolatedStacks) {
6584 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6585 logIt = false;
6586 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006587 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006588 // the relative pain numbers, without logging all
6589 // the stack traces repeatedly. We'd want to do
6590 // likewise in the client code, which also does
6591 // dup suppression, before the Binder call.
6592 } else {
6593 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6594 mAlreadyLoggedViolatedStacks.clear();
6595 }
6596 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6597 }
6598 }
6599 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006600 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006601 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006602 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006603
6604 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6605 AppErrorResult result = new AppErrorResult();
6606 synchronized (this) {
6607 final long origId = Binder.clearCallingIdentity();
6608
6609 Message msg = Message.obtain();
6610 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6611 HashMap<String, Object> data = new HashMap<String, Object>();
6612 data.put("result", result);
6613 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006614 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006615 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006616 msg.obj = data;
6617 mHandler.sendMessage(msg);
6618
6619 Binder.restoreCallingIdentity(origId);
6620 }
6621 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006622 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006623 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006624 }
6625
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006626 // Depending on the policy in effect, there could be a bunch of
6627 // these in quick succession so we try to batch these together to
6628 // minimize disk writes, number of dropbox entries, and maximize
6629 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006630 private void logStrictModeViolationToDropBox(
6631 ProcessRecord process,
6632 StrictMode.ViolationInfo info) {
6633 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006634 return;
6635 }
6636 final boolean isSystemApp = process == null ||
6637 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6638 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6639 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6640 final DropBoxManager dbox = (DropBoxManager)
6641 mContext.getSystemService(Context.DROPBOX_SERVICE);
6642
6643 // Exit early if the dropbox isn't configured to accept this report type.
6644 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6645
6646 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006647 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006648 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6649 synchronized (sb) {
6650 bufferWasEmpty = sb.length() == 0;
6651 appendDropBoxProcessHeaders(process, sb);
6652 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6653 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006654 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6655 if (info.violationNumThisLoop != 0) {
6656 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6657 }
6658 if (info != null && info.durationMillis != -1) {
6659 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006660 }
6661 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006662 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6663 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006664 }
6665 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006666
6667 // Only buffer up to ~64k. Various logging bits truncate
6668 // things at 128k.
6669 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006670 }
6671
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006672 // Flush immediately if the buffer's grown too large, or this
6673 // is a non-system app. Non-system apps are isolated with a
6674 // different tag & policy and not batched.
6675 //
6676 // Batching is useful during internal testing with
6677 // StrictMode settings turned up high. Without batching,
6678 // thousands of separate files could be created on boot.
6679 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006680 new Thread("Error dump: " + dropboxTag) {
6681 @Override
6682 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006683 String report;
6684 synchronized (sb) {
6685 report = sb.toString();
6686 sb.delete(0, sb.length());
6687 sb.trimToSize();
6688 }
6689 if (report.length() != 0) {
6690 dbox.addText(dropboxTag, report);
6691 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006692 }
6693 }.start();
6694 return;
6695 }
6696
6697 // System app batching:
6698 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006699 // An existing dropbox-writing thread is outstanding, so
6700 // we don't need to start it up. The existing thread will
6701 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006702 return;
6703 }
6704
6705 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6706 // (After this point, we shouldn't access AMS internal data structures.)
6707 new Thread("Error dump: " + dropboxTag) {
6708 @Override
6709 public void run() {
6710 // 5 second sleep to let stacks arrive and be batched together
6711 try {
6712 Thread.sleep(5000); // 5 seconds
6713 } catch (InterruptedException e) {}
6714
6715 String errorReport;
6716 synchronized (mStrictModeBuffer) {
6717 errorReport = mStrictModeBuffer.toString();
6718 if (errorReport.length() == 0) {
6719 return;
6720 }
6721 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6722 mStrictModeBuffer.trimToSize();
6723 }
6724 dbox.addText(dropboxTag, errorReport);
6725 }
6726 }.start();
6727 }
6728
Dan Egnor60d87622009-12-16 16:32:58 -08006729 /**
6730 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6731 * @param app object of the crashing app, null for the system server
6732 * @param tag reported by the caller
6733 * @param crashInfo describing the context of the error
6734 * @return true if the process should exit immediately (WTF is fatal)
6735 */
6736 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006737 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006738 ProcessRecord r = findAppProcess(app);
6739
6740 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6741 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006742 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006743 tag, crashInfo.exceptionMessage);
6744
Dan Egnor42471dd2010-01-07 17:25:22 -08006745 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006746
Doug Zongker43866e02010-01-07 12:09:54 -08006747 if (Settings.Secure.getInt(mContext.getContentResolver(),
6748 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006749 crashApplication(r, crashInfo);
6750 return true;
6751 } else {
6752 return false;
6753 }
6754 }
6755
6756 /**
6757 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6758 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6759 */
6760 private ProcessRecord findAppProcess(IBinder app) {
6761 if (app == null) {
6762 return null;
6763 }
6764
6765 synchronized (this) {
6766 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6767 final int NA = apps.size();
6768 for (int ia=0; ia<NA; ia++) {
6769 ProcessRecord p = apps.valueAt(ia);
6770 if (p.thread != null && p.thread.asBinder() == app) {
6771 return p;
6772 }
6773 }
6774 }
6775
Joe Onorato8a9b2202010-02-26 18:56:32 -08006776 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006777 return null;
6778 }
6779 }
6780
6781 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006782 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6783 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006784 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006785 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6786 // Note: ProcessRecord 'process' is guarded by the service
6787 // instance. (notably process.pkgList, which could otherwise change
6788 // concurrently during execution of this method)
6789 synchronized (this) {
6790 if (process == null || process.pid == MY_PID) {
6791 sb.append("Process: system_server\n");
6792 } else {
6793 sb.append("Process: ").append(process.processName).append("\n");
6794 }
6795 if (process == null) {
6796 return;
6797 }
Dan Egnora455d192010-03-12 08:52:28 -08006798 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006799 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006800 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6801 for (String pkg : process.pkgList) {
6802 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006803 try {
Dan Egnora455d192010-03-12 08:52:28 -08006804 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6805 if (pi != null) {
6806 sb.append(" v").append(pi.versionCode);
6807 if (pi.versionName != null) {
6808 sb.append(" (").append(pi.versionName).append(")");
6809 }
6810 }
6811 } catch (RemoteException e) {
6812 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006813 }
Dan Egnora455d192010-03-12 08:52:28 -08006814 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006815 }
Dan Egnora455d192010-03-12 08:52:28 -08006816 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006817 }
6818
6819 private static String processClass(ProcessRecord process) {
6820 if (process == null || process.pid == MY_PID) {
6821 return "system_server";
6822 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6823 return "system_app";
6824 } else {
6825 return "data_app";
6826 }
6827 }
6828
6829 /**
6830 * Write a description of an error (crash, WTF, ANR) to the drop box.
6831 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6832 * @param process which caused the error, null means the system server
6833 * @param activity which triggered the error, null if unknown
6834 * @param parent activity related to the error, null if unknown
6835 * @param subject line related to the error, null if absent
6836 * @param report in long form describing the error, null if absent
6837 * @param logFile to include in the report, null if none
6838 * @param crashInfo giving an application stack trace, null if absent
6839 */
6840 public void addErrorToDropBox(String eventType,
6841 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6842 final String report, final File logFile,
6843 final ApplicationErrorReport.CrashInfo crashInfo) {
6844 // NOTE -- this must never acquire the ActivityManagerService lock,
6845 // otherwise the watchdog may be prevented from resetting the system.
6846
6847 final String dropboxTag = processClass(process) + "_" + eventType;
6848 final DropBoxManager dbox = (DropBoxManager)
6849 mContext.getSystemService(Context.DROPBOX_SERVICE);
6850
6851 // Exit early if the dropbox isn't configured to accept this report type.
6852 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6853
6854 final StringBuilder sb = new StringBuilder(1024);
6855 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006856 if (activity != null) {
6857 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6858 }
6859 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6860 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6861 }
6862 if (parent != null && parent != activity) {
6863 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6864 }
6865 if (subject != null) {
6866 sb.append("Subject: ").append(subject).append("\n");
6867 }
6868 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6869 sb.append("\n");
6870
6871 // Do the rest in a worker thread to avoid blocking the caller on I/O
6872 // (After this point, we shouldn't access AMS internal data structures.)
6873 Thread worker = new Thread("Error dump: " + dropboxTag) {
6874 @Override
6875 public void run() {
6876 if (report != null) {
6877 sb.append(report);
6878 }
6879 if (logFile != null) {
6880 try {
6881 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6882 } catch (IOException e) {
6883 Slog.e(TAG, "Error reading " + logFile, e);
6884 }
6885 }
6886 if (crashInfo != null && crashInfo.stackTrace != null) {
6887 sb.append(crashInfo.stackTrace);
6888 }
6889
6890 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6891 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6892 if (lines > 0) {
6893 sb.append("\n");
6894
6895 // Merge several logcat streams, and take the last N lines
6896 InputStreamReader input = null;
6897 try {
6898 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6899 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6900 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6901
6902 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6903 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6904 input = new InputStreamReader(logcat.getInputStream());
6905
6906 int num;
6907 char[] buf = new char[8192];
6908 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6909 } catch (IOException e) {
6910 Slog.e(TAG, "Error running logcat", e);
6911 } finally {
6912 if (input != null) try { input.close(); } catch (IOException e) {}
6913 }
6914 }
6915
6916 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006917 }
Dan Egnora455d192010-03-12 08:52:28 -08006918 };
6919
6920 if (process == null || process.pid == MY_PID) {
6921 worker.run(); // We may be about to die -- need to run this synchronously
6922 } else {
6923 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006924 }
6925 }
6926
6927 /**
6928 * Bring up the "unexpected error" dialog box for a crashing app.
6929 * Deal with edge cases (intercepts from instrumented applications,
6930 * ActivityController, error intent receivers, that sort of thing).
6931 * @param r the application crashing
6932 * @param crashInfo describing the failure
6933 */
6934 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006935 long timeMillis = System.currentTimeMillis();
6936 String shortMsg = crashInfo.exceptionClassName;
6937 String longMsg = crashInfo.exceptionMessage;
6938 String stackTrace = crashInfo.stackTrace;
6939 if (shortMsg != null && longMsg != null) {
6940 longMsg = shortMsg + ": " + longMsg;
6941 } else if (shortMsg != null) {
6942 longMsg = shortMsg;
6943 }
6944
Dan Egnor60d87622009-12-16 16:32:58 -08006945 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006946 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006947 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006948 try {
6949 String name = r != null ? r.processName : null;
6950 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006951 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006952 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006953 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006954 + " at watcher's request");
6955 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006956 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006957 }
6958 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006959 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006960 }
6961 }
6962
6963 final long origId = Binder.clearCallingIdentity();
6964
6965 // If this process is running instrumentation, finish it.
6966 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006967 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006969 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6970 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 Bundle info = new Bundle();
6972 info.putString("shortMsg", shortMsg);
6973 info.putString("longMsg", longMsg);
6974 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6975 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006976 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006977 }
6978
Dan Egnor60d87622009-12-16 16:32:58 -08006979 // If we can't identify the process or it's already exceeded its crash quota,
6980 // quit right away without showing a crash dialog.
6981 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006982 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006983 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 }
6985
6986 Message msg = Message.obtain();
6987 msg.what = SHOW_ERROR_MSG;
6988 HashMap data = new HashMap();
6989 data.put("result", result);
6990 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006991 msg.obj = data;
6992 mHandler.sendMessage(msg);
6993
6994 Binder.restoreCallingIdentity(origId);
6995 }
6996
6997 int res = result.get();
6998
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006999 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007000 synchronized (this) {
7001 if (r != null) {
7002 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7003 SystemClock.uptimeMillis());
7004 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007005 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007006 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007007 }
7008 }
7009
7010 if (appErrorIntent != null) {
7011 try {
7012 mContext.startActivity(appErrorIntent);
7013 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007014 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007017 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007018
7019 Intent createAppErrorIntentLocked(ProcessRecord r,
7020 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7021 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007022 if (report == null) {
7023 return null;
7024 }
7025 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7026 result.setComponent(r.errorReportReceiver);
7027 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7028 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7029 return result;
7030 }
7031
Dan Egnorb7f03672009-12-09 16:22:32 -08007032 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7033 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007034 if (r.errorReportReceiver == null) {
7035 return null;
7036 }
7037
7038 if (!r.crashing && !r.notResponding) {
7039 return null;
7040 }
7041
Dan Egnorb7f03672009-12-09 16:22:32 -08007042 ApplicationErrorReport report = new ApplicationErrorReport();
7043 report.packageName = r.info.packageName;
7044 report.installerPackageName = r.errorReportReceiver.getPackageName();
7045 report.processName = r.processName;
7046 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007047 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007048
Dan Egnorb7f03672009-12-09 16:22:32 -08007049 if (r.crashing) {
7050 report.type = ApplicationErrorReport.TYPE_CRASH;
7051 report.crashInfo = crashInfo;
7052 } else if (r.notResponding) {
7053 report.type = ApplicationErrorReport.TYPE_ANR;
7054 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007055
Dan Egnorb7f03672009-12-09 16:22:32 -08007056 report.anrInfo.activity = r.notRespondingReport.tag;
7057 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7058 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007059 }
7060
Dan Egnorb7f03672009-12-09 16:22:32 -08007061 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007062 }
7063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7065 // assume our apps are happy - lazy create the list
7066 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7067
7068 synchronized (this) {
7069
7070 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007071 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7072 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7074 // This one's in trouble, so we'll generate a report for it
7075 // crashes are higher priority (in case there's a crash *and* an anr)
7076 ActivityManager.ProcessErrorStateInfo report = null;
7077 if (app.crashing) {
7078 report = app.crashingReport;
7079 } else if (app.notResponding) {
7080 report = app.notRespondingReport;
7081 }
7082
7083 if (report != null) {
7084 if (errList == null) {
7085 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7086 }
7087 errList.add(report);
7088 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007089 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007090 " crashing = " + app.crashing +
7091 " notResponding = " + app.notResponding);
7092 }
7093 }
7094 }
7095 }
7096
7097 return errList;
7098 }
7099
7100 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7101 // Lazy instantiation of list
7102 List<ActivityManager.RunningAppProcessInfo> runList = null;
7103 synchronized (this) {
7104 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007105 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7106 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7108 // Generate process state info for running application
7109 ActivityManager.RunningAppProcessInfo currApp =
7110 new ActivityManager.RunningAppProcessInfo(app.processName,
7111 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007112 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007113 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007114 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007116 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007117 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007118 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7119 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7120 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007121 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7122 } else if (adj >= HOME_APP_ADJ) {
7123 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7124 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007125 } else if (adj >= SECONDARY_SERVER_ADJ) {
7126 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007127 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
7128 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
7129 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7130 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 } else if (adj >= VISIBLE_APP_ADJ) {
7132 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7133 } else {
7134 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7135 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007136 currApp.importanceReasonCode = app.adjTypeCode;
7137 if (app.adjSource instanceof ProcessRecord) {
7138 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007139 } else if (app.adjSource instanceof ActivityRecord) {
7140 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007141 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7142 }
7143 if (app.adjTarget instanceof ComponentName) {
7144 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7145 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007146 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 // + " lru=" + currApp.lru);
7148 if (runList == null) {
7149 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7150 }
7151 runList.add(currApp);
7152 }
7153 }
7154 }
7155 return runList;
7156 }
7157
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007158 public List<ApplicationInfo> getRunningExternalApplications() {
7159 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7160 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7161 if (runningApps != null && runningApps.size() > 0) {
7162 Set<String> extList = new HashSet<String>();
7163 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7164 if (app.pkgList != null) {
7165 for (String pkg : app.pkgList) {
7166 extList.add(pkg);
7167 }
7168 }
7169 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007170 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007171 for (String pkg : extList) {
7172 try {
7173 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7174 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7175 retList.add(info);
7176 }
7177 } catch (RemoteException e) {
7178 }
7179 }
7180 }
7181 return retList;
7182 }
7183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 @Override
7185 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007186 if (checkCallingPermission(android.Manifest.permission.DUMP)
7187 != PackageManager.PERMISSION_GRANTED) {
7188 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7189 + Binder.getCallingPid()
7190 + ", uid=" + Binder.getCallingUid()
7191 + " without permission "
7192 + android.Manifest.permission.DUMP);
7193 return;
7194 }
7195
7196 boolean dumpAll = false;
7197
7198 int opti = 0;
7199 while (opti < args.length) {
7200 String opt = args[opti];
7201 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7202 break;
7203 }
7204 opti++;
7205 if ("-a".equals(opt)) {
7206 dumpAll = true;
7207 } else if ("-h".equals(opt)) {
7208 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007209 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007210 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007211 pw.println(" a[ctivities]: activity stack state");
7212 pw.println(" b[roadcasts]: broadcast state");
7213 pw.println(" i[ntents]: pending intent state");
7214 pw.println(" p[rocesses]: process state");
7215 pw.println(" o[om]: out of memory management");
7216 pw.println(" prov[iders]: content provider state");
7217 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007218 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007220 } else {
7221 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007222 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007223 }
7224
7225 // Is the caller requesting to dump a particular piece of data?
7226 if (opti < args.length) {
7227 String cmd = args[opti];
7228 opti++;
7229 if ("activities".equals(cmd) || "a".equals(cmd)) {
7230 synchronized (this) {
7231 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007233 return;
7234 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7235 synchronized (this) {
7236 dumpBroadcastsLocked(fd, pw, args, opti, true);
7237 }
7238 return;
7239 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7240 synchronized (this) {
7241 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7242 }
7243 return;
7244 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7245 synchronized (this) {
7246 dumpProcessesLocked(fd, pw, args, opti, true);
7247 }
7248 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007249 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7250 synchronized (this) {
7251 dumpOomLocked(fd, pw, args, opti, true);
7252 }
7253 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007254 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7255 synchronized (this) {
7256 dumpProvidersLocked(fd, pw, args, opti, true);
7257 }
7258 return;
7259 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007260 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007261 return;
7262 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7263 synchronized (this) {
7264 dumpServicesLocked(fd, pw, args, opti, true);
7265 }
7266 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007268 }
7269
7270 // No piece of data specified, dump everything.
7271 synchronized (this) {
7272 boolean needSep;
7273 if (dumpAll) {
7274 pw.println("Providers in Current Activity Manager State:");
7275 }
7276 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7277 if (needSep) {
7278 pw.println(" ");
7279 }
7280 if (dumpAll) {
7281 pw.println("-------------------------------------------------------------------------------");
7282 pw.println("Broadcasts in Current Activity Manager State:");
7283 }
7284 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7285 if (needSep) {
7286 pw.println(" ");
7287 }
7288 if (dumpAll) {
7289 pw.println("-------------------------------------------------------------------------------");
7290 pw.println("Services in Current Activity Manager State:");
7291 }
7292 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7293 if (needSep) {
7294 pw.println(" ");
7295 }
7296 if (dumpAll) {
7297 pw.println("-------------------------------------------------------------------------------");
7298 pw.println("PendingIntents in Current Activity Manager State:");
7299 }
7300 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7301 if (needSep) {
7302 pw.println(" ");
7303 }
7304 if (dumpAll) {
7305 pw.println("-------------------------------------------------------------------------------");
7306 pw.println("Activities in Current Activity Manager State:");
7307 }
7308 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7309 if (needSep) {
7310 pw.println(" ");
7311 }
7312 if (dumpAll) {
7313 pw.println("-------------------------------------------------------------------------------");
7314 pw.println("Processes in Current Activity Manager State:");
7315 }
7316 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7317 }
7318 }
7319
7320 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7321 int opti, boolean dumpAll, boolean needHeader) {
7322 if (needHeader) {
7323 pw.println(" Activity stack:");
7324 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007325 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007326 pw.println(" ");
7327 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007328 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7329 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007331 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007332 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007333 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007334 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007336 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007337 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007338 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007339 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007340 pw.println(" ");
7341 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007342 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007345 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007346 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7347 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007348 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007349 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007351 if (dumpAll && mRecentTasks.size() > 0) {
7352 pw.println(" ");
7353 pw.println("Recent tasks in Current Activity Manager State:");
7354
7355 final int N = mRecentTasks.size();
7356 for (int i=0; i<N; i++) {
7357 TaskRecord tr = mRecentTasks.get(i);
7358 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7359 pw.println(tr);
7360 mRecentTasks.get(i).dump(pw, " ");
7361 }
7362 }
7363
7364 pw.println(" ");
7365 pw.println(" mCurTask: " + mCurTask);
7366
7367 return true;
7368 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007369
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007370 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7371 int opti, boolean dumpAll) {
7372 boolean needSep = false;
7373 int numPers = 0;
7374
7375 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7377 final int NA = procs.size();
7378 for (int ia=0; ia<NA; ia++) {
7379 if (!needSep) {
7380 pw.println(" All known processes:");
7381 needSep = true;
7382 }
7383 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007384 pw.print(r.persistent ? " *PERS*" : " *APP*");
7385 pw.print(" UID "); pw.print(procs.keyAt(ia));
7386 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 r.dump(pw, " ");
7388 if (r.persistent) {
7389 numPers++;
7390 }
7391 }
7392 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007393 }
7394
7395 if (mLruProcesses.size() > 0) {
7396 if (needSep) pw.println(" ");
7397 needSep = true;
7398 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007399 dumpProcessOomList(pw, this, mLruProcesses, " ",
7400 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007401 needSep = true;
7402 }
7403
7404 synchronized (mPidsSelfLocked) {
7405 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007406 if (needSep) pw.println(" ");
7407 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007408 pw.println(" PID mappings:");
7409 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7410 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7411 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 }
7413 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007414 }
7415
7416 if (mForegroundProcesses.size() > 0) {
7417 if (needSep) pw.println(" ");
7418 needSep = true;
7419 pw.println(" Foreground Processes:");
7420 for (int i=0; i<mForegroundProcesses.size(); i++) {
7421 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7422 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007424 }
7425
7426 if (mPersistentStartingProcesses.size() > 0) {
7427 if (needSep) pw.println(" ");
7428 needSep = true;
7429 pw.println(" Persisent processes that are starting:");
7430 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007431 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007434 if (mStartingProcesses.size() > 0) {
7435 if (needSep) pw.println(" ");
7436 needSep = true;
7437 pw.println(" Processes that are starting:");
7438 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007439 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007442 if (mRemovedProcesses.size() > 0) {
7443 if (needSep) pw.println(" ");
7444 needSep = true;
7445 pw.println(" Processes that are being removed:");
7446 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007447 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007448 }
7449
7450 if (mProcessesOnHold.size() > 0) {
7451 if (needSep) pw.println(" ");
7452 needSep = true;
7453 pw.println(" Processes that are on old until the system is ready:");
7454 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007455 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457
Dianne Hackborn287952c2010-09-22 22:34:31 -07007458 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007459
7460 if (mProcessCrashTimes.getMap().size() > 0) {
7461 if (needSep) pw.println(" ");
7462 needSep = true;
7463 pw.println(" Time since processes crashed:");
7464 long now = SystemClock.uptimeMillis();
7465 for (Map.Entry<String, SparseArray<Long>> procs
7466 : mProcessCrashTimes.getMap().entrySet()) {
7467 SparseArray<Long> uids = procs.getValue();
7468 final int N = uids.size();
7469 for (int i=0; i<N; i++) {
7470 pw.print(" Process "); pw.print(procs.getKey());
7471 pw.print(" uid "); pw.print(uids.keyAt(i));
7472 pw.print(": last crashed ");
7473 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007474 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007475 }
7476 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007478
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007479 if (mBadProcesses.getMap().size() > 0) {
7480 if (needSep) pw.println(" ");
7481 needSep = true;
7482 pw.println(" Bad processes:");
7483 for (Map.Entry<String, SparseArray<Long>> procs
7484 : mBadProcesses.getMap().entrySet()) {
7485 SparseArray<Long> uids = procs.getValue();
7486 final int N = uids.size();
7487 for (int i=0; i<N; i++) {
7488 pw.print(" Bad process "); pw.print(procs.getKey());
7489 pw.print(" uid "); pw.print(uids.keyAt(i));
7490 pw.print(": crashed at time ");
7491 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 }
7493 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007496 pw.println(" ");
7497 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007498 if (mHeavyWeightProcess != null) {
7499 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7500 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007501 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007502 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007503 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7504 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7505 || mOrigWaitForDebugger) {
7506 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7507 + " mDebugTransient=" + mDebugTransient
7508 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7509 }
7510 if (mAlwaysFinishActivities || mController != null) {
7511 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7512 + " mController=" + mController);
7513 }
7514 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007517 + " mProcessesReady=" + mProcessesReady
7518 + " mSystemReady=" + mSystemReady);
7519 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520 + " mBooted=" + mBooted
7521 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007522 pw.print(" mLastPowerCheckRealtime=");
7523 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7524 pw.println("");
7525 pw.print(" mLastPowerCheckUptime=");
7526 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7527 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007528 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7529 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007530 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007532
7533 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 }
7535
Dianne Hackborn287952c2010-09-22 22:34:31 -07007536 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7537 int opti, boolean needSep, boolean dumpAll) {
7538 if (mProcessesToGc.size() > 0) {
7539 if (needSep) pw.println(" ");
7540 needSep = true;
7541 pw.println(" Processes that are waiting to GC:");
7542 long now = SystemClock.uptimeMillis();
7543 for (int i=0; i<mProcessesToGc.size(); i++) {
7544 ProcessRecord proc = mProcessesToGc.get(i);
7545 pw.print(" Process "); pw.println(proc);
7546 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7547 pw.print(", last gced=");
7548 pw.print(now-proc.lastRequestedGc);
7549 pw.print(" ms ago, last lowMem=");
7550 pw.print(now-proc.lastLowMemory);
7551 pw.println(" ms ago");
7552
7553 }
7554 }
7555 return needSep;
7556 }
7557
7558 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7559 int opti, boolean dumpAll) {
7560 boolean needSep = false;
7561
7562 if (mLruProcesses.size() > 0) {
7563 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7564
7565 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7566 @Override
7567 public int compare(ProcessRecord object1, ProcessRecord object2) {
7568 if (object1.setAdj != object2.setAdj) {
7569 return object1.setAdj > object2.setAdj ? -1 : 1;
7570 }
7571 if (object1.setSchedGroup != object2.setSchedGroup) {
7572 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7573 }
7574 if (object1.keeping != object2.keeping) {
7575 return object1.keeping ? -1 : 1;
7576 }
7577 if (object1.pid != object2.pid) {
7578 return object1.pid > object2.pid ? -1 : 1;
7579 }
7580 return 0;
7581 }
7582 };
7583
7584 Collections.sort(procs, comparator);
7585
7586 if (needSep) pw.println(" ");
7587 needSep = true;
7588 pw.println(" Process OOM control:");
7589 dumpProcessOomList(pw, this, procs, " ",
7590 "Proc", "PERS", true);
7591 needSep = true;
7592 }
7593
7594 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7595
7596 pw.println(" ");
7597 pw.println(" mHomeProcess: " + mHomeProcess);
7598 if (mHeavyWeightProcess != null) {
7599 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7600 }
7601
7602 return true;
7603 }
7604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 /**
7606 * There are three ways to call this:
7607 * - no service specified: dump all the services
7608 * - a flattened component name that matched an existing service was specified as the
7609 * first arg: dump that one service
7610 * - the first arg isn't the flattened component name of an existing service:
7611 * dump all services whose component contains the first arg as a substring
7612 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007613 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7614 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 String[] newArgs;
7616 String componentNameString;
7617 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007618 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 componentNameString = null;
7620 newArgs = EMPTY_STRING_ARRAY;
7621 r = null;
7622 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007623 componentNameString = args[opti];
7624 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007626 synchronized (this) {
7627 r = componentName != null ? mServices.get(componentName) : null;
7628 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007629 newArgs = new String[args.length - opti];
7630 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 }
7632
7633 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007634 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007636 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7637 synchronized (this) {
7638 for (ServiceRecord r1 : mServices.values()) {
7639 if (componentNameString == null
7640 || r1.name.flattenToString().contains(componentNameString)) {
7641 services.add(r1);
7642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 }
7644 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007645 for (int i=0; i<services.size(); i++) {
7646 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 }
7649 }
7650
7651 /**
7652 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7653 * there is a thread associated with the service.
7654 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007655 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7656 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007658 if (dumpAll) {
7659 synchronized (this) {
7660 pw.print(" * "); pw.println(r);
7661 r.dump(pw, " ");
7662 }
7663 pw.println("");
7664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 if (r.app != null && r.app.thread != null) {
7666 try {
7667 // flush anything that is already in the PrintWriter since the thread is going
7668 // to write to the file descriptor directly
7669 pw.flush();
7670 r.app.thread.dumpService(fd, r, args);
7671 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007672 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 } catch (RemoteException e) {
7674 pw.println("got a RemoteException while dumping the service");
7675 }
7676 }
7677 }
7678
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007679 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7680 int opti, boolean dumpAll) {
7681 boolean needSep = false;
7682
7683 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 if (mRegisteredReceivers.size() > 0) {
7685 pw.println(" ");
7686 pw.println(" Registered Receivers:");
7687 Iterator it = mRegisteredReceivers.values().iterator();
7688 while (it.hasNext()) {
7689 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007690 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007691 r.dump(pw, " ");
7692 }
7693 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 pw.println(" ");
7696 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007697 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007698 needSep = true;
7699 }
7700
7701 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7702 || mPendingBroadcast != null) {
7703 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007705 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007707 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7708 pw.println(" Broadcast #" + i + ":");
7709 mParallelBroadcasts.get(i).dump(pw, " ");
7710 }
7711 if (mOrderedBroadcasts.size() > 0) {
7712 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007713 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007714 }
7715 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7716 pw.println(" Serialized Broadcast #" + i + ":");
7717 mOrderedBroadcasts.get(i).dump(pw, " ");
7718 }
7719 pw.println(" ");
7720 pw.println(" Pending broadcast:");
7721 if (mPendingBroadcast != null) {
7722 mPendingBroadcast.dump(pw, " ");
7723 } else {
7724 pw.println(" (null)");
7725 }
7726 needSep = true;
7727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007728
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007731 pw.println(" Historical broadcasts:");
7732 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7733 BroadcastRecord r = mBroadcastHistory[i];
7734 if (r == null) {
7735 break;
7736 }
7737 pw.println(" Historical Broadcast #" + i + ":");
7738 r.dump(pw, " ");
7739 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007740 needSep = true;
7741 }
7742
7743 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007744 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007745 pw.println(" Sticky broadcasts:");
7746 StringBuilder sb = new StringBuilder(128);
7747 for (Map.Entry<String, ArrayList<Intent>> ent
7748 : mStickyBroadcasts.entrySet()) {
7749 pw.print(" * Sticky action "); pw.print(ent.getKey());
7750 pw.println(":");
7751 ArrayList<Intent> intents = ent.getValue();
7752 final int N = intents.size();
7753 for (int i=0; i<N; i++) {
7754 sb.setLength(0);
7755 sb.append(" Intent: ");
7756 intents.get(i).toShortString(sb, true, false);
7757 pw.println(sb.toString());
7758 Bundle bundle = intents.get(i).getExtras();
7759 if (bundle != null) {
7760 pw.print(" ");
7761 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 }
7763 }
7764 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 needSep = true;
7766 }
7767
7768 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007770 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 pw.println(" mHandler:");
7772 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007773 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775
7776 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 }
7778
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007779 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7780 int opti, boolean dumpAll) {
7781 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007783 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007784 if (mServices.size() > 0) {
7785 pw.println(" Active services:");
7786 Iterator<ServiceRecord> it = mServices.values().iterator();
7787 while (it.hasNext()) {
7788 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007789 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 r.dump(pw, " ");
7791 }
7792 needSep = true;
7793 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007796 if (mPendingServices.size() > 0) {
7797 if (needSep) pw.println(" ");
7798 pw.println(" Pending services:");
7799 for (int i=0; i<mPendingServices.size(); i++) {
7800 ServiceRecord r = mPendingServices.get(i);
7801 pw.print(" * Pending "); pw.println(r);
7802 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007804 needSep = true;
7805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007806
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007807 if (mRestartingServices.size() > 0) {
7808 if (needSep) pw.println(" ");
7809 pw.println(" Restarting services:");
7810 for (int i=0; i<mRestartingServices.size(); i++) {
7811 ServiceRecord r = mRestartingServices.get(i);
7812 pw.print(" * Restarting "); pw.println(r);
7813 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007815 needSep = true;
7816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007818 if (mStoppingServices.size() > 0) {
7819 if (needSep) pw.println(" ");
7820 pw.println(" Stopping services:");
7821 for (int i=0; i<mStoppingServices.size(); i++) {
7822 ServiceRecord r = mStoppingServices.get(i);
7823 pw.print(" * Stopping "); pw.println(r);
7824 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007826 needSep = true;
7827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007829 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007830 if (mServiceConnections.size() > 0) {
7831 if (needSep) pw.println(" ");
7832 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007833 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 = mServiceConnections.values().iterator();
7835 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007836 ArrayList<ConnectionRecord> r = it.next();
7837 for (int i=0; i<r.size(); i++) {
7838 pw.print(" * "); pw.println(r.get(i));
7839 r.get(i).dump(pw, " ");
7840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007842 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 }
7844 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007845
7846 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 }
7848
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007849 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7850 int opti, boolean dumpAll) {
7851 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007853 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 if (mProvidersByClass.size() > 0) {
7855 if (needSep) pw.println(" ");
7856 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007857 Iterator<Map.Entry<String, ContentProviderRecord>> it
7858 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007859 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007860 Map.Entry<String, ContentProviderRecord> e = it.next();
7861 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007862 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 r.dump(pw, " ");
7864 }
7865 needSep = true;
7866 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007867
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007868 if (mProvidersByName.size() > 0) {
7869 pw.println(" ");
7870 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007871 Iterator<Map.Entry<String, ContentProviderRecord>> it
7872 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007873 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007874 Map.Entry<String, ContentProviderRecord> e = it.next();
7875 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007876 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7877 pw.println(r);
7878 }
7879 needSep = true;
7880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007882
7883 if (mLaunchingProviders.size() > 0) {
7884 if (needSep) pw.println(" ");
7885 pw.println(" Launching content providers:");
7886 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7887 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7888 pw.println(mLaunchingProviders.get(i));
7889 }
7890 needSep = true;
7891 }
7892
7893 if (mGrantedUriPermissions.size() > 0) {
7894 pw.println();
7895 pw.println("Granted Uri Permissions:");
7896 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7897 int uid = mGrantedUriPermissions.keyAt(i);
7898 HashMap<Uri, UriPermission> perms
7899 = mGrantedUriPermissions.valueAt(i);
7900 pw.print(" * UID "); pw.print(uid);
7901 pw.println(" holds:");
7902 for (UriPermission perm : perms.values()) {
7903 pw.print(" "); pw.println(perm);
7904 perm.dump(pw, " ");
7905 }
7906 }
7907 needSep = true;
7908 }
7909
7910 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 }
7912
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007913 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7914 int opti, boolean dumpAll) {
7915 boolean needSep = false;
7916
7917 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 if (this.mIntentSenderRecords.size() > 0) {
7919 Iterator<WeakReference<PendingIntentRecord>> it
7920 = mIntentSenderRecords.values().iterator();
7921 while (it.hasNext()) {
7922 WeakReference<PendingIntentRecord> ref = it.next();
7923 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007924 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007926 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 rec.dump(pw, " ");
7928 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007929 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007930 }
7931 }
7932 }
7933 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934
7935 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 }
7937
7938 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007939 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 TaskRecord lastTask = null;
7941 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007942 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007943 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 if (lastTask != r.task) {
7945 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007946 pw.print(prefix);
7947 pw.print(full ? "* " : " ");
7948 pw.println(lastTask);
7949 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007950 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007952 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007953 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7954 pw.print(" #"); pw.print(i); pw.print(": ");
7955 pw.println(r);
7956 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007957 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 }
7960 }
7961
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007962 private static String buildOomTag(String prefix, String space, int val, int base) {
7963 if (val == base) {
7964 if (space == null) return prefix;
7965 return prefix + " ";
7966 }
7967 return prefix + "+" + Integer.toString(val-base);
7968 }
7969
7970 private static final int dumpProcessList(PrintWriter pw,
7971 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007972 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007973 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007974 final int N = list.size()-1;
7975 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007977 pw.println(String.format("%s%s #%2d: %s",
7978 prefix, (r.persistent ? persistentLabel : normalLabel),
7979 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 if (r.persistent) {
7981 numPers++;
7982 }
7983 }
7984 return numPers;
7985 }
7986
Dianne Hackborn287952c2010-09-22 22:34:31 -07007987 private static final void dumpProcessOomList(PrintWriter pw,
7988 ActivityManagerService service, List<ProcessRecord> list,
7989 String prefix, String normalLabel, String persistentLabel,
7990 boolean inclDetails) {
7991
7992 final long curRealtime = SystemClock.elapsedRealtime();
7993 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7994 final long curUptime = SystemClock.uptimeMillis();
7995 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7996
7997 final int N = list.size()-1;
7998 for (int i=N; i>=0; i--) {
7999 ProcessRecord r = list.get(i);
8000 String oomAdj;
8001 if (r.setAdj >= EMPTY_APP_ADJ) {
8002 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8003 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8004 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8005 } else if (r.setAdj >= HOME_APP_ADJ) {
8006 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8007 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8008 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8009 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8010 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8011 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8012 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8013 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8014 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8015 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8016 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8017 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8018 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8019 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8020 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8021 } else if (r.setAdj >= SYSTEM_ADJ) {
8022 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8023 } else {
8024 oomAdj = Integer.toString(r.setAdj);
8025 }
8026 String schedGroup;
8027 switch (r.setSchedGroup) {
8028 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8029 schedGroup = "B";
8030 break;
8031 case Process.THREAD_GROUP_DEFAULT:
8032 schedGroup = "F";
8033 break;
8034 default:
8035 schedGroup = Integer.toString(r.setSchedGroup);
8036 break;
8037 }
8038 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8039 prefix, (r.persistent ? persistentLabel : normalLabel),
8040 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8041 if (r.adjSource != null || r.adjTarget != null) {
8042 pw.print(prefix);
8043 pw.print(" ");
8044 if (r.adjTarget instanceof ComponentName) {
8045 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8046 } else if (r.adjTarget != null) {
8047 pw.print(r.adjTarget.toString());
8048 } else {
8049 pw.print("{null}");
8050 }
8051 pw.print("<=");
8052 if (r.adjSource instanceof ProcessRecord) {
8053 pw.print("Proc{");
8054 pw.print(((ProcessRecord)r.adjSource).toShortString());
8055 pw.println("}");
8056 } else if (r.adjSource != null) {
8057 pw.println(r.adjSource.toString());
8058 } else {
8059 pw.println("{null}");
8060 }
8061 }
8062 if (inclDetails) {
8063 pw.print(prefix);
8064 pw.print(" ");
8065 pw.print("oom: max="); pw.print(r.maxAdj);
8066 pw.print(" hidden="); pw.print(r.hiddenAdj);
8067 pw.print(" curRaw="); pw.print(r.curRawAdj);
8068 pw.print(" setRaw="); pw.print(r.setRawAdj);
8069 pw.print(" cur="); pw.print(r.curAdj);
8070 pw.print(" set="); pw.println(r.setAdj);
8071 pw.print(prefix);
8072 pw.print(" ");
8073 pw.print("keeping="); pw.print(r.keeping);
8074 pw.print(" hidden="); pw.print(r.hidden);
8075 pw.print(" empty="); pw.println(r.empty);
8076
8077 if (!r.keeping) {
8078 if (r.lastWakeTime != 0) {
8079 long wtime;
8080 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8081 synchronized (stats) {
8082 wtime = stats.getProcessWakeTime(r.info.uid,
8083 r.pid, curRealtime);
8084 }
8085 long timeUsed = wtime - r.lastWakeTime;
8086 pw.print(prefix);
8087 pw.print(" ");
8088 pw.print("keep awake over ");
8089 TimeUtils.formatDuration(realtimeSince, pw);
8090 pw.print(" used ");
8091 TimeUtils.formatDuration(timeUsed, pw);
8092 pw.print(" (");
8093 pw.print((timeUsed*100)/realtimeSince);
8094 pw.println("%)");
8095 }
8096 if (r.lastCpuTime != 0) {
8097 long timeUsed = r.curCpuTime - r.lastCpuTime;
8098 pw.print(prefix);
8099 pw.print(" ");
8100 pw.print("run cpu over ");
8101 TimeUtils.formatDuration(uptimeSince, pw);
8102 pw.print(" used ");
8103 TimeUtils.formatDuration(timeUsed, pw);
8104 pw.print(" (");
8105 pw.print((timeUsed*100)/uptimeSince);
8106 pw.println("%)");
8107 }
8108 }
8109 }
8110 }
8111 }
8112
Dianne Hackborn472ad872010-04-07 17:31:48 -07008113 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008115 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 long uptime = SystemClock.uptimeMillis();
8117 long realtime = SystemClock.elapsedRealtime();
8118
8119 if (isCheckinRequest) {
8120 // short checkin version
8121 pw.println(uptime + "," + realtime);
8122 pw.flush();
8123 } else {
8124 pw.println("Applications Memory Usage (kB):");
8125 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8126 }
8127 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8128 ProcessRecord r = (ProcessRecord)list.get(i);
8129 if (r.thread != null) {
8130 if (!isCheckinRequest) {
8131 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8132 pw.flush();
8133 }
8134 try {
8135 r.thread.asBinder().dump(fd, args);
8136 } catch (RemoteException e) {
8137 if (!isCheckinRequest) {
8138 pw.println("Got RemoteException!");
8139 pw.flush();
8140 }
8141 }
8142 }
8143 }
8144 }
8145
8146 /**
8147 * Searches array of arguments for the specified string
8148 * @param args array of argument strings
8149 * @param value value to search for
8150 * @return true if the value is contained in the array
8151 */
8152 private static boolean scanArgs(String[] args, String value) {
8153 if (args != null) {
8154 for (String arg : args) {
8155 if (value.equals(arg)) {
8156 return true;
8157 }
8158 }
8159 }
8160 return false;
8161 }
8162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008163 private final void killServicesLocked(ProcessRecord app,
8164 boolean allowRestart) {
8165 // Report disconnected services.
8166 if (false) {
8167 // XXX we are letting the client link to the service for
8168 // death notifications.
8169 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008170 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008172 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008174 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 = r.connections.values().iterator();
8176 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008177 ArrayList<ConnectionRecord> cl = jt.next();
8178 for (int i=0; i<cl.size(); i++) {
8179 ConnectionRecord c = cl.get(i);
8180 if (c.binding.client != app) {
8181 try {
8182 //c.conn.connected(r.className, null);
8183 } catch (Exception e) {
8184 // todo: this should be asynchronous!
8185 Slog.w(TAG, "Exception thrown disconnected servce "
8186 + r.shortName
8187 + " from app " + app.processName, e);
8188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 }
8190 }
8191 }
8192 }
8193 }
8194 }
8195 }
8196
8197 // Clean up any connections this application has to other services.
8198 if (app.connections.size() > 0) {
8199 Iterator<ConnectionRecord> it = app.connections.iterator();
8200 while (it.hasNext()) {
8201 ConnectionRecord r = it.next();
8202 removeConnectionLocked(r, app, null);
8203 }
8204 }
8205 app.connections.clear();
8206
8207 if (app.services.size() != 0) {
8208 // Any services running in the application need to be placed
8209 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008210 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008211 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008212 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008213 synchronized (sr.stats.getBatteryStats()) {
8214 sr.stats.stopLaunchedLocked();
8215 }
8216 sr.app = null;
8217 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008218 if (mStoppingServices.remove(sr)) {
8219 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8220 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008221
8222 boolean hasClients = sr.bindings.size() > 0;
8223 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 Iterator<IntentBindRecord> bindings
8225 = sr.bindings.values().iterator();
8226 while (bindings.hasNext()) {
8227 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008228 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 + ": shouldUnbind=" + b.hasBound);
8230 b.binder = null;
8231 b.requested = b.received = b.hasBound = false;
8232 }
8233 }
8234
8235 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008236 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008237 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008238 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008239 sr.crashCount, sr.shortName, app.pid);
8240 bringDownServiceLocked(sr, true);
8241 } else if (!allowRestart) {
8242 bringDownServiceLocked(sr, true);
8243 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008244 boolean canceled = scheduleServiceRestartLocked(sr, true);
8245
8246 // Should the service remain running? Note that in the
8247 // extreme case of so many attempts to deliver a command
8248 // that it failed, that we also will stop it here.
8249 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8250 if (sr.pendingStarts.size() == 0) {
8251 sr.startRequested = false;
8252 if (!hasClients) {
8253 // Whoops, no reason to restart!
8254 bringDownServiceLocked(sr, true);
8255 }
8256 }
8257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008258 }
8259 }
8260
8261 if (!allowRestart) {
8262 app.services.clear();
8263 }
8264 }
8265
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008266 // Make sure we have no more records on the stopping list.
8267 int i = mStoppingServices.size();
8268 while (i > 0) {
8269 i--;
8270 ServiceRecord sr = mStoppingServices.get(i);
8271 if (sr.app == app) {
8272 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008273 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008274 }
8275 }
8276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 app.executingServices.clear();
8278 }
8279
8280 private final void removeDyingProviderLocked(ProcessRecord proc,
8281 ContentProviderRecord cpr) {
8282 synchronized (cpr) {
8283 cpr.launchingApp = null;
8284 cpr.notifyAll();
8285 }
8286
8287 mProvidersByClass.remove(cpr.info.name);
8288 String names[] = cpr.info.authority.split(";");
8289 for (int j = 0; j < names.length; j++) {
8290 mProvidersByName.remove(names[j]);
8291 }
8292
8293 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8294 while (cit.hasNext()) {
8295 ProcessRecord capp = cit.next();
8296 if (!capp.persistent && capp.thread != null
8297 && capp.pid != 0
8298 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008299 Slog.i(TAG, "Kill " + capp.processName
8300 + " (pid " + capp.pid + "): provider " + cpr.info.name
8301 + " in dying process " + proc.processName);
8302 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8303 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 Process.killProcess(capp.pid);
8305 }
8306 }
8307
8308 mLaunchingProviders.remove(cpr);
8309 }
8310
8311 /**
8312 * Main code for cleaning up a process when it has gone away. This is
8313 * called both as a result of the process dying, or directly when stopping
8314 * a process when running in single process mode.
8315 */
8316 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8317 boolean restarting, int index) {
8318 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008319 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008320 }
8321
Dianne Hackborn36124872009-10-08 16:22:03 -07008322 mProcessesToGc.remove(app);
8323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 // Dismiss any open dialogs.
8325 if (app.crashDialog != null) {
8326 app.crashDialog.dismiss();
8327 app.crashDialog = null;
8328 }
8329 if (app.anrDialog != null) {
8330 app.anrDialog.dismiss();
8331 app.anrDialog = null;
8332 }
8333 if (app.waitDialog != null) {
8334 app.waitDialog.dismiss();
8335 app.waitDialog = null;
8336 }
8337
8338 app.crashing = false;
8339 app.notResponding = false;
8340
8341 app.resetPackageList();
8342 app.thread = null;
8343 app.forcingToForeground = null;
8344 app.foregroundServices = false;
8345
8346 killServicesLocked(app, true);
8347
8348 boolean restart = false;
8349
8350 int NL = mLaunchingProviders.size();
8351
8352 // Remove published content providers.
8353 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008354 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008355 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008356 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 cpr.provider = null;
8358 cpr.app = null;
8359
8360 // See if someone is waiting for this provider... in which
8361 // case we don't remove it, but just let it restart.
8362 int i = 0;
8363 if (!app.bad) {
8364 for (; i<NL; i++) {
8365 if (mLaunchingProviders.get(i) == cpr) {
8366 restart = true;
8367 break;
8368 }
8369 }
8370 } else {
8371 i = NL;
8372 }
8373
8374 if (i >= NL) {
8375 removeDyingProviderLocked(app, cpr);
8376 NL = mLaunchingProviders.size();
8377 }
8378 }
8379 app.pubProviders.clear();
8380 }
8381
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008382 // Take care of any launching providers waiting for this process.
8383 if (checkAppInLaunchingProvidersLocked(app, false)) {
8384 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008387 // Unregister from connected content providers.
8388 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008389 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 while (it.hasNext()) {
8391 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8392 cpr.clients.remove(app);
8393 }
8394 app.conProviders.clear();
8395 }
8396
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008397 // At this point there may be remaining entries in mLaunchingProviders
8398 // where we were the only one waiting, so they are no longer of use.
8399 // Look for these and clean up if found.
8400 // XXX Commented out for now. Trying to figure out a way to reproduce
8401 // the actual situation to identify what is actually going on.
8402 if (false) {
8403 for (int i=0; i<NL; i++) {
8404 ContentProviderRecord cpr = (ContentProviderRecord)
8405 mLaunchingProviders.get(i);
8406 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8407 synchronized (cpr) {
8408 cpr.launchingApp = null;
8409 cpr.notifyAll();
8410 }
8411 }
8412 }
8413 }
8414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 skipCurrentReceiverLocked(app);
8416
8417 // Unregister any receivers.
8418 if (app.receivers.size() > 0) {
8419 Iterator<ReceiverList> it = app.receivers.iterator();
8420 while (it.hasNext()) {
8421 removeReceiverLocked(it.next());
8422 }
8423 app.receivers.clear();
8424 }
8425
Christopher Tate181fafa2009-05-14 11:12:14 -07008426 // If the app is undergoing backup, tell the backup manager about it
8427 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008428 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008429 try {
8430 IBackupManager bm = IBackupManager.Stub.asInterface(
8431 ServiceManager.getService(Context.BACKUP_SERVICE));
8432 bm.agentDisconnected(app.info.packageName);
8433 } catch (RemoteException e) {
8434 // can't happen; backup manager is local
8435 }
8436 }
8437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008438 // If the caller is restarting this app, then leave it in its
8439 // current lists and let the caller take care of it.
8440 if (restarting) {
8441 return;
8442 }
8443
8444 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008445 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008446 "Removing non-persistent process during cleanup: " + app);
8447 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008448 if (mHeavyWeightProcess == app) {
8449 mHeavyWeightProcess = null;
8450 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 } else if (!app.removed) {
8453 // This app is persistent, so we need to keep its record around.
8454 // If it is not already on the pending app list, add it there
8455 // and start a new process for it.
8456 app.thread = null;
8457 app.forcingToForeground = null;
8458 app.foregroundServices = false;
8459 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8460 mPersistentStartingProcesses.add(app);
8461 restart = true;
8462 }
8463 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008464 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8465 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008466 mProcessesOnHold.remove(app);
8467
The Android Open Source Project4df24232009-03-05 14:34:35 -08008468 if (app == mHomeProcess) {
8469 mHomeProcess = null;
8470 }
8471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008472 if (restart) {
8473 // We have components that still need to be running in the
8474 // process, so re-launch it.
8475 mProcessNames.put(app.processName, app.info.uid, app);
8476 startProcessLocked(app, "restart", app.processName);
8477 } else if (app.pid > 0 && app.pid != MY_PID) {
8478 // Goodbye!
8479 synchronized (mPidsSelfLocked) {
8480 mPidsSelfLocked.remove(app.pid);
8481 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8482 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008483 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 }
8485 }
8486
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008487 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8488 // Look through the content providers we are waiting to have launched,
8489 // and if any run in this process then either schedule a restart of
8490 // the process or kill the client waiting for it if this process has
8491 // gone bad.
8492 int NL = mLaunchingProviders.size();
8493 boolean restart = false;
8494 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008495 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008496 if (cpr.launchingApp == app) {
8497 if (!alwaysBad && !app.bad) {
8498 restart = true;
8499 } else {
8500 removeDyingProviderLocked(app, cpr);
8501 NL = mLaunchingProviders.size();
8502 }
8503 }
8504 }
8505 return restart;
8506 }
8507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 // =========================================================
8509 // SERVICES
8510 // =========================================================
8511
8512 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8513 ActivityManager.RunningServiceInfo info =
8514 new ActivityManager.RunningServiceInfo();
8515 info.service = r.name;
8516 if (r.app != null) {
8517 info.pid = r.app.pid;
8518 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008519 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 info.process = r.processName;
8521 info.foreground = r.isForeground;
8522 info.activeSince = r.createTime;
8523 info.started = r.startRequested;
8524 info.clientCount = r.connections.size();
8525 info.crashCount = r.crashCount;
8526 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008527 if (r.isForeground) {
8528 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8529 }
8530 if (r.startRequested) {
8531 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8532 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008533 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008534 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8535 }
8536 if (r.app != null && r.app.persistent) {
8537 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8538 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008539
8540 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8541 for (int i=0; i<connl.size(); i++) {
8542 ConnectionRecord conn = connl.get(i);
8543 if (conn.clientLabel != 0) {
8544 info.clientPackage = conn.binding.client.info.packageName;
8545 info.clientLabel = conn.clientLabel;
8546 return info;
8547 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008548 }
8549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 return info;
8551 }
8552
8553 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8554 int flags) {
8555 synchronized (this) {
8556 ArrayList<ActivityManager.RunningServiceInfo> res
8557 = new ArrayList<ActivityManager.RunningServiceInfo>();
8558
8559 if (mServices.size() > 0) {
8560 Iterator<ServiceRecord> it = mServices.values().iterator();
8561 while (it.hasNext() && res.size() < maxNum) {
8562 res.add(makeRunningServiceInfoLocked(it.next()));
8563 }
8564 }
8565
8566 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8567 ServiceRecord r = mRestartingServices.get(i);
8568 ActivityManager.RunningServiceInfo info =
8569 makeRunningServiceInfoLocked(r);
8570 info.restarting = r.nextRestartTime;
8571 res.add(info);
8572 }
8573
8574 return res;
8575 }
8576 }
8577
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008578 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8579 synchronized (this) {
8580 ServiceRecord r = mServices.get(name);
8581 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008582 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8583 for (int i=0; i<conn.size(); i++) {
8584 if (conn.get(i).clientIntent != null) {
8585 return conn.get(i).clientIntent;
8586 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008587 }
8588 }
8589 }
8590 }
8591 return null;
8592 }
8593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 private final ServiceRecord findServiceLocked(ComponentName name,
8595 IBinder token) {
8596 ServiceRecord r = mServices.get(name);
8597 return r == token ? r : null;
8598 }
8599
8600 private final class ServiceLookupResult {
8601 final ServiceRecord record;
8602 final String permission;
8603
8604 ServiceLookupResult(ServiceRecord _record, String _permission) {
8605 record = _record;
8606 permission = _permission;
8607 }
8608 };
8609
8610 private ServiceLookupResult findServiceLocked(Intent service,
8611 String resolvedType) {
8612 ServiceRecord r = null;
8613 if (service.getComponent() != null) {
8614 r = mServices.get(service.getComponent());
8615 }
8616 if (r == null) {
8617 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8618 r = mServicesByIntent.get(filter);
8619 }
8620
8621 if (r == null) {
8622 try {
8623 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008624 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625 service, resolvedType, 0);
8626 ServiceInfo sInfo =
8627 rInfo != null ? rInfo.serviceInfo : null;
8628 if (sInfo == null) {
8629 return null;
8630 }
8631
8632 ComponentName name = new ComponentName(
8633 sInfo.applicationInfo.packageName, sInfo.name);
8634 r = mServices.get(name);
8635 } catch (RemoteException ex) {
8636 // pm is in same process, this will never happen.
8637 }
8638 }
8639 if (r != null) {
8640 int callingPid = Binder.getCallingPid();
8641 int callingUid = Binder.getCallingUid();
8642 if (checkComponentPermission(r.permission,
8643 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8644 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008645 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008646 + " from pid=" + callingPid
8647 + ", uid=" + callingUid
8648 + " requires " + r.permission);
8649 return new ServiceLookupResult(null, r.permission);
8650 }
8651 return new ServiceLookupResult(r, null);
8652 }
8653 return null;
8654 }
8655
8656 private class ServiceRestarter implements Runnable {
8657 private ServiceRecord mService;
8658
8659 void setService(ServiceRecord service) {
8660 mService = service;
8661 }
8662
8663 public void run() {
8664 synchronized(ActivityManagerService.this) {
8665 performServiceRestartLocked(mService);
8666 }
8667 }
8668 }
8669
8670 private ServiceLookupResult retrieveServiceLocked(Intent service,
8671 String resolvedType, int callingPid, int callingUid) {
8672 ServiceRecord r = null;
8673 if (service.getComponent() != null) {
8674 r = mServices.get(service.getComponent());
8675 }
8676 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8677 r = mServicesByIntent.get(filter);
8678 if (r == null) {
8679 try {
8680 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008681 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008682 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 ServiceInfo sInfo =
8684 rInfo != null ? rInfo.serviceInfo : null;
8685 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008686 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 ": not found");
8688 return null;
8689 }
8690
8691 ComponentName name = new ComponentName(
8692 sInfo.applicationInfo.packageName, sInfo.name);
8693 r = mServices.get(name);
8694 if (r == null) {
8695 filter = new Intent.FilterComparison(service.cloneFilter());
8696 ServiceRestarter res = new ServiceRestarter();
8697 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8698 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8699 synchronized (stats) {
8700 ss = stats.getServiceStatsLocked(
8701 sInfo.applicationInfo.uid, sInfo.packageName,
8702 sInfo.name);
8703 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008704 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 res.setService(r);
8706 mServices.put(name, r);
8707 mServicesByIntent.put(filter, r);
8708
8709 // Make sure this component isn't in the pending list.
8710 int N = mPendingServices.size();
8711 for (int i=0; i<N; i++) {
8712 ServiceRecord pr = mPendingServices.get(i);
8713 if (pr.name.equals(name)) {
8714 mPendingServices.remove(i);
8715 i--;
8716 N--;
8717 }
8718 }
8719 }
8720 } catch (RemoteException ex) {
8721 // pm is in same process, this will never happen.
8722 }
8723 }
8724 if (r != null) {
8725 if (checkComponentPermission(r.permission,
8726 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8727 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008728 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008729 + " from pid=" + Binder.getCallingPid()
8730 + ", uid=" + Binder.getCallingUid()
8731 + " requires " + r.permission);
8732 return new ServiceLookupResult(null, r.permission);
8733 }
8734 return new ServiceLookupResult(r, null);
8735 }
8736 return null;
8737 }
8738
Dianne Hackborn287952c2010-09-22 22:34:31 -07008739 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8740 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8741 + why + " of " + r + " in app " + r.app);
8742 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8743 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008744 long now = SystemClock.uptimeMillis();
8745 if (r.executeNesting == 0 && r.app != null) {
8746 if (r.app.executingServices.size() == 0) {
8747 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8748 msg.obj = r.app;
8749 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8750 }
8751 r.app.executingServices.add(r);
8752 }
8753 r.executeNesting++;
8754 r.executingStart = now;
8755 }
8756
8757 private final void sendServiceArgsLocked(ServiceRecord r,
8758 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008759 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008760 if (N == 0) {
8761 return;
8762 }
8763
Dianne Hackborn39792d22010-08-19 18:01:52 -07008764 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008766 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008767 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8768 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008769 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008770 // If somehow we got a dummy start at the front, then
8771 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008772 continue;
8773 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008774 si.deliveredTime = SystemClock.uptimeMillis();
8775 r.deliveredStarts.add(si);
8776 si.deliveryCount++;
8777 if (si.targetPermissionUid >= 0) {
8778 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008779 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008780 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008781 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 if (!oomAdjusted) {
8783 oomAdjusted = true;
8784 updateOomAdjLocked(r.app);
8785 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008786 int flags = 0;
8787 if (si.deliveryCount > 0) {
8788 flags |= Service.START_FLAG_RETRY;
8789 }
8790 if (si.doneExecutingCount > 0) {
8791 flags |= Service.START_FLAG_REDELIVERY;
8792 }
8793 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008794 } catch (RemoteException e) {
8795 // Remote process gone... we'll let the normal cleanup take
8796 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008797 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008798 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008800 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 break;
8802 }
8803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 }
8805
8806 private final boolean requestServiceBindingLocked(ServiceRecord r,
8807 IntentBindRecord i, boolean rebind) {
8808 if (r.app == null || r.app.thread == null) {
8809 // If service is not currently running, can't yet bind.
8810 return false;
8811 }
8812 if ((!i.requested || rebind) && i.apps.size() > 0) {
8813 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008814 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008815 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8816 if (!rebind) {
8817 i.requested = true;
8818 }
8819 i.hasBound = true;
8820 i.doRebind = false;
8821 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008822 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008823 return false;
8824 }
8825 }
8826 return true;
8827 }
8828
8829 private final void requestServiceBindingsLocked(ServiceRecord r) {
8830 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8831 while (bindings.hasNext()) {
8832 IntentBindRecord i = bindings.next();
8833 if (!requestServiceBindingLocked(r, i, false)) {
8834 break;
8835 }
8836 }
8837 }
8838
8839 private final void realStartServiceLocked(ServiceRecord r,
8840 ProcessRecord app) throws RemoteException {
8841 if (app.thread == null) {
8842 throw new RemoteException();
8843 }
8844
8845 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008846 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008847
8848 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008849 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008850 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008851
8852 boolean created = false;
8853 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008854 mStringBuilder.setLength(0);
8855 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008856 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008857 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008858 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 synchronized (r.stats.getBatteryStats()) {
8860 r.stats.startLaunchedLocked();
8861 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008862 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008863 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008864 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 created = true;
8866 } finally {
8867 if (!created) {
8868 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008869 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 }
8871 }
8872
8873 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008874
8875 // If the service is in the started state, and there are no
8876 // pending arguments, then fake up one so its onStartCommand() will
8877 // be called.
8878 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8879 r.lastStartId++;
8880 if (r.lastStartId < 1) {
8881 r.lastStartId = 1;
8882 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008883 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008884 }
8885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 sendServiceArgsLocked(r, true);
8887 }
8888
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008889 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8890 boolean allowCancel) {
8891 boolean canceled = false;
8892
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008893 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008894 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008895 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008896
8897 // Any delivered but not yet finished starts should be put back
8898 // on the pending list.
8899 final int N = r.deliveredStarts.size();
8900 if (N > 0) {
8901 for (int i=N-1; i>=0; i--) {
8902 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008903 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008904 if (si.intent == null) {
8905 // We'll generate this again if needed.
8906 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8907 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8908 r.pendingStarts.add(0, si);
8909 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8910 dur *= 2;
8911 if (minDuration < dur) minDuration = dur;
8912 if (resetTime < dur) resetTime = dur;
8913 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008914 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008915 + r.name);
8916 canceled = true;
8917 }
8918 }
8919 r.deliveredStarts.clear();
8920 }
8921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008922 r.totalRestartCount++;
8923 if (r.restartDelay == 0) {
8924 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008925 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 } else {
8927 // If it has been a "reasonably long time" since the service
8928 // was started, then reset our restart duration back to
8929 // the beginning, so we don't infinitely increase the duration
8930 // on a service that just occasionally gets killed (which is
8931 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008932 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008934 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008936 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008937 if (r.restartDelay < minDuration) {
8938 r.restartDelay = minDuration;
8939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008940 }
8941 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008942
8943 r.nextRestartTime = now + r.restartDelay;
8944
8945 // Make sure that we don't end up restarting a bunch of services
8946 // all at the same time.
8947 boolean repeat;
8948 do {
8949 repeat = false;
8950 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8951 ServiceRecord r2 = mRestartingServices.get(i);
8952 if (r2 != r && r.nextRestartTime
8953 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8954 && r.nextRestartTime
8955 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8956 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8957 r.restartDelay = r.nextRestartTime - now;
8958 repeat = true;
8959 break;
8960 }
8961 }
8962 } while (repeat);
8963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 if (!mRestartingServices.contains(r)) {
8965 mRestartingServices.add(r);
8966 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008967
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008968 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008971 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008972 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008973 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008974 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008975 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 r.shortName, r.restartDelay);
8977
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008978 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 }
8980
8981 final void performServiceRestartLocked(ServiceRecord r) {
8982 if (!mRestartingServices.contains(r)) {
8983 return;
8984 }
8985 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8986 }
8987
8988 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8989 if (r.restartDelay == 0) {
8990 return false;
8991 }
8992 r.resetRestartCounter();
8993 mRestartingServices.remove(r);
8994 mHandler.removeCallbacks(r.restarter);
8995 return true;
8996 }
8997
8998 private final boolean bringUpServiceLocked(ServiceRecord r,
8999 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009000 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 //r.dump(" ");
9002
Dianne Hackborn36124872009-10-08 16:22:03 -07009003 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009004 sendServiceArgsLocked(r, false);
9005 return true;
9006 }
9007
9008 if (!whileRestarting && r.restartDelay > 0) {
9009 // If waiting for a restart, then do nothing.
9010 return true;
9011 }
9012
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009013 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009014
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009015 // We are now bringing the service up, so no longer in the
9016 // restarting state.
9017 mRestartingServices.remove(r);
9018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009019 final String appName = r.processName;
9020 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9021 if (app != null && app.thread != null) {
9022 try {
9023 realStartServiceLocked(r, app);
9024 return true;
9025 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 }
9028
9029 // If a dead object exception was thrown -- fall through to
9030 // restart the application.
9031 }
9032
Dianne Hackborn36124872009-10-08 16:22:03 -07009033 // Not running -- get it started, and enqueue this service record
9034 // to be executed when the app comes up.
9035 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9036 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009037 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009038 + r.appInfo.packageName + "/"
9039 + r.appInfo.uid + " for service "
9040 + r.intent.getIntent() + ": process is bad");
9041 bringDownServiceLocked(r, true);
9042 return false;
9043 }
9044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 mPendingServices.add(r);
9047 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 return true;
9050 }
9051
9052 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009053 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 //r.dump(" ");
9055
9056 // Does it still need to run?
9057 if (!force && r.startRequested) {
9058 return;
9059 }
9060 if (r.connections.size() > 0) {
9061 if (!force) {
9062 // XXX should probably keep a count of the number of auto-create
9063 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009064 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009065 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009066 ArrayList<ConnectionRecord> cr = it.next();
9067 for (int i=0; i<cr.size(); i++) {
9068 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9069 return;
9070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 }
9072 }
9073 }
9074
9075 // Report to all of the connections that the service is no longer
9076 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009077 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009078 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009079 ArrayList<ConnectionRecord> c = it.next();
9080 for (int i=0; i<c.size(); i++) {
9081 try {
9082 c.get(i).conn.connected(r.name, null);
9083 } catch (Exception e) {
9084 Slog.w(TAG, "Failure disconnecting service " + r.name +
9085 " to connection " + c.get(i).conn.asBinder() +
9086 " (in " + c.get(i).binding.client.processName + ")", e);
9087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 }
9089 }
9090 }
9091
9092 // Tell the service that it has been unbound.
9093 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9094 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9095 while (it.hasNext()) {
9096 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009097 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 + ": hasBound=" + ibr.hasBound);
9099 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9100 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009101 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 updateOomAdjLocked(r.app);
9103 ibr.hasBound = false;
9104 r.app.thread.scheduleUnbindService(r,
9105 ibr.intent.getIntent());
9106 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009107 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 + r.shortName, e);
9109 serviceDoneExecutingLocked(r, true);
9110 }
9111 }
9112 }
9113 }
9114
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009115 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009116 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009117 System.identityHashCode(r), r.shortName,
9118 (r.app != null) ? r.app.pid : -1);
9119
9120 mServices.remove(r.name);
9121 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122 r.totalRestartCount = 0;
9123 unscheduleServiceRestartLocked(r);
9124
9125 // Also make sure it is not on the pending list.
9126 int N = mPendingServices.size();
9127 for (int i=0; i<N; i++) {
9128 if (mPendingServices.get(i) == r) {
9129 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009130 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009131 i--;
9132 N--;
9133 }
9134 }
9135
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009136 r.cancelNotification();
9137 r.isForeground = false;
9138 r.foregroundId = 0;
9139 r.foregroundNoti = null;
9140
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009141 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009142 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009143 r.pendingStarts.clear();
9144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 if (r.app != null) {
9146 synchronized (r.stats.getBatteryStats()) {
9147 r.stats.stopLaunchedLocked();
9148 }
9149 r.app.services.remove(r);
9150 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009152 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 mStoppingServices.add(r);
9154 updateOomAdjLocked(r.app);
9155 r.app.thread.scheduleStopService(r);
9156 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009157 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 + r.shortName, e);
9159 serviceDoneExecutingLocked(r, true);
9160 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009161 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009162 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009163 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009164 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 }
9166 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009167 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009168 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009169 }
9170 }
9171
9172 ComponentName startServiceLocked(IApplicationThread caller,
9173 Intent service, String resolvedType,
9174 int callingPid, int callingUid) {
9175 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009176 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 + " type=" + resolvedType + " args=" + service.getExtras());
9178
9179 if (caller != null) {
9180 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9181 if (callerApp == null) {
9182 throw new SecurityException(
9183 "Unable to find app for caller " + caller
9184 + " (pid=" + Binder.getCallingPid()
9185 + ") when starting service " + service);
9186 }
9187 }
9188
9189 ServiceLookupResult res =
9190 retrieveServiceLocked(service, resolvedType,
9191 callingPid, callingUid);
9192 if (res == null) {
9193 return null;
9194 }
9195 if (res.record == null) {
9196 return new ComponentName("!", res.permission != null
9197 ? res.permission : "private to package");
9198 }
9199 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009200 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9201 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009203 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 }
9205 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009206 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 r.lastStartId++;
9208 if (r.lastStartId < 1) {
9209 r.lastStartId = 1;
9210 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009211 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9212 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 r.lastActivity = SystemClock.uptimeMillis();
9214 synchronized (r.stats.getBatteryStats()) {
9215 r.stats.startRunningLocked();
9216 }
9217 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9218 return new ComponentName("!", "Service process is bad");
9219 }
9220 return r.name;
9221 }
9222 }
9223
9224 public ComponentName startService(IApplicationThread caller, Intent service,
9225 String resolvedType) {
9226 // Refuse possible leaked file descriptors
9227 if (service != null && service.hasFileDescriptors() == true) {
9228 throw new IllegalArgumentException("File descriptors passed in Intent");
9229 }
9230
9231 synchronized(this) {
9232 final int callingPid = Binder.getCallingPid();
9233 final int callingUid = Binder.getCallingUid();
9234 final long origId = Binder.clearCallingIdentity();
9235 ComponentName res = startServiceLocked(caller, service,
9236 resolvedType, callingPid, callingUid);
9237 Binder.restoreCallingIdentity(origId);
9238 return res;
9239 }
9240 }
9241
9242 ComponentName startServiceInPackage(int uid,
9243 Intent service, String resolvedType) {
9244 synchronized(this) {
9245 final long origId = Binder.clearCallingIdentity();
9246 ComponentName res = startServiceLocked(null, service,
9247 resolvedType, -1, uid);
9248 Binder.restoreCallingIdentity(origId);
9249 return res;
9250 }
9251 }
9252
9253 public int stopService(IApplicationThread caller, Intent service,
9254 String resolvedType) {
9255 // Refuse possible leaked file descriptors
9256 if (service != null && service.hasFileDescriptors() == true) {
9257 throw new IllegalArgumentException("File descriptors passed in Intent");
9258 }
9259
9260 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009261 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 + " type=" + resolvedType);
9263
9264 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9265 if (caller != null && callerApp == null) {
9266 throw new SecurityException(
9267 "Unable to find app for caller " + caller
9268 + " (pid=" + Binder.getCallingPid()
9269 + ") when stopping service " + service);
9270 }
9271
9272 // If this service is active, make sure it is stopped.
9273 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9274 if (r != null) {
9275 if (r.record != null) {
9276 synchronized (r.record.stats.getBatteryStats()) {
9277 r.record.stats.stopRunningLocked();
9278 }
9279 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009280 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 final long origId = Binder.clearCallingIdentity();
9282 bringDownServiceLocked(r.record, false);
9283 Binder.restoreCallingIdentity(origId);
9284 return 1;
9285 }
9286 return -1;
9287 }
9288 }
9289
9290 return 0;
9291 }
9292
9293 public IBinder peekService(Intent service, String resolvedType) {
9294 // Refuse possible leaked file descriptors
9295 if (service != null && service.hasFileDescriptors() == true) {
9296 throw new IllegalArgumentException("File descriptors passed in Intent");
9297 }
9298
9299 IBinder ret = null;
9300
9301 synchronized(this) {
9302 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9303
9304 if (r != null) {
9305 // r.record is null if findServiceLocked() failed the caller permission check
9306 if (r.record == null) {
9307 throw new SecurityException(
9308 "Permission Denial: Accessing service " + r.record.name
9309 + " from pid=" + Binder.getCallingPid()
9310 + ", uid=" + Binder.getCallingUid()
9311 + " requires " + r.permission);
9312 }
9313 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9314 if (ib != null) {
9315 ret = ib.binder;
9316 }
9317 }
9318 }
9319
9320 return ret;
9321 }
9322
9323 public boolean stopServiceToken(ComponentName className, IBinder token,
9324 int startId) {
9325 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009326 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009327 + " " + token + " startId=" + startId);
9328 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009329 if (r != null) {
9330 if (startId >= 0) {
9331 // Asked to only stop if done with all work. Note that
9332 // to avoid leaks, we will take this as dropping all
9333 // start items up to and including this one.
9334 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9335 if (si != null) {
9336 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009337 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9338 cur.removeUriPermissionsLocked();
9339 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009340 break;
9341 }
9342 }
9343 }
9344
9345 if (r.lastStartId != startId) {
9346 return false;
9347 }
9348
9349 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009350 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009351 + " is last, but have " + r.deliveredStarts.size()
9352 + " remaining args");
9353 }
9354 }
9355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009356 synchronized (r.stats.getBatteryStats()) {
9357 r.stats.stopRunningLocked();
9358 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009359 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 }
9361 final long origId = Binder.clearCallingIdentity();
9362 bringDownServiceLocked(r, false);
9363 Binder.restoreCallingIdentity(origId);
9364 return true;
9365 }
9366 }
9367 return false;
9368 }
9369
9370 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009371 int id, Notification notification, boolean removeNotification) {
9372 final long origId = Binder.clearCallingIdentity();
9373 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 synchronized(this) {
9375 ServiceRecord r = findServiceLocked(className, token);
9376 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009377 if (id != 0) {
9378 if (notification == null) {
9379 throw new IllegalArgumentException("null notification");
9380 }
9381 if (r.foregroundId != id) {
9382 r.cancelNotification();
9383 r.foregroundId = id;
9384 }
9385 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9386 r.foregroundNoti = notification;
9387 r.isForeground = true;
9388 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 if (r.app != null) {
9390 updateServiceForegroundLocked(r.app, true);
9391 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009392 } else {
9393 if (r.isForeground) {
9394 r.isForeground = false;
9395 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009396 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009397 updateServiceForegroundLocked(r.app, true);
9398 }
9399 }
9400 if (removeNotification) {
9401 r.cancelNotification();
9402 r.foregroundId = 0;
9403 r.foregroundNoti = null;
9404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 }
9406 }
9407 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009408 } finally {
9409 Binder.restoreCallingIdentity(origId);
9410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 }
9412
9413 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9414 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009415 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 if (sr.isForeground) {
9417 anyForeground = true;
9418 break;
9419 }
9420 }
9421 if (anyForeground != proc.foregroundServices) {
9422 proc.foregroundServices = anyForeground;
9423 if (oomAdj) {
9424 updateOomAdjLocked();
9425 }
9426 }
9427 }
9428
9429 public int bindService(IApplicationThread caller, IBinder token,
9430 Intent service, String resolvedType,
9431 IServiceConnection connection, int flags) {
9432 // Refuse possible leaked file descriptors
9433 if (service != null && service.hasFileDescriptors() == true) {
9434 throw new IllegalArgumentException("File descriptors passed in Intent");
9435 }
9436
9437 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009438 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009439 + " type=" + resolvedType + " conn=" + connection.asBinder()
9440 + " flags=0x" + Integer.toHexString(flags));
9441 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9442 if (callerApp == null) {
9443 throw new SecurityException(
9444 "Unable to find app for caller " + caller
9445 + " (pid=" + Binder.getCallingPid()
9446 + ") when binding service " + service);
9447 }
9448
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009449 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009450 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009451 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009453 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 return 0;
9455 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009456 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009457 }
9458
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009459 int clientLabel = 0;
9460 PendingIntent clientIntent = null;
9461
9462 if (callerApp.info.uid == Process.SYSTEM_UID) {
9463 // Hacky kind of thing -- allow system stuff to tell us
9464 // what they are, so we can report this elsewhere for
9465 // others to know why certain services are running.
9466 try {
9467 clientIntent = (PendingIntent)service.getParcelableExtra(
9468 Intent.EXTRA_CLIENT_INTENT);
9469 } catch (RuntimeException e) {
9470 }
9471 if (clientIntent != null) {
9472 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9473 if (clientLabel != 0) {
9474 // There are no useful extras in the intent, trash them.
9475 // System code calling with this stuff just needs to know
9476 // this will happen.
9477 service = service.cloneFilter();
9478 }
9479 }
9480 }
9481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482 ServiceLookupResult res =
9483 retrieveServiceLocked(service, resolvedType,
9484 Binder.getCallingPid(), Binder.getCallingUid());
9485 if (res == null) {
9486 return 0;
9487 }
9488 if (res.record == null) {
9489 return -1;
9490 }
9491 ServiceRecord s = res.record;
9492
9493 final long origId = Binder.clearCallingIdentity();
9494
9495 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009496 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009497 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 }
9499
9500 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9501 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009502 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503
9504 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009505 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9506 if (clist == null) {
9507 clist = new ArrayList<ConnectionRecord>();
9508 s.connections.put(binder, clist);
9509 }
9510 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511 b.connections.add(c);
9512 if (activity != null) {
9513 if (activity.connections == null) {
9514 activity.connections = new HashSet<ConnectionRecord>();
9515 }
9516 activity.connections.add(c);
9517 }
9518 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009519 clist = mServiceConnections.get(binder);
9520 if (clist == null) {
9521 clist = new ArrayList<ConnectionRecord>();
9522 mServiceConnections.put(binder, clist);
9523 }
9524 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009525
9526 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9527 s.lastActivity = SystemClock.uptimeMillis();
9528 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9529 return 0;
9530 }
9531 }
9532
9533 if (s.app != null) {
9534 // This could have made the service more important.
9535 updateOomAdjLocked(s.app);
9536 }
9537
Joe Onorato8a9b2202010-02-26 18:56:32 -08009538 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 + ": received=" + b.intent.received
9540 + " apps=" + b.intent.apps.size()
9541 + " doRebind=" + b.intent.doRebind);
9542
9543 if (s.app != null && b.intent.received) {
9544 // Service is already running, so we can immediately
9545 // publish the connection.
9546 try {
9547 c.conn.connected(s.name, b.intent.binder);
9548 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009549 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 + " to connection " + c.conn.asBinder()
9551 + " (in " + c.binding.client.processName + ")", e);
9552 }
9553
9554 // If this is the first app connected back to this binding,
9555 // and the service had previously asked to be told when
9556 // rebound, then do so.
9557 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9558 requestServiceBindingLocked(s, b.intent, true);
9559 }
9560 } else if (!b.intent.requested) {
9561 requestServiceBindingLocked(s, b.intent, false);
9562 }
9563
9564 Binder.restoreCallingIdentity(origId);
9565 }
9566
9567 return 1;
9568 }
9569
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009570 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009571 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 IBinder binder = c.conn.asBinder();
9573 AppBindRecord b = c.binding;
9574 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009575 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9576 if (clist != null) {
9577 clist.remove(c);
9578 if (clist.size() == 0) {
9579 s.connections.remove(binder);
9580 }
9581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 b.connections.remove(c);
9583 if (c.activity != null && c.activity != skipAct) {
9584 if (c.activity.connections != null) {
9585 c.activity.connections.remove(c);
9586 }
9587 }
9588 if (b.client != skipApp) {
9589 b.client.connections.remove(c);
9590 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009591 clist = mServiceConnections.get(binder);
9592 if (clist != null) {
9593 clist.remove(c);
9594 if (clist.size() == 0) {
9595 mServiceConnections.remove(binder);
9596 }
9597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598
9599 if (b.connections.size() == 0) {
9600 b.intent.apps.remove(b.client);
9601 }
9602
Joe Onorato8a9b2202010-02-26 18:56:32 -08009603 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 + ": shouldUnbind=" + b.intent.hasBound);
9605 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9606 && b.intent.hasBound) {
9607 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009608 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009609 updateOomAdjLocked(s.app);
9610 b.intent.hasBound = false;
9611 // Assume the client doesn't want to know about a rebind;
9612 // we will deal with that later if it asks for one.
9613 b.intent.doRebind = false;
9614 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9615 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009616 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009617 serviceDoneExecutingLocked(s, true);
9618 }
9619 }
9620
9621 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9622 bringDownServiceLocked(s, false);
9623 }
9624 }
9625
9626 public boolean unbindService(IServiceConnection connection) {
9627 synchronized (this) {
9628 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009629 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009630 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9631 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009632 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 + connection.asBinder());
9634 return false;
9635 }
9636
9637 final long origId = Binder.clearCallingIdentity();
9638
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009639 while (clist.size() > 0) {
9640 ConnectionRecord r = clist.get(0);
9641 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009643 if (r.binding.service.app != null) {
9644 // This could have made the service less important.
9645 updateOomAdjLocked(r.binding.service.app);
9646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009647 }
9648
9649 Binder.restoreCallingIdentity(origId);
9650 }
9651
9652 return true;
9653 }
9654
9655 public void publishService(IBinder token, Intent intent, IBinder service) {
9656 // Refuse possible leaked file descriptors
9657 if (intent != null && intent.hasFileDescriptors() == true) {
9658 throw new IllegalArgumentException("File descriptors passed in Intent");
9659 }
9660
9661 synchronized(this) {
9662 if (!(token instanceof ServiceRecord)) {
9663 throw new IllegalArgumentException("Invalid service token");
9664 }
9665 ServiceRecord r = (ServiceRecord)token;
9666
9667 final long origId = Binder.clearCallingIdentity();
9668
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009669 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 + " " + intent + ": " + service);
9671 if (r != null) {
9672 Intent.FilterComparison filter
9673 = new Intent.FilterComparison(intent);
9674 IntentBindRecord b = r.bindings.get(filter);
9675 if (b != null && !b.received) {
9676 b.binder = service;
9677 b.requested = true;
9678 b.received = true;
9679 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009680 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681 = r.connections.values().iterator();
9682 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009683 ArrayList<ConnectionRecord> clist = it.next();
9684 for (int i=0; i<clist.size(); i++) {
9685 ConnectionRecord c = clist.get(i);
9686 if (!filter.equals(c.binding.intent.intent)) {
9687 if (DEBUG_SERVICE) Slog.v(
9688 TAG, "Not publishing to: " + c);
9689 if (DEBUG_SERVICE) Slog.v(
9690 TAG, "Bound intent: " + c.binding.intent.intent);
9691 if (DEBUG_SERVICE) Slog.v(
9692 TAG, "Published intent: " + intent);
9693 continue;
9694 }
9695 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9696 try {
9697 c.conn.connected(r.name, service);
9698 } catch (Exception e) {
9699 Slog.w(TAG, "Failure sending service " + r.name +
9700 " to connection " + c.conn.asBinder() +
9701 " (in " + c.binding.client.processName + ")", e);
9702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 }
9704 }
9705 }
9706 }
9707
9708 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9709
9710 Binder.restoreCallingIdentity(origId);
9711 }
9712 }
9713 }
9714
9715 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9716 // Refuse possible leaked file descriptors
9717 if (intent != null && intent.hasFileDescriptors() == true) {
9718 throw new IllegalArgumentException("File descriptors passed in Intent");
9719 }
9720
9721 synchronized(this) {
9722 if (!(token instanceof ServiceRecord)) {
9723 throw new IllegalArgumentException("Invalid service token");
9724 }
9725 ServiceRecord r = (ServiceRecord)token;
9726
9727 final long origId = Binder.clearCallingIdentity();
9728
9729 if (r != null) {
9730 Intent.FilterComparison filter
9731 = new Intent.FilterComparison(intent);
9732 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009733 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009734 + " at " + b + ": apps="
9735 + (b != null ? b.apps.size() : 0));
9736 if (b != null) {
9737 if (b.apps.size() > 0) {
9738 // Applications have already bound since the last
9739 // unbind, so just rebind right here.
9740 requestServiceBindingLocked(r, b, true);
9741 } else {
9742 // Note to tell the service the next time there is
9743 // a new client.
9744 b.doRebind = true;
9745 }
9746 }
9747
9748 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9749
9750 Binder.restoreCallingIdentity(origId);
9751 }
9752 }
9753 }
9754
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009755 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756 synchronized(this) {
9757 if (!(token instanceof ServiceRecord)) {
9758 throw new IllegalArgumentException("Invalid service token");
9759 }
9760 ServiceRecord r = (ServiceRecord)token;
9761 boolean inStopping = mStoppingServices.contains(token);
9762 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009763 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009764 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 + " with incorrect token: given " + token
9766 + ", expected " + r);
9767 return;
9768 }
9769
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009770 if (type == 1) {
9771 // This is a call from a service start... take care of
9772 // book-keeping.
9773 r.callStart = true;
9774 switch (res) {
9775 case Service.START_STICKY_COMPATIBILITY:
9776 case Service.START_STICKY: {
9777 // We are done with the associated start arguments.
9778 r.findDeliveredStart(startId, true);
9779 // Don't stop if killed.
9780 r.stopIfKilled = false;
9781 break;
9782 }
9783 case Service.START_NOT_STICKY: {
9784 // We are done with the associated start arguments.
9785 r.findDeliveredStart(startId, true);
9786 if (r.lastStartId == startId) {
9787 // There is no more work, and this service
9788 // doesn't want to hang around if killed.
9789 r.stopIfKilled = true;
9790 }
9791 break;
9792 }
9793 case Service.START_REDELIVER_INTENT: {
9794 // We'll keep this item until they explicitly
9795 // call stop for it, but keep track of the fact
9796 // that it was delivered.
9797 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9798 if (si != null) {
9799 si.deliveryCount = 0;
9800 si.doneExecutingCount++;
9801 // Don't stop if killed.
9802 r.stopIfKilled = true;
9803 }
9804 break;
9805 }
9806 default:
9807 throw new IllegalArgumentException(
9808 "Unknown service start result: " + res);
9809 }
9810 if (res == Service.START_STICKY_COMPATIBILITY) {
9811 r.callStart = false;
9812 }
9813 }
9814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009815 final long origId = Binder.clearCallingIdentity();
9816 serviceDoneExecutingLocked(r, inStopping);
9817 Binder.restoreCallingIdentity(origId);
9818 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009819 Slog.w(TAG, "Done executing unknown service from pid "
9820 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 }
9822 }
9823 }
9824
9825 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009826 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9827 + ": nesting=" + r.executeNesting
9828 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009829 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 r.executeNesting--;
9831 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009832 if (DEBUG_SERVICE) Slog.v(TAG,
9833 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009834 r.app.executingServices.remove(r);
9835 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009836 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9837 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009838 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9839 }
9840 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009841 if (DEBUG_SERVICE) Slog.v(TAG,
9842 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 mStoppingServices.remove(r);
9844 }
9845 updateOomAdjLocked(r.app);
9846 }
9847 }
9848
9849 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009850 String anrMessage = null;
9851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 synchronized(this) {
9853 if (proc.executingServices.size() == 0 || proc.thread == null) {
9854 return;
9855 }
9856 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9857 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9858 ServiceRecord timeout = null;
9859 long nextTime = 0;
9860 while (it.hasNext()) {
9861 ServiceRecord sr = it.next();
9862 if (sr.executingStart < maxTime) {
9863 timeout = sr;
9864 break;
9865 }
9866 if (sr.executingStart > nextTime) {
9867 nextTime = sr.executingStart;
9868 }
9869 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009870 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009871 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009872 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 } else {
9874 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9875 msg.obj = proc;
9876 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9877 }
9878 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009879
9880 if (anrMessage != null) {
9881 appNotResponding(proc, null, null, anrMessage);
9882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 }
9884
9885 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009886 // BACKUP AND RESTORE
9887 // =========================================================
9888
9889 // Cause the target app to be launched if necessary and its backup agent
9890 // instantiated. The backup agent will invoke backupAgentCreated() on the
9891 // activity manager to announce its creation.
9892 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009893 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009894 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9895
9896 synchronized(this) {
9897 // !!! TODO: currently no check here that we're already bound
9898 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9899 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9900 synchronized (stats) {
9901 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9902 }
9903
9904 BackupRecord r = new BackupRecord(ss, app, backupMode);
9905 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9906 // startProcessLocked() returns existing proc's record if it's already running
9907 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009908 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009909 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009910 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009911 return false;
9912 }
9913
9914 r.app = proc;
9915 mBackupTarget = r;
9916 mBackupAppName = app.packageName;
9917
Christopher Tate6fa95972009-06-05 18:43:55 -07009918 // Try not to kill the process during backup
9919 updateOomAdjLocked(proc);
9920
Christopher Tate181fafa2009-05-14 11:12:14 -07009921 // If the process is already attached, schedule the creation of the backup agent now.
9922 // If it is not yet live, this will be done when it attaches to the framework.
9923 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009924 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009925 try {
9926 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9927 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009928 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009929 }
9930 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009931 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009932 }
9933 // Invariants: at this point, the target app process exists and the application
9934 // is either already running or in the process of coming up. mBackupTarget and
9935 // mBackupAppName describe the app, so that when it binds back to the AM we
9936 // know that it's scheduled for a backup-agent operation.
9937 }
9938
9939 return true;
9940 }
9941
9942 // A backup agent has just come up
9943 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009944 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009945 + " = " + agent);
9946
9947 synchronized(this) {
9948 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009949 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009950 return;
9951 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009952 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009953
Dianne Hackborn06740692010-09-22 22:46:21 -07009954 long oldIdent = Binder.clearCallingIdentity();
9955 try {
9956 IBackupManager bm = IBackupManager.Stub.asInterface(
9957 ServiceManager.getService(Context.BACKUP_SERVICE));
9958 bm.agentConnected(agentPackageName, agent);
9959 } catch (RemoteException e) {
9960 // can't happen; the backup manager service is local
9961 } catch (Exception e) {
9962 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9963 e.printStackTrace();
9964 } finally {
9965 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009966 }
9967 }
9968
9969 // done with this agent
9970 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009971 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009972 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009973 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009974 return;
9975 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009976
9977 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009978 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009979 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009980 return;
9981 }
9982
Christopher Tate181fafa2009-05-14 11:12:14 -07009983 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009984 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009985 return;
9986 }
9987
Christopher Tate6fa95972009-06-05 18:43:55 -07009988 ProcessRecord proc = mBackupTarget.app;
9989 mBackupTarget = null;
9990 mBackupAppName = null;
9991
9992 // Not backing this app up any more; reset its OOM adjustment
9993 updateOomAdjLocked(proc);
9994
Christopher Tatec7b31e32009-06-10 15:49:30 -07009995 // If the app crashed during backup, 'thread' will be null here
9996 if (proc.thread != null) {
9997 try {
9998 proc.thread.scheduleDestroyBackupAgent(appInfo);
9999 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010000 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010001 e.printStackTrace();
10002 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010003 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010004 }
10005 }
10006 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010007 // BROADCASTS
10008 // =========================================================
10009
Josh Bartel7f208742010-02-25 11:01:44 -060010010 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 List cur) {
10012 final ContentResolver resolver = mContext.getContentResolver();
10013 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10014 if (list == null) {
10015 return cur;
10016 }
10017 int N = list.size();
10018 for (int i=0; i<N; i++) {
10019 Intent intent = list.get(i);
10020 if (filter.match(resolver, intent, true, TAG) >= 0) {
10021 if (cur == null) {
10022 cur = new ArrayList<Intent>();
10023 }
10024 cur.add(intent);
10025 }
10026 }
10027 return cur;
10028 }
10029
10030 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010031 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 + mBroadcastsScheduled);
10033
10034 if (mBroadcastsScheduled) {
10035 return;
10036 }
10037 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10038 mBroadcastsScheduled = true;
10039 }
10040
10041 public Intent registerReceiver(IApplicationThread caller,
10042 IIntentReceiver receiver, IntentFilter filter, String permission) {
10043 synchronized(this) {
10044 ProcessRecord callerApp = null;
10045 if (caller != null) {
10046 callerApp = getRecordForAppLocked(caller);
10047 if (callerApp == null) {
10048 throw new SecurityException(
10049 "Unable to find app for caller " + caller
10050 + " (pid=" + Binder.getCallingPid()
10051 + ") when registering receiver " + receiver);
10052 }
10053 }
10054
10055 List allSticky = null;
10056
10057 // Look for any matching sticky broadcasts...
10058 Iterator actions = filter.actionsIterator();
10059 if (actions != null) {
10060 while (actions.hasNext()) {
10061 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010062 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010063 }
10064 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010065 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 }
10067
10068 // The first sticky in the list is returned directly back to
10069 // the client.
10070 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10071
Joe Onorato8a9b2202010-02-26 18:56:32 -080010072 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010073 + ": " + sticky);
10074
10075 if (receiver == null) {
10076 return sticky;
10077 }
10078
10079 ReceiverList rl
10080 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10081 if (rl == null) {
10082 rl = new ReceiverList(this, callerApp,
10083 Binder.getCallingPid(),
10084 Binder.getCallingUid(), receiver);
10085 if (rl.app != null) {
10086 rl.app.receivers.add(rl);
10087 } else {
10088 try {
10089 receiver.asBinder().linkToDeath(rl, 0);
10090 } catch (RemoteException e) {
10091 return sticky;
10092 }
10093 rl.linkedToDeath = true;
10094 }
10095 mRegisteredReceivers.put(receiver.asBinder(), rl);
10096 }
10097 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10098 rl.add(bf);
10099 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010100 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 }
10102 mReceiverResolver.addFilter(bf);
10103
10104 // Enqueue broadcasts for all existing stickies that match
10105 // this filter.
10106 if (allSticky != null) {
10107 ArrayList receivers = new ArrayList();
10108 receivers.add(bf);
10109
10110 int N = allSticky.size();
10111 for (int i=0; i<N; i++) {
10112 Intent intent = (Intent)allSticky.get(i);
10113 BroadcastRecord r = new BroadcastRecord(intent, null,
10114 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010115 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010116 if (mParallelBroadcasts.size() == 0) {
10117 scheduleBroadcastsLocked();
10118 }
10119 mParallelBroadcasts.add(r);
10120 }
10121 }
10122
10123 return sticky;
10124 }
10125 }
10126
10127 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010128 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129
10130 boolean doNext = false;
10131
10132 synchronized(this) {
10133 ReceiverList rl
10134 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10135 if (rl != null) {
10136 if (rl.curBroadcast != null) {
10137 BroadcastRecord r = rl.curBroadcast;
10138 doNext = finishReceiverLocked(
10139 receiver.asBinder(), r.resultCode, r.resultData,
10140 r.resultExtras, r.resultAbort, true);
10141 }
10142
10143 if (rl.app != null) {
10144 rl.app.receivers.remove(rl);
10145 }
10146 removeReceiverLocked(rl);
10147 if (rl.linkedToDeath) {
10148 rl.linkedToDeath = false;
10149 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10150 }
10151 }
10152 }
10153
10154 if (!doNext) {
10155 return;
10156 }
10157
10158 final long origId = Binder.clearCallingIdentity();
10159 processNextBroadcast(false);
10160 trimApplications();
10161 Binder.restoreCallingIdentity(origId);
10162 }
10163
10164 void removeReceiverLocked(ReceiverList rl) {
10165 mRegisteredReceivers.remove(rl.receiver.asBinder());
10166 int N = rl.size();
10167 for (int i=0; i<N; i++) {
10168 mReceiverResolver.removeFilter(rl.get(i));
10169 }
10170 }
10171
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010172 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10173 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10174 ProcessRecord r = mLruProcesses.get(i);
10175 if (r.thread != null) {
10176 try {
10177 r.thread.dispatchPackageBroadcast(cmd, packages);
10178 } catch (RemoteException ex) {
10179 }
10180 }
10181 }
10182 }
10183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184 private final int broadcastIntentLocked(ProcessRecord callerApp,
10185 String callerPackage, Intent intent, String resolvedType,
10186 IIntentReceiver resultTo, int resultCode, String resultData,
10187 Bundle map, String requiredPermission,
10188 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10189 intent = new Intent(intent);
10190
Joe Onorato8a9b2202010-02-26 18:56:32 -080010191 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10193 + " ordered=" + ordered);
10194 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010195 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 }
10197
10198 // Handle special intents: if this broadcast is from the package
10199 // manager about a package being removed, we need to remove all of
10200 // its activities from the history stack.
10201 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10202 intent.getAction());
10203 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10204 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010205 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 || uidRemoved) {
10207 if (checkComponentPermission(
10208 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10209 callingPid, callingUid, -1)
10210 == PackageManager.PERMISSION_GRANTED) {
10211 if (uidRemoved) {
10212 final Bundle intentExtras = intent.getExtras();
10213 final int uid = intentExtras != null
10214 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10215 if (uid >= 0) {
10216 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10217 synchronized (bs) {
10218 bs.removeUidStatsLocked(uid);
10219 }
10220 }
10221 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010222 // If resources are unvailble just force stop all
10223 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010224 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010225 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10226 if (list != null && (list.length > 0)) {
10227 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010228 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010229 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010230 sendPackageBroadcastLocked(
10231 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010232 }
10233 } else {
10234 Uri data = intent.getData();
10235 String ssp;
10236 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10237 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10238 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010239 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010240 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010241 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10242 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10243 new String[] {ssp});
10244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 }
10246 }
10247 }
10248 } else {
10249 String msg = "Permission Denial: " + intent.getAction()
10250 + " broadcast from " + callerPackage + " (pid=" + callingPid
10251 + ", uid=" + callingUid + ")"
10252 + " requires "
10253 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010254 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010255 throw new SecurityException(msg);
10256 }
10257 }
10258
10259 /*
10260 * If this is the time zone changed action, queue up a message that will reset the timezone
10261 * of all currently running processes. This message will get queued up before the broadcast
10262 * happens.
10263 */
10264 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10265 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10266 }
10267
Dianne Hackborn854060af2009-07-09 18:14:31 -070010268 /*
10269 * Prevent non-system code (defined here to be non-persistent
10270 * processes) from sending protected broadcasts.
10271 */
10272 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10273 || callingUid == Process.SHELL_UID || callingUid == 0) {
10274 // Always okay.
10275 } else if (callerApp == null || !callerApp.persistent) {
10276 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010277 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010278 intent.getAction())) {
10279 String msg = "Permission Denial: not allowed to send broadcast "
10280 + intent.getAction() + " from pid="
10281 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010282 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010283 throw new SecurityException(msg);
10284 }
10285 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010286 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010287 return BROADCAST_SUCCESS;
10288 }
10289 }
10290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 // Add to the sticky list if requested.
10292 if (sticky) {
10293 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10294 callingPid, callingUid)
10295 != PackageManager.PERMISSION_GRANTED) {
10296 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10297 + callingPid + ", uid=" + callingUid
10298 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010299 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 throw new SecurityException(msg);
10301 }
10302 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 + " and enforce permission " + requiredPermission);
10305 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10306 }
10307 if (intent.getComponent() != null) {
10308 throw new SecurityException(
10309 "Sticky broadcasts can't target a specific component");
10310 }
10311 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10312 if (list == null) {
10313 list = new ArrayList<Intent>();
10314 mStickyBroadcasts.put(intent.getAction(), list);
10315 }
10316 int N = list.size();
10317 int i;
10318 for (i=0; i<N; i++) {
10319 if (intent.filterEquals(list.get(i))) {
10320 // This sticky already exists, replace it.
10321 list.set(i, new Intent(intent));
10322 break;
10323 }
10324 }
10325 if (i >= N) {
10326 list.add(new Intent(intent));
10327 }
10328 }
10329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010330 // Figure out who all will receive this broadcast.
10331 List receivers = null;
10332 List<BroadcastFilter> registeredReceivers = null;
10333 try {
10334 if (intent.getComponent() != null) {
10335 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010336 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010337 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 if (ai != null) {
10339 receivers = new ArrayList();
10340 ResolveInfo ri = new ResolveInfo();
10341 ri.activityInfo = ai;
10342 receivers.add(ri);
10343 }
10344 } else {
10345 // Need to resolve the intent to interested receivers...
10346 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10347 == 0) {
10348 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010349 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010350 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 }
Mihai Preda074edef2009-05-18 17:13:31 +020010352 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 }
10354 } catch (RemoteException ex) {
10355 // pm is in same process, this will never happen.
10356 }
10357
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010358 final boolean replacePending =
10359 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10360
Joe Onorato8a9b2202010-02-26 18:56:32 -080010361 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010362 + " replacePending=" + replacePending);
10363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10365 if (!ordered && NR > 0) {
10366 // If we are not serializing this broadcast, then send the
10367 // registered receivers separately so they don't wait for the
10368 // components to be launched.
10369 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10370 callerPackage, callingPid, callingUid, requiredPermission,
10371 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010372 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010373 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010374 TAG, "Enqueueing parallel broadcast " + r
10375 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010376 boolean replaced = false;
10377 if (replacePending) {
10378 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10379 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010381 "***** DROPPING PARALLEL: " + intent);
10382 mParallelBroadcasts.set(i, r);
10383 replaced = true;
10384 break;
10385 }
10386 }
10387 }
10388 if (!replaced) {
10389 mParallelBroadcasts.add(r);
10390 scheduleBroadcastsLocked();
10391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 registeredReceivers = null;
10393 NR = 0;
10394 }
10395
10396 // Merge into one list.
10397 int ir = 0;
10398 if (receivers != null) {
10399 // A special case for PACKAGE_ADDED: do not allow the package
10400 // being added to see this broadcast. This prevents them from
10401 // using this as a back door to get run as soon as they are
10402 // installed. Maybe in the future we want to have a special install
10403 // broadcast or such for apps, but we'd like to deliberately make
10404 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010405 String skipPackages[] = null;
10406 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10407 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10408 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10409 Uri data = intent.getData();
10410 if (data != null) {
10411 String pkgName = data.getSchemeSpecificPart();
10412 if (pkgName != null) {
10413 skipPackages = new String[] { pkgName };
10414 }
10415 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010416 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010417 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010418 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010419 if (skipPackages != null && (skipPackages.length > 0)) {
10420 for (String skipPackage : skipPackages) {
10421 if (skipPackage != null) {
10422 int NT = receivers.size();
10423 for (int it=0; it<NT; it++) {
10424 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10425 if (curt.activityInfo.packageName.equals(skipPackage)) {
10426 receivers.remove(it);
10427 it--;
10428 NT--;
10429 }
10430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010431 }
10432 }
10433 }
10434
10435 int NT = receivers != null ? receivers.size() : 0;
10436 int it = 0;
10437 ResolveInfo curt = null;
10438 BroadcastFilter curr = null;
10439 while (it < NT && ir < NR) {
10440 if (curt == null) {
10441 curt = (ResolveInfo)receivers.get(it);
10442 }
10443 if (curr == null) {
10444 curr = registeredReceivers.get(ir);
10445 }
10446 if (curr.getPriority() >= curt.priority) {
10447 // Insert this broadcast record into the final list.
10448 receivers.add(it, curr);
10449 ir++;
10450 curr = null;
10451 it++;
10452 NT++;
10453 } else {
10454 // Skip to the next ResolveInfo in the final list.
10455 it++;
10456 curt = null;
10457 }
10458 }
10459 }
10460 while (ir < NR) {
10461 if (receivers == null) {
10462 receivers = new ArrayList();
10463 }
10464 receivers.add(registeredReceivers.get(ir));
10465 ir++;
10466 }
10467
10468 if ((receivers != null && receivers.size() > 0)
10469 || resultTo != null) {
10470 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10471 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010472 receivers, resultTo, resultCode, resultData, map, ordered,
10473 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010474 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 TAG, "Enqueueing ordered broadcast " + r
10476 + ": prev had " + mOrderedBroadcasts.size());
10477 if (DEBUG_BROADCAST) {
10478 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010479 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010480 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010481 boolean replaced = false;
10482 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010483 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010484 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010485 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010486 "***** DROPPING ORDERED: " + intent);
10487 mOrderedBroadcasts.set(i, r);
10488 replaced = true;
10489 break;
10490 }
10491 }
10492 }
10493 if (!replaced) {
10494 mOrderedBroadcasts.add(r);
10495 scheduleBroadcastsLocked();
10496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 }
10498
10499 return BROADCAST_SUCCESS;
10500 }
10501
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010502 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010503 // Refuse possible leaked file descriptors
10504 if (intent != null && intent.hasFileDescriptors() == true) {
10505 throw new IllegalArgumentException("File descriptors passed in Intent");
10506 }
10507
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010508 int flags = intent.getFlags();
10509
10510 if (!mProcessesReady) {
10511 // if the caller really truly claims to know what they're doing, go
10512 // ahead and allow the broadcast without launching any receivers
10513 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10514 intent = new Intent(intent);
10515 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10516 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10517 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10518 + " before boot completion");
10519 throw new IllegalStateException("Cannot broadcast before boot completed");
10520 }
10521 }
10522
10523 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10524 throw new IllegalArgumentException(
10525 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10526 }
10527
10528 return intent;
10529 }
10530
10531 public final int broadcastIntent(IApplicationThread caller,
10532 Intent intent, String resolvedType, IIntentReceiver resultTo,
10533 int resultCode, String resultData, Bundle map,
10534 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010536 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10539 final int callingPid = Binder.getCallingPid();
10540 final int callingUid = Binder.getCallingUid();
10541 final long origId = Binder.clearCallingIdentity();
10542 int res = broadcastIntentLocked(callerApp,
10543 callerApp != null ? callerApp.info.packageName : null,
10544 intent, resolvedType, resultTo,
10545 resultCode, resultData, map, requiredPermission, serialized,
10546 sticky, callingPid, callingUid);
10547 Binder.restoreCallingIdentity(origId);
10548 return res;
10549 }
10550 }
10551
10552 int broadcastIntentInPackage(String packageName, int uid,
10553 Intent intent, String resolvedType, IIntentReceiver resultTo,
10554 int resultCode, String resultData, Bundle map,
10555 String requiredPermission, boolean serialized, boolean sticky) {
10556 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010557 intent = verifyBroadcastLocked(intent);
10558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 final long origId = Binder.clearCallingIdentity();
10560 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10561 resultTo, resultCode, resultData, map, requiredPermission,
10562 serialized, sticky, -1, uid);
10563 Binder.restoreCallingIdentity(origId);
10564 return res;
10565 }
10566 }
10567
10568 public final void unbroadcastIntent(IApplicationThread caller,
10569 Intent intent) {
10570 // Refuse possible leaked file descriptors
10571 if (intent != null && intent.hasFileDescriptors() == true) {
10572 throw new IllegalArgumentException("File descriptors passed in Intent");
10573 }
10574
10575 synchronized(this) {
10576 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10577 != PackageManager.PERMISSION_GRANTED) {
10578 String msg = "Permission Denial: unbroadcastIntent() from pid="
10579 + Binder.getCallingPid()
10580 + ", uid=" + Binder.getCallingUid()
10581 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010582 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 throw new SecurityException(msg);
10584 }
10585 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10586 if (list != null) {
10587 int N = list.size();
10588 int i;
10589 for (i=0; i<N; i++) {
10590 if (intent.filterEquals(list.get(i))) {
10591 list.remove(i);
10592 break;
10593 }
10594 }
10595 }
10596 }
10597 }
10598
10599 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10600 String resultData, Bundle resultExtras, boolean resultAbort,
10601 boolean explicit) {
10602 if (mOrderedBroadcasts.size() == 0) {
10603 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010604 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 }
10606 return false;
10607 }
10608 BroadcastRecord r = mOrderedBroadcasts.get(0);
10609 if (r.receiver == null) {
10610 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 }
10613 return false;
10614 }
10615 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010616 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010617 return false;
10618 }
10619 int state = r.state;
10620 r.state = r.IDLE;
10621 if (state == r.IDLE) {
10622 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010623 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010624 }
10625 }
10626 r.receiver = null;
10627 r.intent.setComponent(null);
10628 if (r.curApp != null) {
10629 r.curApp.curReceiver = null;
10630 }
10631 if (r.curFilter != null) {
10632 r.curFilter.receiverList.curBroadcast = null;
10633 }
10634 r.curFilter = null;
10635 r.curApp = null;
10636 r.curComponent = null;
10637 r.curReceiver = null;
10638 mPendingBroadcast = null;
10639
10640 r.resultCode = resultCode;
10641 r.resultData = resultData;
10642 r.resultExtras = resultExtras;
10643 r.resultAbort = resultAbort;
10644
10645 // We will process the next receiver right now if this is finishing
10646 // an app receiver (which is always asynchronous) or after we have
10647 // come back from calling a receiver.
10648 return state == BroadcastRecord.APP_RECEIVE
10649 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10650 }
10651
10652 public void finishReceiver(IBinder who, int resultCode, String resultData,
10653 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010654 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655
10656 // Refuse possible leaked file descriptors
10657 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10658 throw new IllegalArgumentException("File descriptors passed in Bundle");
10659 }
10660
10661 boolean doNext;
10662
10663 final long origId = Binder.clearCallingIdentity();
10664
10665 synchronized(this) {
10666 doNext = finishReceiverLocked(
10667 who, resultCode, resultData, resultExtras, resultAbort, true);
10668 }
10669
10670 if (doNext) {
10671 processNextBroadcast(false);
10672 }
10673 trimApplications();
10674
10675 Binder.restoreCallingIdentity(origId);
10676 }
10677
Jeff Brown4d94a762010-09-23 11:33:28 -070010678 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 if (r.nextReceiver > 0) {
10680 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10681 if (curReceiver instanceof BroadcastFilter) {
10682 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010683 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010684 System.identityHashCode(r),
10685 r.intent.getAction(),
10686 r.nextReceiver - 1,
10687 System.identityHashCode(bf));
10688 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010689 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010690 System.identityHashCode(r),
10691 r.intent.getAction(),
10692 r.nextReceiver - 1,
10693 ((ResolveInfo)curReceiver).toString());
10694 }
10695 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010696 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010698 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010699 System.identityHashCode(r),
10700 r.intent.getAction(),
10701 r.nextReceiver,
10702 "NONE");
10703 }
10704 }
10705
Jeff Brown4d94a762010-09-23 11:33:28 -070010706 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10707 if (! mPendingBroadcastTimeoutMessage) {
10708 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10709 mHandler.sendMessageAtTime(msg, timeoutTime);
10710 mPendingBroadcastTimeoutMessage = true;
10711 }
10712 }
10713
10714 private final void cancelBroadcastTimeoutLocked() {
10715 if (mPendingBroadcastTimeoutMessage) {
10716 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10717 mPendingBroadcastTimeoutMessage = false;
10718 }
10719 }
10720
10721 private final void broadcastTimeoutLocked(boolean fromMsg) {
10722 if (fromMsg) {
10723 mPendingBroadcastTimeoutMessage = false;
10724 }
10725
10726 if (mOrderedBroadcasts.size() == 0) {
10727 return;
10728 }
10729
10730 long now = SystemClock.uptimeMillis();
10731 BroadcastRecord r = mOrderedBroadcasts.get(0);
10732 if (fromMsg) {
10733 if (mDidDexOpt) {
10734 // Delay timeouts until dexopt finishes.
10735 mDidDexOpt = false;
10736 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10737 setBroadcastTimeoutLocked(timeoutTime);
10738 return;
10739 }
10740 if (! mProcessesReady) {
10741 // Only process broadcast timeouts if the system is ready. That way
10742 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10743 // to do heavy lifting for system up.
10744 return;
10745 }
10746
10747 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10748 if (timeoutTime > now) {
10749 // We can observe premature timeouts because we do not cancel and reset the
10750 // broadcast timeout message after each receiver finishes. Instead, we set up
10751 // an initial timeout then kick it down the road a little further as needed
10752 // when it expires.
10753 if (DEBUG_BROADCAST) Slog.v(TAG,
10754 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10755 + timeoutTime);
10756 setBroadcastTimeoutLocked(timeoutTime);
10757 return;
10758 }
10759 }
10760
10761 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10762 + ", started " + (now - r.receiverTime) + "ms ago");
10763 r.receiverTime = now;
10764 r.anrCount++;
10765
10766 // Current receiver has passed its expiration date.
10767 if (r.nextReceiver <= 0) {
10768 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10769 return;
10770 }
10771
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010772 ProcessRecord app = null;
10773 String anrMessage = null;
10774
Jeff Brown4d94a762010-09-23 11:33:28 -070010775 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10776 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10777 logBroadcastReceiverDiscardLocked(r);
10778 if (curReceiver instanceof BroadcastFilter) {
10779 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10780 if (bf.receiverList.pid != 0
10781 && bf.receiverList.pid != MY_PID) {
10782 synchronized (this.mPidsSelfLocked) {
10783 app = this.mPidsSelfLocked.get(
10784 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010787 } else {
10788 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010790
Jeff Brown4d94a762010-09-23 11:33:28 -070010791 if (app != null) {
10792 anrMessage = "Broadcast of " + r.intent.toString();
10793 }
10794
10795 if (mPendingBroadcast == r) {
10796 mPendingBroadcast = null;
10797 }
10798
10799 // Move on to the next receiver.
10800 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10801 r.resultExtras, r.resultAbort, true);
10802 scheduleBroadcastsLocked();
10803
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010804 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010805 // Post the ANR to the handler since we do not want to process ANRs while
10806 // potentially holding our lock.
10807 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010809 }
10810
10811 private final void processCurBroadcastLocked(BroadcastRecord r,
10812 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010813 if (DEBUG_BROADCAST) Slog.v(TAG,
10814 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010815 if (app.thread == null) {
10816 throw new RemoteException();
10817 }
10818 r.receiver = app.thread.asBinder();
10819 r.curApp = app;
10820 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010821 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822
10823 // Tell the application to launch this receiver.
10824 r.intent.setComponent(r.curComponent);
10825
10826 boolean started = false;
10827 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010828 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 "Delivering to component " + r.curComponent
10830 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010831 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10833 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010834 if (DEBUG_BROADCAST) Slog.v(TAG,
10835 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 started = true;
10837 } finally {
10838 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010839 if (DEBUG_BROADCAST) Slog.v(TAG,
10840 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 r.receiver = null;
10842 r.curApp = null;
10843 app.curReceiver = null;
10844 }
10845 }
10846
10847 }
10848
Jeff Brown4d94a762010-09-23 11:33:28 -070010849 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010850 Intent intent, int resultCode, String data, Bundle extras,
10851 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010852 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 if (app != null && app.thread != null) {
10854 // If we have an app thread, do the call through that so it is
10855 // correctly ordered with other one-way calls.
10856 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010857 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010859 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 }
10861 }
10862
Jeff Brown4d94a762010-09-23 11:33:28 -070010863 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 BroadcastFilter filter, boolean ordered) {
10865 boolean skip = false;
10866 if (filter.requiredPermission != null) {
10867 int perm = checkComponentPermission(filter.requiredPermission,
10868 r.callingPid, r.callingUid, -1);
10869 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010870 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 + r.intent.toString()
10872 + " from " + r.callerPackage + " (pid="
10873 + r.callingPid + ", uid=" + r.callingUid + ")"
10874 + " requires " + filter.requiredPermission
10875 + " due to registered receiver " + filter);
10876 skip = true;
10877 }
10878 }
10879 if (r.requiredPermission != null) {
10880 int perm = checkComponentPermission(r.requiredPermission,
10881 filter.receiverList.pid, filter.receiverList.uid, -1);
10882 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 + r.intent.toString()
10885 + " to " + filter.receiverList.app
10886 + " (pid=" + filter.receiverList.pid
10887 + ", uid=" + filter.receiverList.uid + ")"
10888 + " requires " + r.requiredPermission
10889 + " due to sender " + r.callerPackage
10890 + " (uid " + r.callingUid + ")");
10891 skip = true;
10892 }
10893 }
10894
10895 if (!skip) {
10896 // If this is not being sent as an ordered broadcast, then we
10897 // don't want to touch the fields that keep track of the current
10898 // state of ordered broadcasts.
10899 if (ordered) {
10900 r.receiver = filter.receiverList.receiver.asBinder();
10901 r.curFilter = filter;
10902 filter.receiverList.curBroadcast = r;
10903 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010904 if (filter.receiverList.app != null) {
10905 // Bump hosting application to no longer be in background
10906 // scheduling class. Note that we can't do that if there
10907 // isn't an app... but we can only be in that case for
10908 // things that directly call the IActivityManager API, which
10909 // are already core system stuff so don't matter for this.
10910 r.curApp = filter.receiverList.app;
10911 filter.receiverList.app.curReceiver = r;
10912 updateOomAdjLocked();
10913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 }
10915 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010916 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010918 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010919 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010921 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010923 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 if (ordered) {
10925 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10926 }
10927 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010928 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 if (ordered) {
10930 r.receiver = null;
10931 r.curFilter = null;
10932 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010933 if (filter.receiverList.app != null) {
10934 filter.receiverList.app.curReceiver = null;
10935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 }
10937 }
10938 }
10939 }
10940
Dianne Hackborn12527f92009-11-11 17:39:50 -080010941 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10942 if (r.callingUid < 0) {
10943 // This was from a registerReceiver() call; ignore it.
10944 return;
10945 }
10946 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10947 MAX_BROADCAST_HISTORY-1);
10948 r.finishTime = SystemClock.uptimeMillis();
10949 mBroadcastHistory[0] = r;
10950 }
10951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 private final void processNextBroadcast(boolean fromMsg) {
10953 synchronized(this) {
10954 BroadcastRecord r;
10955
Joe Onorato8a9b2202010-02-26 18:56:32 -080010956 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010958 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959
10960 updateCpuStats();
10961
10962 if (fromMsg) {
10963 mBroadcastsScheduled = false;
10964 }
10965
10966 // First, deliver any non-serialized broadcasts right away.
10967 while (mParallelBroadcasts.size() > 0) {
10968 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010969 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010971 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010972 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 for (int i=0; i<N; i++) {
10974 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010975 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010976 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010978 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010980 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010981 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010982 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 }
10984
10985 // Now take care of the next serialized one...
10986
10987 // If we are waiting for a process to come up to handle the next
10988 // broadcast, then do nothing at this point. Just in case, we
10989 // check that the process we're waiting for still exists.
10990 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010991 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010992 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010993 + mPendingBroadcast.curApp);
10994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995
10996 boolean isDead;
10997 synchronized (mPidsSelfLocked) {
10998 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10999 }
11000 if (!isDead) {
11001 // It's still alive, so keep waiting
11002 return;
11003 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011004 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011006 mPendingBroadcast.state = BroadcastRecord.IDLE;
11007 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 mPendingBroadcast = null;
11009 }
11010 }
11011
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011012 boolean looped = false;
11013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011014 do {
11015 if (mOrderedBroadcasts.size() == 0) {
11016 // No more broadcasts pending, so all done!
11017 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011018 if (looped) {
11019 // If we had finished the last ordered broadcast, then
11020 // make sure all processes have correct oom and sched
11021 // adjustments.
11022 updateOomAdjLocked();
11023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011024 return;
11025 }
11026 r = mOrderedBroadcasts.get(0);
11027 boolean forceReceive = false;
11028
11029 // Ensure that even if something goes awry with the timeout
11030 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011031 // and continue to make progress.
11032 //
11033 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011034 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011035 // one time heavy lifting after system upgrades and can take
11036 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011038 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011039 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 if ((numReceivers > 0) &&
11041 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011042 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011043 + " now=" + now
11044 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011045 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 + " intent=" + r.intent
11047 + " numReceivers=" + numReceivers
11048 + " nextReceiver=" + r.nextReceiver
11049 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011050 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 forceReceive = true;
11052 r.state = BroadcastRecord.IDLE;
11053 }
11054 }
11055
11056 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011057 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 "processNextBroadcast() called when not idle (state="
11059 + r.state + ")");
11060 return;
11061 }
11062
11063 if (r.receivers == null || r.nextReceiver >= numReceivers
11064 || r.resultAbort || forceReceive) {
11065 // No more receivers for this broadcast! Send the final
11066 // result if requested...
11067 if (r.resultTo != null) {
11068 try {
11069 if (DEBUG_BROADCAST) {
11070 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011071 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 + " seq=" + seq + " app=" + r.callerApp);
11073 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011074 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011076 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011078 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 }
11080 }
11081
Joe Onorato8a9b2202010-02-26 18:56:32 -080011082 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011083 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084
Joe Onorato8a9b2202010-02-26 18:56:32 -080011085 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011086 + r);
11087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011089 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 mOrderedBroadcasts.remove(0);
11091 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011092 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 continue;
11094 }
11095 } while (r == null);
11096
11097 // Get the next receiver...
11098 int recIdx = r.nextReceiver++;
11099
11100 // Keep track of when this receiver started, and make sure there
11101 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011102 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011104 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105
Joe Onorato8a9b2202010-02-26 18:56:32 -080011106 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011107 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011108 }
11109 if (! mPendingBroadcastTimeoutMessage) {
11110 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011111 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011112 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11113 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 }
11115
11116 Object nextReceiver = r.receivers.get(recIdx);
11117 if (nextReceiver instanceof BroadcastFilter) {
11118 // Simple case: this is a registered receiver who gets
11119 // a direct call.
11120 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011121 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011122 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011124 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 if (r.receiver == null || !r.ordered) {
11126 // The receiver has already finished, so schedule to
11127 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011128 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11129 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 r.state = BroadcastRecord.IDLE;
11131 scheduleBroadcastsLocked();
11132 }
11133 return;
11134 }
11135
11136 // Hard case: need to instantiate the receiver, possibly
11137 // starting its application process to host it.
11138
11139 ResolveInfo info =
11140 (ResolveInfo)nextReceiver;
11141
11142 boolean skip = false;
11143 int perm = checkComponentPermission(info.activityInfo.permission,
11144 r.callingPid, r.callingUid,
11145 info.activityInfo.exported
11146 ? -1 : info.activityInfo.applicationInfo.uid);
11147 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011148 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 + r.intent.toString()
11150 + " from " + r.callerPackage + " (pid=" + r.callingPid
11151 + ", uid=" + r.callingUid + ")"
11152 + " requires " + info.activityInfo.permission
11153 + " due to receiver " + info.activityInfo.packageName
11154 + "/" + info.activityInfo.name);
11155 skip = true;
11156 }
11157 if (r.callingUid != Process.SYSTEM_UID &&
11158 r.requiredPermission != null) {
11159 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011160 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 checkPermission(r.requiredPermission,
11162 info.activityInfo.applicationInfo.packageName);
11163 } catch (RemoteException e) {
11164 perm = PackageManager.PERMISSION_DENIED;
11165 }
11166 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011167 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 + r.intent + " to "
11169 + info.activityInfo.applicationInfo.packageName
11170 + " requires " + r.requiredPermission
11171 + " due to sender " + r.callerPackage
11172 + " (uid " + r.callingUid + ")");
11173 skip = true;
11174 }
11175 }
11176 if (r.curApp != null && r.curApp.crashing) {
11177 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011178 if (DEBUG_BROADCAST) Slog.v(TAG,
11179 "Skipping deliver ordered " + r + " to " + r.curApp
11180 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 skip = true;
11182 }
11183
11184 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011185 if (DEBUG_BROADCAST) Slog.v(TAG,
11186 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 r.receiver = null;
11188 r.curFilter = null;
11189 r.state = BroadcastRecord.IDLE;
11190 scheduleBroadcastsLocked();
11191 return;
11192 }
11193
11194 r.state = BroadcastRecord.APP_RECEIVE;
11195 String targetProcess = info.activityInfo.processName;
11196 r.curComponent = new ComponentName(
11197 info.activityInfo.applicationInfo.packageName,
11198 info.activityInfo.name);
11199 r.curReceiver = info.activityInfo;
11200
11201 // Is this receiver's application already running?
11202 ProcessRecord app = getProcessRecordLocked(targetProcess,
11203 info.activityInfo.applicationInfo.uid);
11204 if (app != null && app.thread != null) {
11205 try {
11206 processCurBroadcastLocked(r, app);
11207 return;
11208 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011209 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 + r.curComponent, e);
11211 }
11212
11213 // If a dead object exception was thrown -- fall through to
11214 // restart the application.
11215 }
11216
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011217 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011218 if (DEBUG_BROADCAST) Slog.v(TAG,
11219 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 if ((r.curApp=startProcessLocked(targetProcess,
11221 info.activityInfo.applicationInfo, true,
11222 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011223 "broadcast", r.curComponent,
11224 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11225 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226 // Ah, this recipient is unavailable. Finish it if necessary,
11227 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011228 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 + info.activityInfo.applicationInfo.packageName + "/"
11230 + info.activityInfo.applicationInfo.uid + " for broadcast "
11231 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011232 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11234 r.resultExtras, r.resultAbort, true);
11235 scheduleBroadcastsLocked();
11236 r.state = BroadcastRecord.IDLE;
11237 return;
11238 }
11239
11240 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011241 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 }
11243 }
11244
11245 // =========================================================
11246 // INSTRUMENTATION
11247 // =========================================================
11248
11249 public boolean startInstrumentation(ComponentName className,
11250 String profileFile, int flags, Bundle arguments,
11251 IInstrumentationWatcher watcher) {
11252 // Refuse possible leaked file descriptors
11253 if (arguments != null && arguments.hasFileDescriptors()) {
11254 throw new IllegalArgumentException("File descriptors passed in Bundle");
11255 }
11256
11257 synchronized(this) {
11258 InstrumentationInfo ii = null;
11259 ApplicationInfo ai = null;
11260 try {
11261 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011262 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011264 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011265 } catch (PackageManager.NameNotFoundException e) {
11266 }
11267 if (ii == null) {
11268 reportStartInstrumentationFailure(watcher, className,
11269 "Unable to find instrumentation info for: " + className);
11270 return false;
11271 }
11272 if (ai == null) {
11273 reportStartInstrumentationFailure(watcher, className,
11274 "Unable to find instrumentation target package: " + ii.targetPackage);
11275 return false;
11276 }
11277
11278 int match = mContext.getPackageManager().checkSignatures(
11279 ii.targetPackage, ii.packageName);
11280 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11281 String msg = "Permission Denial: starting instrumentation "
11282 + className + " from pid="
11283 + Binder.getCallingPid()
11284 + ", uid=" + Binder.getCallingPid()
11285 + " not allowed because package " + ii.packageName
11286 + " does not have a signature matching the target "
11287 + ii.targetPackage;
11288 reportStartInstrumentationFailure(watcher, className, msg);
11289 throw new SecurityException(msg);
11290 }
11291
11292 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011293 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011294 ProcessRecord app = addAppLocked(ai);
11295 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011296 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011297 app.instrumentationProfileFile = profileFile;
11298 app.instrumentationArguments = arguments;
11299 app.instrumentationWatcher = watcher;
11300 app.instrumentationResultClass = className;
11301 Binder.restoreCallingIdentity(origId);
11302 }
11303
11304 return true;
11305 }
11306
11307 /**
11308 * Report errors that occur while attempting to start Instrumentation. Always writes the
11309 * error to the logs, but if somebody is watching, send the report there too. This enables
11310 * the "am" command to report errors with more information.
11311 *
11312 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11313 * @param cn The component name of the instrumentation.
11314 * @param report The error report.
11315 */
11316 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11317 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011318 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 try {
11320 if (watcher != null) {
11321 Bundle results = new Bundle();
11322 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11323 results.putString("Error", report);
11324 watcher.instrumentationStatus(cn, -1, results);
11325 }
11326 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011327 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 }
11329 }
11330
11331 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11332 if (app.instrumentationWatcher != null) {
11333 try {
11334 // NOTE: IInstrumentationWatcher *must* be oneway here
11335 app.instrumentationWatcher.instrumentationFinished(
11336 app.instrumentationClass,
11337 resultCode,
11338 results);
11339 } catch (RemoteException e) {
11340 }
11341 }
11342 app.instrumentationWatcher = null;
11343 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011344 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 app.instrumentationProfileFile = null;
11346 app.instrumentationArguments = null;
11347
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011348 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 }
11350
11351 public void finishInstrumentation(IApplicationThread target,
11352 int resultCode, Bundle results) {
11353 // Refuse possible leaked file descriptors
11354 if (results != null && results.hasFileDescriptors()) {
11355 throw new IllegalArgumentException("File descriptors passed in Intent");
11356 }
11357
11358 synchronized(this) {
11359 ProcessRecord app = getRecordForAppLocked(target);
11360 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011361 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 return;
11363 }
11364 final long origId = Binder.clearCallingIdentity();
11365 finishInstrumentationLocked(app, resultCode, results);
11366 Binder.restoreCallingIdentity(origId);
11367 }
11368 }
11369
11370 // =========================================================
11371 // CONFIGURATION
11372 // =========================================================
11373
11374 public ConfigurationInfo getDeviceConfigurationInfo() {
11375 ConfigurationInfo config = new ConfigurationInfo();
11376 synchronized (this) {
11377 config.reqTouchScreen = mConfiguration.touchscreen;
11378 config.reqKeyboardType = mConfiguration.keyboard;
11379 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011380 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11381 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11383 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011384 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11385 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011386 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11387 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011388 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011389 }
11390 return config;
11391 }
11392
11393 public Configuration getConfiguration() {
11394 Configuration ci;
11395 synchronized(this) {
11396 ci = new Configuration(mConfiguration);
11397 }
11398 return ci;
11399 }
11400
11401 public void updateConfiguration(Configuration values) {
11402 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11403 "updateConfiguration()");
11404
11405 synchronized(this) {
11406 if (values == null && mWindowManager != null) {
11407 // sentinel: fetch the current configuration from the window manager
11408 values = mWindowManager.computeNewConfiguration();
11409 }
11410
11411 final long origId = Binder.clearCallingIdentity();
11412 updateConfigurationLocked(values, null);
11413 Binder.restoreCallingIdentity(origId);
11414 }
11415 }
11416
11417 /**
11418 * Do either or both things: (1) change the current configuration, and (2)
11419 * make sure the given activity is running with the (now) current
11420 * configuration. Returns true if the activity has been left running, or
11421 * false if <var>starting</var> is being destroyed to match the new
11422 * configuration.
11423 */
11424 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011425 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 int changes = 0;
11427
11428 boolean kept = true;
11429
11430 if (values != null) {
11431 Configuration newConfig = new Configuration(mConfiguration);
11432 changes = newConfig.updateFrom(values);
11433 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011434 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011435 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 }
11437
Doug Zongker2bec3d42009-12-04 12:52:44 -080011438 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439
11440 if (values.locale != null) {
11441 saveLocaleLocked(values.locale,
11442 !values.locale.equals(mConfiguration.locale),
11443 values.userSetLocale);
11444 }
11445
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011446 mConfigurationSeq++;
11447 if (mConfigurationSeq <= 0) {
11448 mConfigurationSeq = 1;
11449 }
11450 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011452 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011453
11454 AttributeCache ac = AttributeCache.instance();
11455 if (ac != null) {
11456 ac.updateConfiguration(mConfiguration);
11457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011459 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11460 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11461 msg.obj = new Configuration(mConfiguration);
11462 mHandler.sendMessage(msg);
11463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011465 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11466 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 try {
11468 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011469 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011470 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011471 app.thread.scheduleConfigurationChanged(mConfiguration);
11472 }
11473 } catch (Exception e) {
11474 }
11475 }
11476 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011477 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11478 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11480 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011481 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11482 broadcastIntentLocked(null, null,
11483 new Intent(Intent.ACTION_LOCALE_CHANGED),
11484 null, null, 0, null, null,
11485 null, false, false, MY_PID, Process.SYSTEM_UID);
11486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 }
11488 }
11489
11490 if (changes != 0 && starting == null) {
11491 // If the configuration changed, and the caller is not already
11492 // in the process of starting an activity, then find the top
11493 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011494 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495 }
11496
11497 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011498 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499 if (kept) {
11500 // If this didn't result in the starting activity being
11501 // destroyed, then we need to make sure at this point that all
11502 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011503 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011505 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 }
11507 }
11508
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011509 if (values != null && mWindowManager != null) {
11510 mWindowManager.setNewConfiguration(mConfiguration);
11511 }
11512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 return kept;
11514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515
11516 /**
11517 * Save the locale. You must be inside a synchronized (this) block.
11518 */
11519 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11520 if(isDiff) {
11521 SystemProperties.set("user.language", l.getLanguage());
11522 SystemProperties.set("user.region", l.getCountry());
11523 }
11524
11525 if(isPersist) {
11526 SystemProperties.set("persist.sys.language", l.getLanguage());
11527 SystemProperties.set("persist.sys.country", l.getCountry());
11528 SystemProperties.set("persist.sys.localevar", l.getVariant());
11529 }
11530 }
11531
11532 // =========================================================
11533 // LIFETIME MANAGEMENT
11534 // =========================================================
11535
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011536 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11537 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011539 // This adjustment has already been computed. If we are calling
11540 // from the top, we may have already computed our adjustment with
11541 // an earlier hidden adjustment that isn't really for us... if
11542 // so, use the new hidden adjustment.
11543 if (!recursed && app.hidden) {
11544 app.curAdj = hiddenAdj;
11545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 return app.curAdj;
11547 }
11548
11549 if (app.thread == null) {
11550 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011551 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 return (app.curAdj=EMPTY_APP_ADJ);
11553 }
11554
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011555 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11556 // The max adjustment doesn't allow this app to be anything
11557 // below foreground, so it is not worth doing work for it.
11558 app.adjType = "fixed";
11559 app.adjSeq = mAdjSeq;
11560 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011561 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011562 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11563 return (app.curAdj=app.maxAdj);
11564 }
11565
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011566 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011567 app.adjSource = null;
11568 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011569 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011570 app.empty = false;
11571 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572
The Android Open Source Project4df24232009-03-05 14:34:35 -080011573 // Determine the importance of the process, starting with most
11574 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011576 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011578 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011579 // The last app on the list is the foreground app.
11580 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011581 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011582 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011583 } else if (app.instrumentationClass != null) {
11584 // Don't want to kill running instrumentation.
11585 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011586 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011587 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011588 } else if (app.persistentActivities > 0) {
11589 // Special persistent activities... shouldn't be used these days.
11590 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011591 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011592 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011593 } else if (app.curReceiver != null ||
11594 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11595 // An app that is currently receiving a broadcast also
11596 // counts as being in the foreground.
11597 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011598 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011599 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 } else if (app.executingServices.size() > 0) {
11601 // An app that is currently executing a service callback also
11602 // counts as being in the foreground.
11603 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011604 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011605 app.adjType = "exec-service";
11606 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011607 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011608 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011609 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011610 app.adjType = "foreground-service";
11611 } else if (app.forcingToForeground != null) {
11612 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011613 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011614 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011615 app.adjType = "force-foreground";
11616 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011617 } else if (app == mHeavyWeightProcess) {
11618 // We don't want to kill the current heavy-weight process.
11619 adj = HEAVY_WEIGHT_APP_ADJ;
11620 schedGroup = Process.THREAD_GROUP_DEFAULT;
11621 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011622 } else if (app == mHomeProcess) {
11623 // This process is hosting what we currently consider to be the
11624 // home app, so we don't want to let it go into the background.
11625 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011626 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011627 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 } else if ((N=app.activities.size()) != 0) {
11629 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011630 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011632 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011633 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011634 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011636 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011638 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011640 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011641 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 break;
11643 }
11644 }
11645 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011646 // A very not-needed process. If this is lower in the lru list,
11647 // we will push it in to the empty bucket.
11648 app.hidden = true;
11649 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011650 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011651 adj = hiddenAdj;
11652 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 }
11654
Joe Onorato8a9b2202010-02-26 18:56:32 -080011655 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011656
The Android Open Source Project4df24232009-03-05 14:34:35 -080011657 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011658 // there are applications dependent on our services or providers, but
11659 // this gives us a baseline and makes sure we don't get into an
11660 // infinite recursion.
11661 app.adjSeq = mAdjSeq;
11662 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663
Christopher Tate6fa95972009-06-05 18:43:55 -070011664 if (mBackupTarget != null && app == mBackupTarget.app) {
11665 // If possible we want to avoid killing apps while they're being backed up
11666 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011667 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011668 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011669 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011670 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011671 }
11672 }
11673
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011674 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11675 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 final long now = SystemClock.uptimeMillis();
11677 // This process is more important if the top activity is
11678 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011679 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011681 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 if (s.startRequested) {
11683 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11684 // This service has seen some activity within
11685 // recent memory, so we will keep its process ahead
11686 // of the background processes.
11687 if (adj > SECONDARY_SERVER_ADJ) {
11688 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011689 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011690 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 }
11692 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011693 // If we have let the service slide into the background
11694 // state, still have some text describing what it is doing
11695 // even though the service no longer has an impact.
11696 if (adj > SECONDARY_SERVER_ADJ) {
11697 app.adjType = "started-bg-services";
11698 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011699 // Don't kill this process because it is doing work; it
11700 // has said it is doing work.
11701 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011703 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11704 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011705 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 = s.connections.values().iterator();
11707 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011708 ArrayList<ConnectionRecord> clist = kt.next();
11709 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11710 // XXX should compute this based on the max of
11711 // all connected clients.
11712 ConnectionRecord cr = clist.get(i);
11713 if (cr.binding.client == app) {
11714 // Binding to ourself is not interesting.
11715 continue;
11716 }
11717 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11718 ProcessRecord client = cr.binding.client;
11719 int myHiddenAdj = hiddenAdj;
11720 if (myHiddenAdj > client.hiddenAdj) {
11721 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11722 myHiddenAdj = client.hiddenAdj;
11723 } else {
11724 myHiddenAdj = VISIBLE_APP_ADJ;
11725 }
11726 }
11727 int clientAdj = computeOomAdjLocked(
11728 client, myHiddenAdj, TOP_APP, true);
11729 if (adj > clientAdj) {
11730 adj = clientAdj >= VISIBLE_APP_ADJ
11731 ? clientAdj : VISIBLE_APP_ADJ;
11732 if (!client.hidden) {
11733 app.hidden = false;
11734 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011735 if (client.keeping) {
11736 app.keeping = true;
11737 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011738 app.adjType = "service";
11739 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11740 .REASON_SERVICE_IN_USE;
11741 app.adjSource = cr.binding.client;
11742 app.adjTarget = s.name;
11743 }
11744 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11745 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11746 schedGroup = Process.THREAD_GROUP_DEFAULT;
11747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 }
11749 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011750 ActivityRecord a = cr.activity;
11751 //if (a != null) {
11752 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11753 //}
11754 if (a != null && adj > FOREGROUND_APP_ADJ &&
11755 (a.state == ActivityState.RESUMED
11756 || a.state == ActivityState.PAUSING)) {
11757 adj = FOREGROUND_APP_ADJ;
11758 schedGroup = Process.THREAD_GROUP_DEFAULT;
11759 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011760 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011761 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11762 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011763 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011764 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766 }
11767 }
11768 }
11769 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011770
Dianne Hackborn287952c2010-09-22 22:34:31 -070011771 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011772 // would like to avoid killing it unless it would prevent the current
11773 // application from running. By default we put the process in
11774 // with the rest of the background processes; as we scan through
11775 // its services we may bump it up from there.
11776 if (adj > hiddenAdj) {
11777 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011778 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011779 app.adjType = "bg-services";
11780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 }
11782
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011783 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11784 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011785 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011786 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11787 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011788 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 if (cpr.clients.size() != 0) {
11790 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11791 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11792 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011793 if (client == app) {
11794 // Being our own client is not interesting.
11795 continue;
11796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 int myHiddenAdj = hiddenAdj;
11798 if (myHiddenAdj > client.hiddenAdj) {
11799 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11800 myHiddenAdj = client.hiddenAdj;
11801 } else {
11802 myHiddenAdj = FOREGROUND_APP_ADJ;
11803 }
11804 }
11805 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011806 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 if (adj > clientAdj) {
11808 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011809 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011810 if (!client.hidden) {
11811 app.hidden = false;
11812 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011813 if (client.keeping) {
11814 app.keeping = true;
11815 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011816 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011817 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11818 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011819 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011820 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011821 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011822 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11823 schedGroup = Process.THREAD_GROUP_DEFAULT;
11824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011825 }
11826 }
11827 // If the provider has external (non-framework) process
11828 // dependencies, ensure that its adjustment is at least
11829 // FOREGROUND_APP_ADJ.
11830 if (cpr.externals != 0) {
11831 if (adj > FOREGROUND_APP_ADJ) {
11832 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011833 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011834 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011835 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011836 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011837 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 }
11839 }
11840 }
11841 }
11842
11843 app.curRawAdj = adj;
11844
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11847 if (adj > app.maxAdj) {
11848 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011849 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011850 schedGroup = Process.THREAD_GROUP_DEFAULT;
11851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011853 if (adj < HIDDEN_APP_MIN_ADJ) {
11854 app.keeping = true;
11855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856
11857 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011858 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011860 return adj;
11861 }
11862
11863 /**
11864 * Ask a given process to GC right now.
11865 */
11866 final void performAppGcLocked(ProcessRecord app) {
11867 try {
11868 app.lastRequestedGc = SystemClock.uptimeMillis();
11869 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011870 if (app.reportLowMemory) {
11871 app.reportLowMemory = false;
11872 app.thread.scheduleLowMemory();
11873 } else {
11874 app.thread.processInBackground();
11875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 }
11877 } catch (Exception e) {
11878 // whatever.
11879 }
11880 }
11881
11882 /**
11883 * Returns true if things are idle enough to perform GCs.
11884 */
Josh Bartel7f208742010-02-25 11:01:44 -060011885 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886 return mParallelBroadcasts.size() == 0
11887 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011888 && (mSleeping || (mMainStack.mResumedActivity != null &&
11889 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011890 }
11891
11892 /**
11893 * Perform GCs on all processes that are waiting for it, but only
11894 * if things are idle.
11895 */
11896 final void performAppGcsLocked() {
11897 final int N = mProcessesToGc.size();
11898 if (N <= 0) {
11899 return;
11900 }
Josh Bartel7f208742010-02-25 11:01:44 -060011901 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011902 while (mProcessesToGc.size() > 0) {
11903 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011904 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011905 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11906 <= SystemClock.uptimeMillis()) {
11907 // To avoid spamming the system, we will GC processes one
11908 // at a time, waiting a few seconds between each.
11909 performAppGcLocked(proc);
11910 scheduleAppGcsLocked();
11911 return;
11912 } else {
11913 // It hasn't been long enough since we last GCed this
11914 // process... put it in the list to wait for its time.
11915 addProcessToGcListLocked(proc);
11916 break;
11917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918 }
11919 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011920
11921 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011922 }
11923 }
11924
11925 /**
11926 * If all looks good, perform GCs on all processes waiting for them.
11927 */
11928 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011929 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 performAppGcsLocked();
11931 return;
11932 }
11933 // Still not idle, wait some more.
11934 scheduleAppGcsLocked();
11935 }
11936
11937 /**
11938 * Schedule the execution of all pending app GCs.
11939 */
11940 final void scheduleAppGcsLocked() {
11941 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011942
11943 if (mProcessesToGc.size() > 0) {
11944 // Schedule a GC for the time to the next process.
11945 ProcessRecord proc = mProcessesToGc.get(0);
11946 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11947
11948 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11949 long now = SystemClock.uptimeMillis();
11950 if (when < (now+GC_TIMEOUT)) {
11951 when = now + GC_TIMEOUT;
11952 }
11953 mHandler.sendMessageAtTime(msg, when);
11954 }
11955 }
11956
11957 /**
11958 * Add a process to the array of processes waiting to be GCed. Keeps the
11959 * list in sorted order by the last GC time. The process can't already be
11960 * on the list.
11961 */
11962 final void addProcessToGcListLocked(ProcessRecord proc) {
11963 boolean added = false;
11964 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11965 if (mProcessesToGc.get(i).lastRequestedGc <
11966 proc.lastRequestedGc) {
11967 added = true;
11968 mProcessesToGc.add(i+1, proc);
11969 break;
11970 }
11971 }
11972 if (!added) {
11973 mProcessesToGc.add(0, proc);
11974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011975 }
11976
11977 /**
11978 * Set up to ask a process to GC itself. This will either do it
11979 * immediately, or put it on the list of processes to gc the next
11980 * time things are idle.
11981 */
11982 final void scheduleAppGcLocked(ProcessRecord app) {
11983 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011984 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011985 return;
11986 }
11987 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011988 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011989 scheduleAppGcsLocked();
11990 }
11991 }
11992
Dianne Hackborn287952c2010-09-22 22:34:31 -070011993 final void checkExcessivePowerUsageLocked(boolean doKills) {
11994 updateCpuStatsNow();
11995
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011996 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011997 boolean doWakeKills = doKills;
11998 boolean doCpuKills = doKills;
11999 if (mLastPowerCheckRealtime == 0) {
12000 doWakeKills = false;
12001 }
12002 if (mLastPowerCheckUptime == 0) {
12003 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012004 }
12005 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012006 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012007 }
12008 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012009 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12010 final long curUptime = SystemClock.uptimeMillis();
12011 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12012 mLastPowerCheckRealtime = curRealtime;
12013 mLastPowerCheckUptime = curUptime;
12014 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12015 doWakeKills = false;
12016 }
12017 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12018 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012019 }
12020 int i = mLruProcesses.size();
12021 while (i > 0) {
12022 i--;
12023 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012024 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012025 long wtime;
12026 synchronized (stats) {
12027 wtime = stats.getProcessWakeTime(app.info.uid,
12028 app.pid, curRealtime);
12029 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012030 long wtimeUsed = wtime - app.lastWakeTime;
12031 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12032 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012033 StringBuilder sb = new StringBuilder(128);
12034 sb.append("Wake for ");
12035 app.toShortString(sb);
12036 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012037 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012038 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012039 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012040 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012041 sb.append((wtimeUsed*100)/realtimeSince);
12042 sb.append("%)");
12043 Slog.i(TAG, sb.toString());
12044 sb.setLength(0);
12045 sb.append("CPU for ");
12046 app.toShortString(sb);
12047 sb.append(": over ");
12048 TimeUtils.formatDuration(uptimeSince, sb);
12049 sb.append(" used ");
12050 TimeUtils.formatDuration(cputimeUsed, sb);
12051 sb.append(" (");
12052 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012053 sb.append("%)");
12054 Slog.i(TAG, sb.toString());
12055 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012056 // If a process has held a wake lock for more
12057 // than 50% of the time during this period,
12058 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012059 if (doWakeKills && realtimeSince > 0
12060 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12061 synchronized (stats) {
12062 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12063 realtimeSince, wtimeUsed);
12064 }
12065 Slog.w(TAG, "Excessive wake lock in " + app.processName
12066 + " (pid " + app.pid + "): held " + wtimeUsed
12067 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012068 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12069 app.processName, app.setAdj, "excessive wake lock");
12070 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012071 } else if (doCpuKills && uptimeSince > 0
12072 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12073 synchronized (stats) {
12074 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12075 uptimeSince, cputimeUsed);
12076 }
12077 Slog.w(TAG, "Excessive CPU in " + app.processName
12078 + " (pid " + app.pid + "): used " + cputimeUsed
12079 + " during " + uptimeSince);
12080 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12081 app.processName, app.setAdj, "excessive cpu");
12082 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012083 } else {
12084 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012085 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012086 }
12087 }
12088 }
12089 }
12090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091 private final boolean updateOomAdjLocked(
12092 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12093 app.hiddenAdj = hiddenAdj;
12094
12095 if (app.thread == null) {
12096 return true;
12097 }
12098
Dianne Hackborn287952c2010-09-22 22:34:31 -070012099 final boolean wasKeeping = app.keeping;
12100
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012101 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012103 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 if (app.curRawAdj != app.setRawAdj) {
12105 if (app.curRawAdj > FOREGROUND_APP_ADJ
12106 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12107 // If this app is transitioning from foreground to
12108 // non-foreground, have it do a gc.
12109 scheduleAppGcLocked(app);
12110 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12111 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12112 // Likewise do a gc when an app is moving in to the
12113 // background (such as a service stopping).
12114 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012115 }
12116
12117 if (wasKeeping && !app.keeping) {
12118 // This app is no longer something we want to keep. Note
12119 // its current wake lock time to later know to kill it if
12120 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012121 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12122 synchronized (stats) {
12123 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12124 app.pid, SystemClock.elapsedRealtime());
12125 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012126 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012127 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012129 app.setRawAdj = app.curRawAdj;
12130 }
12131 if (adj != app.setAdj) {
12132 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012133 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012134 TAG, "Set app " + app.processName +
12135 " oom adj to " + adj);
12136 app.setAdj = adj;
12137 } else {
12138 return false;
12139 }
12140 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012141 if (app.setSchedGroup != app.curSchedGroup) {
12142 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012143 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012144 "Setting process group of " + app.processName
12145 + " to " + app.curSchedGroup);
12146 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012147 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012148 try {
12149 Process.setProcessGroup(app.pid, app.curSchedGroup);
12150 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012151 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012152 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012153 e.printStackTrace();
12154 } finally {
12155 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012156 }
12157 }
12158 if (false) {
12159 if (app.thread != null) {
12160 try {
12161 app.thread.setSchedulingGroup(app.curSchedGroup);
12162 } catch (RemoteException e) {
12163 }
12164 }
12165 }
12166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012167 }
12168
12169 return true;
12170 }
12171
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012172 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012173 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012175 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012177 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 }
12179 }
12180 return resumedActivity;
12181 }
12182
12183 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012184 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12186 int curAdj = app.curAdj;
12187 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12188 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12189
12190 mAdjSeq++;
12191
12192 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12193 if (res) {
12194 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12195 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12196 if (nowHidden != wasHidden) {
12197 // Changed to/from hidden state, so apps after it in the LRU
12198 // list may also be changed.
12199 updateOomAdjLocked();
12200 }
12201 }
12202 return res;
12203 }
12204
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012205 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012207 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012208 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12209
12210 if (false) {
12211 RuntimeException e = new RuntimeException();
12212 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012213 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012214 }
12215
12216 mAdjSeq++;
12217
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012218 // Let's determine how many processes we have running vs.
12219 // how many slots we have for background processes; we may want
12220 // to put multiple processes in a slot of there are enough of
12221 // them.
12222 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12223 int factor = (mLruProcesses.size()-4)/numSlots;
12224 if (factor < 1) factor = 1;
12225 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012226 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012228 // First try updating the OOM adjustment for each of the
12229 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012230 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012231 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12232 while (i > 0) {
12233 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012234 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012235 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012236 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012237 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012239 step++;
12240 if (step >= factor) {
12241 step = 0;
12242 curHiddenAdj++;
12243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012244 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012245 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012246 if (!app.killedBackground) {
12247 numHidden++;
12248 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012249 Slog.i(TAG, "No longer want " + app.processName
12250 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012251 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12252 app.processName, app.setAdj, "too many background");
12253 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012254 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012255 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012256 }
12257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 } else {
12259 didOomAdj = false;
12260 }
12261 }
12262
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012263 // If we return false, we will fall back on killing processes to
12264 // have a fixed limit. Do this if a limit has been requested; else
12265 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012266 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12267 }
12268
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012269 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012270 synchronized (this) {
12271 int i;
12272
12273 // First remove any unused application processes whose package
12274 // has been removed.
12275 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12276 final ProcessRecord app = mRemovedProcesses.get(i);
12277 if (app.activities.size() == 0
12278 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012279 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 TAG, "Exiting empty application process "
12281 + app.processName + " ("
12282 + (app.thread != null ? app.thread.asBinder() : null)
12283 + ")\n");
12284 if (app.pid > 0 && app.pid != MY_PID) {
12285 Process.killProcess(app.pid);
12286 } else {
12287 try {
12288 app.thread.scheduleExit();
12289 } catch (Exception e) {
12290 // Ignore exceptions.
12291 }
12292 }
12293 cleanUpApplicationRecordLocked(app, false, -1);
12294 mRemovedProcesses.remove(i);
12295
12296 if (app.persistent) {
12297 if (app.persistent) {
12298 addAppLocked(app.info);
12299 }
12300 }
12301 }
12302 }
12303
12304 // Now try updating the OOM adjustment for each of the
12305 // application processes based on their current state.
12306 // If the setOomAdj() API is not supported, then go with our
12307 // back-up plan...
12308 if (!updateOomAdjLocked()) {
12309
12310 // Count how many processes are running services.
12311 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012312 for (i=mLruProcesses.size()-1; i>=0; i--) {
12313 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012314
12315 if (app.persistent || app.services.size() != 0
12316 || app.curReceiver != null
12317 || app.persistentActivities > 0) {
12318 // Don't count processes holding services against our
12319 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012320 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012321 TAG, "Not trimming app " + app + " with services: "
12322 + app.services);
12323 numServiceProcs++;
12324 }
12325 }
12326
12327 int curMaxProcs = mProcessLimit;
12328 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12329 if (mAlwaysFinishActivities) {
12330 curMaxProcs = 1;
12331 }
12332 curMaxProcs += numServiceProcs;
12333
12334 // Quit as many processes as we can to get down to the desired
12335 // process count. First remove any processes that no longer
12336 // have activites running in them.
12337 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012338 i<mLruProcesses.size()
12339 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012340 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012341 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342 // Quit an application only if it is not currently
12343 // running any activities.
12344 if (!app.persistent && app.activities.size() == 0
12345 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012346 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 TAG, "Exiting empty application process "
12348 + app.processName + " ("
12349 + (app.thread != null ? app.thread.asBinder() : null)
12350 + ")\n");
12351 if (app.pid > 0 && app.pid != MY_PID) {
12352 Process.killProcess(app.pid);
12353 } else {
12354 try {
12355 app.thread.scheduleExit();
12356 } catch (Exception e) {
12357 // Ignore exceptions.
12358 }
12359 }
12360 // todo: For now we assume the application is not buggy
12361 // or evil, and will quit as a result of our request.
12362 // Eventually we need to drive this off of the death
12363 // notification, and kill the process if it takes too long.
12364 cleanUpApplicationRecordLocked(app, false, i);
12365 i--;
12366 }
12367 }
12368
12369 // If we still have too many processes, now from the least
12370 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012371 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012372 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 " of " + curMaxProcs + " processes");
12374 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012375 i<mLruProcesses.size()
12376 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012377 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012378 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 // Quit the application only if we have a state saved for
12380 // all of its activities.
12381 boolean canQuit = !app.persistent && app.curReceiver == null
12382 && app.services.size() == 0
12383 && app.persistentActivities == 0;
12384 int NUMA = app.activities.size();
12385 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012386 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012387 TAG, "Looking to quit " + app.processName);
12388 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012389 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012390 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012391 TAG, " " + r.intent.getComponent().flattenToShortString()
12392 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12393 canQuit = (r.haveState || !r.stateNotNeeded)
12394 && !r.visible && r.stopped;
12395 }
12396 if (canQuit) {
12397 // Finish all of the activities, and then the app itself.
12398 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012399 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012400 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012401 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402 }
12403 r.resultTo = null;
12404 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012405 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012406 + app.processName + " ("
12407 + (app.thread != null ? app.thread.asBinder() : null)
12408 + ")\n");
12409 if (app.pid > 0 && app.pid != MY_PID) {
12410 Process.killProcess(app.pid);
12411 } else {
12412 try {
12413 app.thread.scheduleExit();
12414 } catch (Exception e) {
12415 // Ignore exceptions.
12416 }
12417 }
12418 // todo: For now we assume the application is not buggy
12419 // or evil, and will quit as a result of our request.
12420 // Eventually we need to drive this off of the death
12421 // notification, and kill the process if it takes too long.
12422 cleanUpApplicationRecordLocked(app, false, i);
12423 i--;
12424 //dump();
12425 }
12426 }
12427
12428 }
12429
12430 int curMaxActivities = MAX_ACTIVITIES;
12431 if (mAlwaysFinishActivities) {
12432 curMaxActivities = 1;
12433 }
12434
12435 // Finally, if there are too many activities now running, try to
12436 // finish as many as we can to get back down to the limit.
12437 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012438 i<mMainStack.mLRUActivities.size()
12439 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012441 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012442 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012443
12444 // We can finish this one if we have its icicle saved and
12445 // it is not persistent.
12446 if ((r.haveState || !r.stateNotNeeded) && !r.visible
12447 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012448 final int origSize = mMainStack.mLRUActivities.size();
12449 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012450
12451 // This will remove it from the LRU list, so keep
12452 // our index at the same value. Note that this check to
12453 // see if the size changes is just paranoia -- if
12454 // something unexpected happens, we don't want to end up
12455 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012456 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012457 i--;
12458 }
12459 }
12460 }
12461 }
12462 }
12463
12464 /** This method sends the specified signal to each of the persistent apps */
12465 public void signalPersistentProcesses(int sig) throws RemoteException {
12466 if (sig != Process.SIGNAL_USR1) {
12467 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12468 }
12469
12470 synchronized (this) {
12471 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12472 != PackageManager.PERMISSION_GRANTED) {
12473 throw new SecurityException("Requires permission "
12474 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12475 }
12476
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012477 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12478 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012479 if (r.thread != null && r.persistent) {
12480 Process.sendSignal(r.pid, sig);
12481 }
12482 }
12483 }
12484 }
12485
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012486 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012487 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012488
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012489 try {
12490 synchronized (this) {
12491 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12492 // its own permission.
12493 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12494 != PackageManager.PERMISSION_GRANTED) {
12495 throw new SecurityException("Requires permission "
12496 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012497 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012498
12499 if (start && fd == null) {
12500 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012501 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012502
12503 ProcessRecord proc = null;
12504 try {
12505 int pid = Integer.parseInt(process);
12506 synchronized (mPidsSelfLocked) {
12507 proc = mPidsSelfLocked.get(pid);
12508 }
12509 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012510 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012511
12512 if (proc == null) {
12513 HashMap<String, SparseArray<ProcessRecord>> all
12514 = mProcessNames.getMap();
12515 SparseArray<ProcessRecord> procs = all.get(process);
12516 if (procs != null && procs.size() > 0) {
12517 proc = procs.valueAt(0);
12518 }
12519 }
12520
12521 if (proc == null || proc.thread == null) {
12522 throw new IllegalArgumentException("Unknown process: " + process);
12523 }
12524
12525 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12526 if (isSecure) {
12527 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12528 throw new SecurityException("Process not debuggable: " + proc);
12529 }
12530 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012531
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012532 proc.thread.profilerControl(start, path, fd);
12533 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012534 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012535 }
12536 } catch (RemoteException e) {
12537 throw new IllegalStateException("Process disappeared");
12538 } finally {
12539 if (fd != null) {
12540 try {
12541 fd.close();
12542 } catch (IOException e) {
12543 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012544 }
12545 }
12546 }
12547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12549 public void monitor() {
12550 synchronized (this) { }
12551 }
12552}