blob: d004034f597fff2485c7c4070a03efca6d69f53a [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 public boolean clearApplicationUserData(final String packageName,
2997 final IPackageDataObserver observer) {
2998 int uid = Binder.getCallingUid();
2999 int pid = Binder.getCallingPid();
3000 long callingId = Binder.clearCallingIdentity();
3001 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003002 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 int pkgUid = -1;
3004 synchronized(this) {
3005 try {
3006 pkgUid = pm.getPackageUid(packageName);
3007 } catch (RemoteException e) {
3008 }
3009 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003010 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003011 return false;
3012 }
3013 if (uid == pkgUid || checkComponentPermission(
3014 android.Manifest.permission.CLEAR_APP_USER_DATA,
3015 pid, uid, -1)
3016 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003017 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 } else {
3019 throw new SecurityException(pid+" does not have permission:"+
3020 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3021 "for process:"+packageName);
3022 }
3023 }
3024
3025 try {
3026 //clear application user data
3027 pm.clearApplicationUserData(packageName, observer);
3028 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3029 Uri.fromParts("package", packageName, null));
3030 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003031 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3032 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 } catch (RemoteException e) {
3034 }
3035 } finally {
3036 Binder.restoreCallingIdentity(callingId);
3037 }
3038 return true;
3039 }
3040
Dianne Hackborn03abb812010-01-04 18:43:19 -08003041 public void killBackgroundProcesses(final String packageName) {
3042 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3043 != PackageManager.PERMISSION_GRANTED &&
3044 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3045 != PackageManager.PERMISSION_GRANTED) {
3046 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 + Binder.getCallingPid()
3048 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003049 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003050 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 throw new SecurityException(msg);
3052 }
3053
3054 long callingId = Binder.clearCallingIdentity();
3055 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003056 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 int pkgUid = -1;
3058 synchronized(this) {
3059 try {
3060 pkgUid = pm.getPackageUid(packageName);
3061 } catch (RemoteException e) {
3062 }
3063 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003064 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 return;
3066 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003067 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003068 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003069 }
3070 } finally {
3071 Binder.restoreCallingIdentity(callingId);
3072 }
3073 }
3074
3075 public void forceStopPackage(final String packageName) {
3076 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3077 != PackageManager.PERMISSION_GRANTED) {
3078 String msg = "Permission Denial: forceStopPackage() from pid="
3079 + Binder.getCallingPid()
3080 + ", uid=" + Binder.getCallingUid()
3081 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003082 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003083 throw new SecurityException(msg);
3084 }
3085
3086 long callingId = Binder.clearCallingIdentity();
3087 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003088 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003089 int pkgUid = -1;
3090 synchronized(this) {
3091 try {
3092 pkgUid = pm.getPackageUid(packageName);
3093 } catch (RemoteException e) {
3094 }
3095 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003096 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003097 return;
3098 }
3099 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 }
3101 } finally {
3102 Binder.restoreCallingIdentity(callingId);
3103 }
3104 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003105
3106 /*
3107 * The pkg name and uid have to be specified.
3108 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3109 */
3110 public void killApplicationWithUid(String pkg, int uid) {
3111 if (pkg == null) {
3112 return;
3113 }
3114 // Make sure the uid is valid.
3115 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003116 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003117 return;
3118 }
3119 int callerUid = Binder.getCallingUid();
3120 // Only the system server can kill an application
3121 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003122 // Post an aysnc message to kill the application
3123 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3124 msg.arg1 = uid;
3125 msg.arg2 = 0;
3126 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003127 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003128 } else {
3129 throw new SecurityException(callerUid + " cannot kill pkg: " +
3130 pkg);
3131 }
3132 }
3133
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003134 public void closeSystemDialogs(String reason) {
3135 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003136 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003137 if (reason != null) {
3138 intent.putExtra("reason", reason);
3139 }
3140
3141 final int uid = Binder.getCallingUid();
3142 final long origId = Binder.clearCallingIdentity();
3143 synchronized (this) {
3144 int i = mWatchers.beginBroadcast();
3145 while (i > 0) {
3146 i--;
3147 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3148 if (w != null) {
3149 try {
3150 w.closingSystemDialogs(reason);
3151 } catch (RemoteException e) {
3152 }
3153 }
3154 }
3155 mWatchers.finishBroadcast();
3156
Dianne Hackbornffa42482009-09-23 22:20:11 -07003157 mWindowManager.closeSystemDialogs(reason);
3158
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003159 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3160 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003161 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003162 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003163 Activity.RESULT_CANCELED, null, "close-sys");
3164 }
3165 }
3166
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003167 broadcastIntentLocked(null, null, intent, null,
3168 null, 0, null, null, null, false, false, -1, uid);
3169 }
3170 Binder.restoreCallingIdentity(origId);
3171 }
3172
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003173 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003174 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003175 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3176 for (int i=pids.length-1; i>=0; i--) {
3177 infos[i] = new Debug.MemoryInfo();
3178 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003179 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003180 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003181 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003182
3183 public void killApplicationProcess(String processName, int uid) {
3184 if (processName == null) {
3185 return;
3186 }
3187
3188 int callerUid = Binder.getCallingUid();
3189 // Only the system server can kill an application
3190 if (callerUid == Process.SYSTEM_UID) {
3191 synchronized (this) {
3192 ProcessRecord app = getProcessRecordLocked(processName, uid);
3193 if (app != null) {
3194 try {
3195 app.thread.scheduleSuicide();
3196 } catch (RemoteException e) {
3197 // If the other end already died, then our work here is done.
3198 }
3199 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003200 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003201 + processName + " / " + uid);
3202 }
3203 }
3204 } else {
3205 throw new SecurityException(callerUid + " cannot kill app process: " +
3206 processName);
3207 }
3208 }
3209
Dianne Hackborn03abb812010-01-04 18:43:19 -08003210 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003211 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3213 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003214 if (!mProcessesReady) {
3215 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 intent.putExtra(Intent.EXTRA_UID, uid);
3218 broadcastIntentLocked(null, null, intent,
3219 null, null, 0, null, null, null,
3220 false, false, MY_PID, Process.SYSTEM_UID);
3221 }
3222
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003223 private final boolean killPackageProcessesLocked(String packageName, int uid,
3224 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003225 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226
Dianne Hackborn03abb812010-01-04 18:43:19 -08003227 // Remove all processes this package may have touched: all with the
3228 // same UID (except for the system or root user), and all whose name
3229 // matches the package name.
3230 final String procNamePrefix = packageName + ":";
3231 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3232 final int NA = apps.size();
3233 for (int ia=0; ia<NA; ia++) {
3234 ProcessRecord app = apps.valueAt(ia);
3235 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003236 if (doit) {
3237 procs.add(app);
3238 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003239 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3240 || app.processName.equals(packageName)
3241 || app.processName.startsWith(procNamePrefix)) {
3242 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003243 if (!doit) {
3244 return true;
3245 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003246 app.removed = true;
3247 procs.add(app);
3248 }
3249 }
3250 }
3251 }
3252
3253 int N = procs.size();
3254 for (int i=0; i<N; i++) {
3255 removeProcessLocked(procs.get(i), callerWillRestart);
3256 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003257 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003258 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003259
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003260 private final boolean forceStopPackageLocked(String name, int uid,
3261 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 int i, N;
3263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 if (uid < 0) {
3265 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003266 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 } catch (RemoteException e) {
3268 }
3269 }
3270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003271 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003273
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003274 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3275 while (badApps.hasNext()) {
3276 SparseArray<Long> ba = badApps.next();
3277 if (ba.get(uid) != null) {
3278 badApps.remove();
3279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 }
3281 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003282
3283 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3284 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003286 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3287 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003289 if (!doit) {
3290 return true;
3291 }
3292 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003293 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 if (r.app != null) {
3295 r.app.removed = true;
3296 }
3297 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003298 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 }
3300 }
3301
3302 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3303 for (ServiceRecord service : mServices.values()) {
3304 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003305 if (!doit) {
3306 return true;
3307 }
3308 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003309 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 if (service.app != null) {
3311 service.app.removed = true;
3312 }
3313 service.app = null;
3314 services.add(service);
3315 }
3316 }
3317
3318 N = services.size();
3319 for (i=0; i<N; i++) {
3320 bringDownServiceLocked(services.get(i), true);
3321 }
3322
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003323 if (doit) {
3324 if (purgeCache) {
3325 AttributeCache ac = AttributeCache.instance();
3326 if (ac != null) {
3327 ac.removePackage(name);
3328 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003329 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003330 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003331 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332
3333 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 }
3335
3336 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3337 final String name = app.processName;
3338 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003339 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 TAG, "Force removing process " + app + " (" + name
3341 + "/" + uid + ")");
3342
3343 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003344 if (mHeavyWeightProcess == app) {
3345 mHeavyWeightProcess = null;
3346 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 boolean needRestart = false;
3349 if (app.pid > 0 && app.pid != MY_PID) {
3350 int pid = app.pid;
3351 synchronized (mPidsSelfLocked) {
3352 mPidsSelfLocked.remove(pid);
3353 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3354 }
3355 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003356 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 Process.killProcess(pid);
3358
3359 if (app.persistent) {
3360 if (!callerWillRestart) {
3361 addAppLocked(app.info);
3362 } else {
3363 needRestart = true;
3364 }
3365 }
3366 } else {
3367 mRemovedProcesses.add(app);
3368 }
3369
3370 return needRestart;
3371 }
3372
3373 private final void processStartTimedOutLocked(ProcessRecord app) {
3374 final int pid = app.pid;
3375 boolean gone = false;
3376 synchronized (mPidsSelfLocked) {
3377 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3378 if (knownApp != null && knownApp.thread == null) {
3379 mPidsSelfLocked.remove(pid);
3380 gone = true;
3381 }
3382 }
3383
3384 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003385 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003386 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003387 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003389 if (mHeavyWeightProcess == app) {
3390 mHeavyWeightProcess = null;
3391 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3392 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003393 // Take care of any launching providers waiting for this process.
3394 checkAppInLaunchingProvidersLocked(app, true);
3395 // Take care of any services that are waiting for the process.
3396 for (int i=0; i<mPendingServices.size(); i++) {
3397 ServiceRecord sr = mPendingServices.get(i);
3398 if (app.info.uid == sr.appInfo.uid
3399 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003400 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003401 mPendingServices.remove(i);
3402 i--;
3403 bringDownServiceLocked(sr, true);
3404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003406 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003407 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003408 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003409 try {
3410 IBackupManager bm = IBackupManager.Stub.asInterface(
3411 ServiceManager.getService(Context.BACKUP_SERVICE));
3412 bm.agentDisconnected(app.info.packageName);
3413 } catch (RemoteException e) {
3414 // Can't happen; the backup manager is local
3415 }
3416 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003417 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003418 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003419 mPendingBroadcast.state = BroadcastRecord.IDLE;
3420 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003421 mPendingBroadcast = null;
3422 scheduleBroadcastsLocked();
3423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427 }
3428
3429 private final boolean attachApplicationLocked(IApplicationThread thread,
3430 int pid) {
3431
3432 // Find the application record that is being attached... either via
3433 // the pid if we are running in multiple processes, or just pull the
3434 // next app record if we are emulating process with anonymous threads.
3435 ProcessRecord app;
3436 if (pid != MY_PID && pid >= 0) {
3437 synchronized (mPidsSelfLocked) {
3438 app = mPidsSelfLocked.get(pid);
3439 }
3440 } else if (mStartingProcesses.size() > 0) {
3441 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003442 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 } else {
3444 app = null;
3445 }
3446
3447 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003448 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003450 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 if (pid > 0 && pid != MY_PID) {
3452 Process.killProcess(pid);
3453 } else {
3454 try {
3455 thread.scheduleExit();
3456 } catch (Exception e) {
3457 // Ignore exceptions.
3458 }
3459 }
3460 return false;
3461 }
3462
3463 // If this application record is still attached to a previous
3464 // process, clean it up now.
3465 if (app.thread != null) {
3466 handleAppDiedLocked(app, true);
3467 }
3468
3469 // Tell the process all about itself.
3470
Joe Onorato8a9b2202010-02-26 18:56:32 -08003471 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 TAG, "Binding process pid " + pid + " to record " + app);
3473
3474 String processName = app.processName;
3475 try {
3476 thread.asBinder().linkToDeath(new AppDeathRecipient(
3477 app, pid, thread), 0);
3478 } catch (RemoteException e) {
3479 app.resetPackageList();
3480 startProcessLocked(app, "link fail", processName);
3481 return false;
3482 }
3483
Doug Zongker2bec3d42009-12-04 12:52:44 -08003484 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485
3486 app.thread = thread;
3487 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003488 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3489 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 app.forcingToForeground = null;
3491 app.foregroundServices = false;
3492 app.debugging = false;
3493
3494 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3495
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003496 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003497 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003499 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003500 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003501 }
3502
Joe Onorato8a9b2202010-02-26 18:56:32 -08003503 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 TAG, "New app record " + app
3505 + " thread=" + thread.asBinder() + " pid=" + pid);
3506 try {
3507 int testMode = IApplicationThread.DEBUG_OFF;
3508 if (mDebugApp != null && mDebugApp.equals(processName)) {
3509 testMode = mWaitForDebugger
3510 ? IApplicationThread.DEBUG_WAIT
3511 : IApplicationThread.DEBUG_ON;
3512 app.debugging = true;
3513 if (mDebugTransient) {
3514 mDebugApp = mOrigDebugApp;
3515 mWaitForDebugger = mOrigWaitForDebugger;
3516 }
3517 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003518
Christopher Tate181fafa2009-05-14 11:12:14 -07003519 // If the app is being launched for restore or full backup, set it up specially
3520 boolean isRestrictedBackupMode = false;
3521 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3522 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3523 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3524 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003525
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003526 ensurePackageDexOpt(app.instrumentationInfo != null
3527 ? app.instrumentationInfo.packageName
3528 : app.info.packageName);
3529 if (app.instrumentationClass != null) {
3530 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003531 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003532 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003533 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003534 thread.bindApplication(processName, app.instrumentationInfo != null
3535 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 app.instrumentationClass, app.instrumentationProfileFile,
3537 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003538 isRestrictedBackupMode || !normalMode,
3539 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003540 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003541 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 } catch (Exception e) {
3543 // todo: Yikes! What should we do? For now we will try to
3544 // start another process, but that could easily get us in
3545 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003546 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547
3548 app.resetPackageList();
3549 startProcessLocked(app, "bind fail", processName);
3550 return false;
3551 }
3552
3553 // Remove this record from the list of starting applications.
3554 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003555 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3556 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 mProcessesOnHold.remove(app);
3558
3559 boolean badApp = false;
3560 boolean didSomething = false;
3561
3562 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003563 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003564 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3566 && processName.equals(hr.processName)) {
3567 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003568 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 didSomething = true;
3570 }
3571 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003572 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 + hr.intent.getComponent().flattenToShortString(), e);
3574 badApp = true;
3575 }
3576 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003577 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 }
3579 }
3580
3581 // Find any services that should be running in this process...
3582 if (!badApp && mPendingServices.size() > 0) {
3583 ServiceRecord sr = null;
3584 try {
3585 for (int i=0; i<mPendingServices.size(); i++) {
3586 sr = mPendingServices.get(i);
3587 if (app.info.uid != sr.appInfo.uid
3588 || !processName.equals(sr.processName)) {
3589 continue;
3590 }
3591
3592 mPendingServices.remove(i);
3593 i--;
3594 realStartServiceLocked(sr, app);
3595 didSomething = true;
3596 }
3597 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003598 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 + sr.shortName, e);
3600 badApp = true;
3601 }
3602 }
3603
3604 // Check if the next broadcast receiver is in this process...
3605 BroadcastRecord br = mPendingBroadcast;
3606 if (!badApp && br != null && br.curApp == app) {
3607 try {
3608 mPendingBroadcast = null;
3609 processCurBroadcastLocked(br, app);
3610 didSomething = true;
3611 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003612 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 + br.curComponent.flattenToShortString(), e);
3614 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003615 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3617 br.resultExtras, br.resultAbort, true);
3618 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003619 // We need to reset the state if we fails to start the receiver.
3620 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 }
3622 }
3623
Christopher Tate181fafa2009-05-14 11:12:14 -07003624 // Check whether the next backup agent is in this process...
3625 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003626 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003627 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003628 try {
3629 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3630 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003631 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003632 e.printStackTrace();
3633 }
3634 }
3635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 if (badApp) {
3637 // todo: Also need to kill application to deal with all
3638 // kinds of exceptions.
3639 handleAppDiedLocked(app, false);
3640 return false;
3641 }
3642
3643 if (!didSomething) {
3644 updateOomAdjLocked();
3645 }
3646
3647 return true;
3648 }
3649
3650 public final void attachApplication(IApplicationThread thread) {
3651 synchronized (this) {
3652 int callingPid = Binder.getCallingPid();
3653 final long origId = Binder.clearCallingIdentity();
3654 attachApplicationLocked(thread, callingPid);
3655 Binder.restoreCallingIdentity(origId);
3656 }
3657 }
3658
Dianne Hackborne88846e2009-09-30 21:34:25 -07003659 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003661 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 Binder.restoreCallingIdentity(origId);
3663 }
3664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003666 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003667 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 mWindowManager.enableScreenAfterBoot();
3669 }
3670
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003671 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003672 IntentFilter pkgFilter = new IntentFilter();
3673 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3674 pkgFilter.addDataScheme("package");
3675 mContext.registerReceiver(new BroadcastReceiver() {
3676 @Override
3677 public void onReceive(Context context, Intent intent) {
3678 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3679 if (pkgs != null) {
3680 for (String pkg : pkgs) {
3681 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3682 setResultCode(Activity.RESULT_OK);
3683 return;
3684 }
3685 }
3686 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003687 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003688 }, pkgFilter);
3689
3690 synchronized (this) {
3691 // Ensure that any processes we had put on hold are now started
3692 // up.
3693 final int NP = mProcessesOnHold.size();
3694 if (NP > 0) {
3695 ArrayList<ProcessRecord> procs =
3696 new ArrayList<ProcessRecord>(mProcessesOnHold);
3697 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003698 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3699 + procs.get(ip));
3700 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003701 }
3702 }
3703
3704 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003705 // Start looking for apps that are abusing wake locks.
3706 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003707 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003708 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003709 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003710 broadcastIntentLocked(null, null,
3711 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3712 null, null, 0, null, null,
3713 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3714 false, false, MY_PID, Process.SYSTEM_UID);
3715 }
3716 }
3717 }
3718
3719 final void ensureBootCompleted() {
3720 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003721 boolean enableScreen;
3722 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003723 booting = mBooting;
3724 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003725 enableScreen = !mBooted;
3726 mBooted = true;
3727 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003728
3729 if (booting) {
3730 finishBooting();
3731 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003732
3733 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003734 enableScreenAfterBoot();
3735 }
3736 }
3737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 public final void activityPaused(IBinder token, Bundle icicle) {
3739 // Refuse possible leaked file descriptors
3740 if (icicle != null && icicle.hasFileDescriptors()) {
3741 throw new IllegalArgumentException("File descriptors passed in Bundle");
3742 }
3743
3744 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003745 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 Binder.restoreCallingIdentity(origId);
3747 }
3748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 public final void activityStopped(IBinder token, Bitmap thumbnail,
3750 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003751 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 TAG, "Activity stopped: token=" + token);
3753
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003754 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755
3756 final long origId = Binder.clearCallingIdentity();
3757
3758 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003759 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003761 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762 r.thumbnail = thumbnail;
3763 r.description = description;
3764 r.stopped = true;
3765 r.state = ActivityState.STOPPED;
3766 if (!r.finishing) {
3767 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003768 r.stack.destroyActivityLocked(r, true);
3769 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003770 }
3771 }
3772 }
3773 }
3774
3775 if (r != null) {
3776 sendPendingThumbnail(r, null, null, null, false);
3777 }
3778
3779 trimApplications();
3780
3781 Binder.restoreCallingIdentity(origId);
3782 }
3783
3784 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003785 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003786 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 }
3788
3789 public String getCallingPackage(IBinder token) {
3790 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003791 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003792 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 }
3794 }
3795
3796 public ComponentName getCallingActivity(IBinder token) {
3797 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003798 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 return r != null ? r.intent.getComponent() : null;
3800 }
3801 }
3802
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003803 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003804 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003806 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 if (r != null) {
3808 return r.resultTo;
3809 }
3810 }
3811 return null;
3812 }
3813
3814 public ComponentName getActivityClassForToken(IBinder token) {
3815 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003816 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003818 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 return r.intent.getComponent();
3820 }
3821 return null;
3822 }
3823 }
3824
3825 public String getPackageForToken(IBinder token) {
3826 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003827 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003829 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 return r.packageName;
3831 }
3832 return null;
3833 }
3834 }
3835
3836 public IIntentSender getIntentSender(int type,
3837 String packageName, IBinder token, String resultWho,
3838 int requestCode, Intent intent, String resolvedType, int flags) {
3839 // Refuse possible leaked file descriptors
3840 if (intent != null && intent.hasFileDescriptors() == true) {
3841 throw new IllegalArgumentException("File descriptors passed in Intent");
3842 }
3843
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003844 if (type == INTENT_SENDER_BROADCAST) {
3845 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3846 throw new IllegalArgumentException(
3847 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3848 }
3849 }
3850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 synchronized(this) {
3852 int callingUid = Binder.getCallingUid();
3853 try {
3854 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3855 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003856 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 .getPackageUid(packageName);
3858 if (uid != Binder.getCallingUid()) {
3859 String msg = "Permission Denial: getIntentSender() from pid="
3860 + Binder.getCallingPid()
3861 + ", uid=" + Binder.getCallingUid()
3862 + ", (need uid=" + uid + ")"
3863 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003864 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 throw new SecurityException(msg);
3866 }
3867 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003868
3869 return getIntentSenderLocked(type, packageName, callingUid,
3870 token, resultWho, requestCode, intent, resolvedType, flags);
3871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 } catch (RemoteException e) {
3873 throw new SecurityException(e);
3874 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003875 }
3876 }
3877
3878 IIntentSender getIntentSenderLocked(int type,
3879 String packageName, int callingUid, IBinder token, String resultWho,
3880 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003881 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003882 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003883 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003884 if (index < 0) {
3885 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003887 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003888 if (activity.finishing) {
3889 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003891 }
3892
3893 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3894 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3895 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3896 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3897 |PendingIntent.FLAG_UPDATE_CURRENT);
3898
3899 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3900 type, packageName, activity, resultWho,
3901 requestCode, intent, resolvedType, flags);
3902 WeakReference<PendingIntentRecord> ref;
3903 ref = mIntentSenderRecords.get(key);
3904 PendingIntentRecord rec = ref != null ? ref.get() : null;
3905 if (rec != null) {
3906 if (!cancelCurrent) {
3907 if (updateCurrent) {
3908 rec.key.requestIntent.replaceExtras(intent);
3909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 return rec;
3911 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003912 rec.canceled = true;
3913 mIntentSenderRecords.remove(key);
3914 }
3915 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 return rec;
3917 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003918 rec = new PendingIntentRecord(this, key, callingUid);
3919 mIntentSenderRecords.put(key, rec.ref);
3920 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3921 if (activity.pendingResults == null) {
3922 activity.pendingResults
3923 = new HashSet<WeakReference<PendingIntentRecord>>();
3924 }
3925 activity.pendingResults.add(rec.ref);
3926 }
3927 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
3929
3930 public void cancelIntentSender(IIntentSender sender) {
3931 if (!(sender instanceof PendingIntentRecord)) {
3932 return;
3933 }
3934 synchronized(this) {
3935 PendingIntentRecord rec = (PendingIntentRecord)sender;
3936 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003937 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 .getPackageUid(rec.key.packageName);
3939 if (uid != Binder.getCallingUid()) {
3940 String msg = "Permission Denial: cancelIntentSender() from pid="
3941 + Binder.getCallingPid()
3942 + ", uid=" + Binder.getCallingUid()
3943 + " is not allowed to cancel packges "
3944 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003945 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946 throw new SecurityException(msg);
3947 }
3948 } catch (RemoteException e) {
3949 throw new SecurityException(e);
3950 }
3951 cancelIntentSenderLocked(rec, true);
3952 }
3953 }
3954
3955 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3956 rec.canceled = true;
3957 mIntentSenderRecords.remove(rec.key);
3958 if (cleanActivity && rec.key.activity != null) {
3959 rec.key.activity.pendingResults.remove(rec.ref);
3960 }
3961 }
3962
3963 public String getPackageForIntentSender(IIntentSender pendingResult) {
3964 if (!(pendingResult instanceof PendingIntentRecord)) {
3965 return null;
3966 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003967 try {
3968 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3969 return res.key.packageName;
3970 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 }
3972 return null;
3973 }
3974
3975 public void setProcessLimit(int max) {
3976 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3977 "setProcessLimit()");
3978 mProcessLimit = max;
3979 }
3980
3981 public int getProcessLimit() {
3982 return mProcessLimit;
3983 }
3984
3985 void foregroundTokenDied(ForegroundToken token) {
3986 synchronized (ActivityManagerService.this) {
3987 synchronized (mPidsSelfLocked) {
3988 ForegroundToken cur
3989 = mForegroundProcesses.get(token.pid);
3990 if (cur != token) {
3991 return;
3992 }
3993 mForegroundProcesses.remove(token.pid);
3994 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3995 if (pr == null) {
3996 return;
3997 }
3998 pr.forcingToForeground = null;
3999 pr.foregroundServices = false;
4000 }
4001 updateOomAdjLocked();
4002 }
4003 }
4004
4005 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4006 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4007 "setProcessForeground()");
4008 synchronized(this) {
4009 boolean changed = false;
4010
4011 synchronized (mPidsSelfLocked) {
4012 ProcessRecord pr = mPidsSelfLocked.get(pid);
4013 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004014 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 return;
4016 }
4017 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4018 if (oldToken != null) {
4019 oldToken.token.unlinkToDeath(oldToken, 0);
4020 mForegroundProcesses.remove(pid);
4021 pr.forcingToForeground = null;
4022 changed = true;
4023 }
4024 if (isForeground && token != null) {
4025 ForegroundToken newToken = new ForegroundToken() {
4026 public void binderDied() {
4027 foregroundTokenDied(this);
4028 }
4029 };
4030 newToken.pid = pid;
4031 newToken.token = token;
4032 try {
4033 token.linkToDeath(newToken, 0);
4034 mForegroundProcesses.put(pid, newToken);
4035 pr.forcingToForeground = token;
4036 changed = true;
4037 } catch (RemoteException e) {
4038 // If the process died while doing this, we will later
4039 // do the cleanup with the process death link.
4040 }
4041 }
4042 }
4043
4044 if (changed) {
4045 updateOomAdjLocked();
4046 }
4047 }
4048 }
4049
4050 // =========================================================
4051 // PERMISSIONS
4052 // =========================================================
4053
4054 static class PermissionController extends IPermissionController.Stub {
4055 ActivityManagerService mActivityManagerService;
4056 PermissionController(ActivityManagerService activityManagerService) {
4057 mActivityManagerService = activityManagerService;
4058 }
4059
4060 public boolean checkPermission(String permission, int pid, int uid) {
4061 return mActivityManagerService.checkPermission(permission, pid,
4062 uid) == PackageManager.PERMISSION_GRANTED;
4063 }
4064 }
4065
4066 /**
4067 * This can be called with or without the global lock held.
4068 */
4069 int checkComponentPermission(String permission, int pid, int uid,
4070 int reqUid) {
4071 // We might be performing an operation on behalf of an indirect binder
4072 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4073 // client identity accordingly before proceeding.
4074 Identity tlsIdentity = sCallerIdentity.get();
4075 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004076 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4078 uid = tlsIdentity.uid;
4079 pid = tlsIdentity.pid;
4080 }
4081
4082 // Root, system server and our own process get to do everything.
4083 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4084 !Process.supportsProcesses()) {
4085 return PackageManager.PERMISSION_GRANTED;
4086 }
4087 // If the target requires a specific UID, always fail for others.
4088 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004089 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 return PackageManager.PERMISSION_DENIED;
4091 }
4092 if (permission == null) {
4093 return PackageManager.PERMISSION_GRANTED;
4094 }
4095 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004096 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 .checkUidPermission(permission, uid);
4098 } catch (RemoteException e) {
4099 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004100 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 }
4102 return PackageManager.PERMISSION_DENIED;
4103 }
4104
4105 /**
4106 * As the only public entry point for permissions checking, this method
4107 * can enforce the semantic that requesting a check on a null global
4108 * permission is automatically denied. (Internally a null permission
4109 * string is used when calling {@link #checkComponentPermission} in cases
4110 * when only uid-based security is needed.)
4111 *
4112 * This can be called with or without the global lock held.
4113 */
4114 public int checkPermission(String permission, int pid, int uid) {
4115 if (permission == null) {
4116 return PackageManager.PERMISSION_DENIED;
4117 }
4118 return checkComponentPermission(permission, pid, uid, -1);
4119 }
4120
4121 /**
4122 * Binder IPC calls go through the public entry point.
4123 * This can be called with or without the global lock held.
4124 */
4125 int checkCallingPermission(String permission) {
4126 return checkPermission(permission,
4127 Binder.getCallingPid(),
4128 Binder.getCallingUid());
4129 }
4130
4131 /**
4132 * This can be called with or without the global lock held.
4133 */
4134 void enforceCallingPermission(String permission, String func) {
4135 if (checkCallingPermission(permission)
4136 == PackageManager.PERMISSION_GRANTED) {
4137 return;
4138 }
4139
4140 String msg = "Permission Denial: " + func + " from pid="
4141 + Binder.getCallingPid()
4142 + ", uid=" + Binder.getCallingUid()
4143 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004145 throw new SecurityException(msg);
4146 }
4147
4148 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004149 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4150 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4151 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4152 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4153 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004155 // Is the component private from the target uid?
4156 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4157
4158 // Acceptable if the there is no read permission needed from the
4159 // target or the target is holding the read permission.
4160 if (!readPerm) {
4161 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004163 == PackageManager.PERMISSION_GRANTED)) {
4164 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 }
4166 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004167
4168 // Acceptable if the there is no write permission needed from the
4169 // target or the target is holding the read permission.
4170 if (!writePerm) {
4171 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004173 == PackageManager.PERMISSION_GRANTED)) {
4174 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 }
4176 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004177
4178 // Acceptable if there is a path permission matching the URI that
4179 // the target holds the permission on.
4180 PathPermission[] pps = pi.pathPermissions;
4181 if (pps != null && (!readPerm || !writePerm)) {
4182 final String path = uri.getPath();
4183 int i = pps.length;
4184 while (i > 0 && (!readPerm || !writePerm)) {
4185 i--;
4186 PathPermission pp = pps[i];
4187 if (!readPerm) {
4188 final String pprperm = pp.getReadPermission();
4189 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4190 + pprperm + " for " + pp.getPath()
4191 + ": match=" + pp.match(path)
4192 + " check=" + pm.checkUidPermission(pprperm, uid));
4193 if (pprperm != null && pp.match(path) &&
4194 (pm.checkUidPermission(pprperm, uid)
4195 == PackageManager.PERMISSION_GRANTED)) {
4196 readPerm = true;
4197 }
4198 }
4199 if (!writePerm) {
4200 final String ppwperm = pp.getWritePermission();
4201 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4202 + ppwperm + " for " + pp.getPath()
4203 + ": match=" + pp.match(path)
4204 + " check=" + pm.checkUidPermission(ppwperm, uid));
4205 if (ppwperm != null && pp.match(path) &&
4206 (pm.checkUidPermission(ppwperm, uid)
4207 == PackageManager.PERMISSION_GRANTED)) {
4208 writePerm = true;
4209 }
4210 }
4211 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 } catch (RemoteException e) {
4214 return false;
4215 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004216
4217 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 }
4219
4220 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4221 int modeFlags) {
4222 // Root gets to do everything.
4223 if (uid == 0 || !Process.supportsProcesses()) {
4224 return true;
4225 }
4226 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4227 if (perms == null) return false;
4228 UriPermission perm = perms.get(uri);
4229 if (perm == null) return false;
4230 return (modeFlags&perm.modeFlags) == modeFlags;
4231 }
4232
4233 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4234 // Another redirected-binder-call permissions check as in
4235 // {@link checkComponentPermission}.
4236 Identity tlsIdentity = sCallerIdentity.get();
4237 if (tlsIdentity != null) {
4238 uid = tlsIdentity.uid;
4239 pid = tlsIdentity.pid;
4240 }
4241
4242 // Our own process gets to do everything.
4243 if (pid == MY_PID) {
4244 return PackageManager.PERMISSION_GRANTED;
4245 }
4246 synchronized(this) {
4247 return checkUriPermissionLocked(uri, uid, modeFlags)
4248 ? PackageManager.PERMISSION_GRANTED
4249 : PackageManager.PERMISSION_DENIED;
4250 }
4251 }
4252
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 /**
4254 * Check if the targetPkg can be granted permission to access uri by
4255 * the callingUid using the given modeFlags. Throws a security exception
4256 * if callingUid is not allowed to do this. Returns the uid of the target
4257 * if the URI permission grant should be performed; returns -1 if it is not
4258 * needed (for example targetPkg already has permission to access the URI).
4259 */
4260 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4261 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4263 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4264 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004265 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 }
4267
Joe Onorato8a9b2202010-02-26 18:56:32 -08004268 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004269 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004270
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004271 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272
4273 // If this is not a content: uri, we can't do anything with it.
4274 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004275 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004276 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004277 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 }
4279
4280 String name = uri.getAuthority();
4281 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004282 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 if (cpr != null) {
4284 pi = cpr.info;
4285 } else {
4286 try {
4287 pi = pm.resolveContentProvider(name,
4288 PackageManager.GET_URI_PERMISSION_PATTERNS);
4289 } catch (RemoteException ex) {
4290 }
4291 }
4292 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004293 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004294 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 }
4296
4297 int targetUid;
4298 try {
4299 targetUid = pm.getPackageUid(targetPkg);
4300 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004301 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004302 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004303 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004306 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 // First... does the target actually need this permission?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004310 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004312 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004313 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004314 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 }
4316
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004317 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 if (!pi.grantUriPermissions) {
4319 throw new SecurityException("Provider " + pi.packageName
4320 + "/" + pi.name
4321 + " does not allow granting of Uri permissions (uri "
4322 + uri + ")");
4323 }
4324 if (pi.uriPermissionPatterns != null) {
4325 final int N = pi.uriPermissionPatterns.length;
4326 boolean allowed = false;
4327 for (int i=0; i<N; i++) {
4328 if (pi.uriPermissionPatterns[i] != null
4329 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4330 allowed = true;
4331 break;
4332 }
4333 }
4334 if (!allowed) {
4335 throw new SecurityException("Provider " + pi.packageName
4336 + "/" + pi.name
4337 + " does not allow granting of permission to path of Uri "
4338 + uri);
4339 }
4340 }
4341
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004342 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 // this uri?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004344 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4346 throw new SecurityException("Uid " + callingUid
4347 + " does not have permission to uri " + uri);
4348 }
4349 }
4350
Dianne Hackborn39792d22010-08-19 18:01:52 -07004351 return targetUid;
4352 }
4353
4354 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4355 Uri uri, int modeFlags, UriPermissionOwner owner) {
4356 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4357 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4358 if (modeFlags == 0) {
4359 return;
4360 }
4361
4362 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 // to the uri, and the target doesn't. Let's now give this to
4364 // the target.
4365
Joe Onorato8a9b2202010-02-26 18:56:32 -08004366 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004367 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 HashMap<Uri, UriPermission> targetUris
4370 = mGrantedUriPermissions.get(targetUid);
4371 if (targetUris == null) {
4372 targetUris = new HashMap<Uri, UriPermission>();
4373 mGrantedUriPermissions.put(targetUid, targetUris);
4374 }
4375
4376 UriPermission perm = targetUris.get(uri);
4377 if (perm == null) {
4378 perm = new UriPermission(targetUid, uri);
4379 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004383 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 perm.globalModeFlags |= modeFlags;
4385 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004386 perm.readOwners.add(owner);
4387 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004389 perm.writeOwners.add(owner);
4390 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 }
4392 }
4393
Dianne Hackborn39792d22010-08-19 18:01:52 -07004394 void grantUriPermissionLocked(int callingUid,
4395 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4396 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4397 if (targetUid < 0) {
4398 return;
4399 }
4400
4401 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4402 }
4403
4404 /**
4405 * Like checkGrantUriPermissionLocked, but takes an Intent.
4406 */
4407 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4408 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004409 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004410 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004411 + " from " + intent + "; flags=0x"
4412 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004415 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 }
4417 Uri data = intent.getData();
4418 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004419 return -1;
4420 }
4421 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4422 intent.getFlags());
4423 }
4424
4425 /**
4426 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4427 */
4428 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4429 String targetPkg, Intent intent, UriPermissionOwner owner) {
4430 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4431 intent.getFlags(), owner);
4432 }
4433
4434 void grantUriPermissionFromIntentLocked(int callingUid,
4435 String targetPkg, Intent intent, UriPermissionOwner owner) {
4436 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4437 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 return;
4439 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004440
4441 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 }
4443
4444 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4445 Uri uri, int modeFlags) {
4446 synchronized(this) {
4447 final ProcessRecord r = getRecordForAppLocked(caller);
4448 if (r == null) {
4449 throw new SecurityException("Unable to find app for caller "
4450 + caller
4451 + " when granting permission to uri " + uri);
4452 }
4453 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004454 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 }
4456 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004457 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
4459
4460 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4461 null);
4462 }
4463 }
4464
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004465 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4467 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4468 HashMap<Uri, UriPermission> perms
4469 = mGrantedUriPermissions.get(perm.uid);
4470 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004471 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004472 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 perms.remove(perm.uri);
4474 if (perms.size() == 0) {
4475 mGrantedUriPermissions.remove(perm.uid);
4476 }
4477 }
4478 }
4479 }
4480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4482 int modeFlags) {
4483 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4484 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4485 if (modeFlags == 0) {
4486 return;
4487 }
4488
Joe Onorato8a9b2202010-02-26 18:56:32 -08004489 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004490 "Revoking all granted permissions to " + uri);
4491
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004492 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493
4494 final String authority = uri.getAuthority();
4495 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004496 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 if (cpr != null) {
4498 pi = cpr.info;
4499 } else {
4500 try {
4501 pi = pm.resolveContentProvider(authority,
4502 PackageManager.GET_URI_PERMISSION_PATTERNS);
4503 } catch (RemoteException ex) {
4504 }
4505 }
4506 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004507 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 return;
4509 }
4510
4511 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004512 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 // Right now, if you are not the original owner of the permission,
4514 // you are not allowed to revoke it.
4515 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4516 throw new SecurityException("Uid " + callingUid
4517 + " does not have permission to uri " + uri);
4518 //}
4519 }
4520
4521 // Go through all of the permissions and remove any that match.
4522 final List<String> SEGMENTS = uri.getPathSegments();
4523 if (SEGMENTS != null) {
4524 final int NS = SEGMENTS.size();
4525 int N = mGrantedUriPermissions.size();
4526 for (int i=0; i<N; i++) {
4527 HashMap<Uri, UriPermission> perms
4528 = mGrantedUriPermissions.valueAt(i);
4529 Iterator<UriPermission> it = perms.values().iterator();
4530 toploop:
4531 while (it.hasNext()) {
4532 UriPermission perm = it.next();
4533 Uri targetUri = perm.uri;
4534 if (!authority.equals(targetUri.getAuthority())) {
4535 continue;
4536 }
4537 List<String> targetSegments = targetUri.getPathSegments();
4538 if (targetSegments == null) {
4539 continue;
4540 }
4541 if (targetSegments.size() < NS) {
4542 continue;
4543 }
4544 for (int j=0; j<NS; j++) {
4545 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4546 continue toploop;
4547 }
4548 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004549 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004550 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 perm.clearModes(modeFlags);
4552 if (perm.modeFlags == 0) {
4553 it.remove();
4554 }
4555 }
4556 if (perms.size() == 0) {
4557 mGrantedUriPermissions.remove(
4558 mGrantedUriPermissions.keyAt(i));
4559 N--;
4560 i--;
4561 }
4562 }
4563 }
4564 }
4565
4566 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4567 int modeFlags) {
4568 synchronized(this) {
4569 final ProcessRecord r = getRecordForAppLocked(caller);
4570 if (r == null) {
4571 throw new SecurityException("Unable to find app for caller "
4572 + caller
4573 + " when revoking permission to uri " + uri);
4574 }
4575 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004576 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 return;
4578 }
4579
4580 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4581 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4582 if (modeFlags == 0) {
4583 return;
4584 }
4585
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004586 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587
4588 final String authority = uri.getAuthority();
4589 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004590 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 if (cpr != null) {
4592 pi = cpr.info;
4593 } else {
4594 try {
4595 pi = pm.resolveContentProvider(authority,
4596 PackageManager.GET_URI_PERMISSION_PATTERNS);
4597 } catch (RemoteException ex) {
4598 }
4599 }
4600 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004601 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 return;
4603 }
4604
4605 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4606 }
4607 }
4608
Dianne Hackborn7e269642010-08-25 19:50:20 -07004609 @Override
4610 public IBinder newUriPermissionOwner(String name) {
4611 synchronized(this) {
4612 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4613 return owner.getExternalTokenLocked();
4614 }
4615 }
4616
4617 @Override
4618 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4619 Uri uri, int modeFlags) {
4620 synchronized(this) {
4621 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4622 if (owner == null) {
4623 throw new IllegalArgumentException("Unknown owner: " + token);
4624 }
4625 if (fromUid != Binder.getCallingUid()) {
4626 if (Binder.getCallingUid() != Process.myUid()) {
4627 // Only system code can grant URI permissions on behalf
4628 // of other users.
4629 throw new SecurityException("nice try");
4630 }
4631 }
4632 if (targetPkg == null) {
4633 throw new IllegalArgumentException("null target");
4634 }
4635 if (uri == null) {
4636 throw new IllegalArgumentException("null uri");
4637 }
4638
4639 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4640 }
4641 }
4642
4643 @Override
4644 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4645 synchronized(this) {
4646 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4647 if (owner == null) {
4648 throw new IllegalArgumentException("Unknown owner: " + token);
4649 }
4650
4651 if (uri == null) {
4652 owner.removeUriPermissionsLocked(mode);
4653 } else {
4654 owner.removeUriPermissionLocked(uri, mode);
4655 }
4656 }
4657 }
4658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4660 synchronized (this) {
4661 ProcessRecord app =
4662 who != null ? getRecordForAppLocked(who) : null;
4663 if (app == null) return;
4664
4665 Message msg = Message.obtain();
4666 msg.what = WAIT_FOR_DEBUGGER_MSG;
4667 msg.obj = app;
4668 msg.arg1 = waiting ? 1 : 0;
4669 mHandler.sendMessage(msg);
4670 }
4671 }
4672
4673 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4674 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004675 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004677 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 }
4679
4680 // =========================================================
4681 // TASK MANAGEMENT
4682 // =========================================================
4683
4684 public List getTasks(int maxNum, int flags,
4685 IThumbnailReceiver receiver) {
4686 ArrayList list = new ArrayList();
4687
4688 PendingThumbnailsRecord pending = null;
4689 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004690 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691
4692 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004693 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4695 + ", receiver=" + receiver);
4696
4697 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4698 != PackageManager.PERMISSION_GRANTED) {
4699 if (receiver != null) {
4700 // If the caller wants to wait for pending thumbnails,
4701 // it ain't gonna get them.
4702 try {
4703 receiver.finished();
4704 } catch (RemoteException ex) {
4705 }
4706 }
4707 String msg = "Permission Denial: getTasks() from pid="
4708 + Binder.getCallingPid()
4709 + ", uid=" + Binder.getCallingUid()
4710 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004711 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 throw new SecurityException(msg);
4713 }
4714
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004715 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004716 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004717 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004718 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 CharSequence topDescription = null;
4720 TaskRecord curTask = null;
4721 int numActivities = 0;
4722 int numRunning = 0;
4723 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004724 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004726 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727
4728 // Initialize state for next task if needed.
4729 if (top == null ||
4730 (top.state == ActivityState.INITIALIZING
4731 && top.task == r.task)) {
4732 top = r;
4733 topDescription = r.description;
4734 curTask = r.task;
4735 numActivities = numRunning = 0;
4736 }
4737
4738 // Add 'r' into the current task.
4739 numActivities++;
4740 if (r.app != null && r.app.thread != null) {
4741 numRunning++;
4742 }
4743 if (topDescription == null) {
4744 topDescription = r.description;
4745 }
4746
Joe Onorato8a9b2202010-02-26 18:56:32 -08004747 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004748 TAG, r.intent.getComponent().flattenToShortString()
4749 + ": task=" + r.task);
4750
4751 // If the next one is a different task, generate a new
4752 // TaskInfo entry for what we have.
4753 if (next == null || next.task != curTask) {
4754 ActivityManager.RunningTaskInfo ci
4755 = new ActivityManager.RunningTaskInfo();
4756 ci.id = curTask.taskId;
4757 ci.baseActivity = r.intent.getComponent();
4758 ci.topActivity = top.intent.getComponent();
4759 ci.thumbnail = top.thumbnail;
4760 ci.description = topDescription;
4761 ci.numActivities = numActivities;
4762 ci.numRunning = numRunning;
4763 //System.out.println(
4764 // "#" + maxNum + ": " + " descr=" + ci.description);
4765 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004766 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 TAG, "State=" + top.state + "Idle=" + top.idle
4768 + " app=" + top.app
4769 + " thr=" + (top.app != null ? top.app.thread : null));
4770 if (top.state == ActivityState.RESUMED
4771 || top.state == ActivityState.PAUSING) {
4772 if (top.idle && top.app != null
4773 && top.app.thread != null) {
4774 topRecord = top;
4775 topThumbnail = top.app.thread;
4776 } else {
4777 top.thumbnailNeeded = true;
4778 }
4779 }
4780 if (pending == null) {
4781 pending = new PendingThumbnailsRecord(receiver);
4782 }
4783 pending.pendingRecords.add(top);
4784 }
4785 list.add(ci);
4786 maxNum--;
4787 top = null;
4788 }
4789 }
4790
4791 if (pending != null) {
4792 mPendingThumbnails.add(pending);
4793 }
4794 }
4795
Joe Onorato8a9b2202010-02-26 18:56:32 -08004796 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797
4798 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004799 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 try {
4801 topThumbnail.requestThumbnail(topRecord);
4802 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004803 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004804 sendPendingThumbnail(null, topRecord, null, null, true);
4805 }
4806 }
4807
4808 if (pending == null && receiver != null) {
4809 // In this case all thumbnails were available and the client
4810 // is being asked to be told when the remaining ones come in...
4811 // which is unusually, since the top-most currently running
4812 // activity should never have a canned thumbnail! Oh well.
4813 try {
4814 receiver.finished();
4815 } catch (RemoteException ex) {
4816 }
4817 }
4818
4819 return list;
4820 }
4821
4822 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4823 int flags) {
4824 synchronized (this) {
4825 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4826 "getRecentTasks()");
4827
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004828 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 final int N = mRecentTasks.size();
4831 ArrayList<ActivityManager.RecentTaskInfo> res
4832 = new ArrayList<ActivityManager.RecentTaskInfo>(
4833 maxNum < N ? maxNum : N);
4834 for (int i=0; i<N && maxNum > 0; i++) {
4835 TaskRecord tr = mRecentTasks.get(i);
4836 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4837 || (tr.intent == null)
4838 || ((tr.intent.getFlags()
4839 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4840 ActivityManager.RecentTaskInfo rti
4841 = new ActivityManager.RecentTaskInfo();
4842 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4843 rti.baseIntent = new Intent(
4844 tr.intent != null ? tr.intent : tr.affinityIntent);
4845 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004846
4847 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4848 // Check whether this activity is currently available.
4849 try {
4850 if (rti.origActivity != null) {
4851 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4852 continue;
4853 }
4854 } else if (rti.baseIntent != null) {
4855 if (pm.queryIntentActivities(rti.baseIntent,
4856 null, 0) == null) {
4857 continue;
4858 }
4859 }
4860 } catch (RemoteException e) {
4861 // Will never happen.
4862 }
4863 }
4864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 res.add(rti);
4866 maxNum--;
4867 }
4868 }
4869 return res;
4870 }
4871 }
4872
4873 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4874 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004875 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 TaskRecord jt = startTask;
4877
4878 // First look backwards
4879 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004880 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 if (r.task != jt) {
4882 jt = r.task;
4883 if (affinity.equals(jt.affinity)) {
4884 return j;
4885 }
4886 }
4887 }
4888
4889 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004890 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 jt = startTask;
4892 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004893 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 if (r.task != jt) {
4895 if (affinity.equals(jt.affinity)) {
4896 return j;
4897 }
4898 jt = r.task;
4899 }
4900 }
4901
4902 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004903 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 return N-1;
4905 }
4906
4907 return -1;
4908 }
4909
4910 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004911 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 */
4913 public void moveTaskToFront(int task) {
4914 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4915 "moveTaskToFront()");
4916
4917 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004918 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4919 Binder.getCallingUid(), "Task to front")) {
4920 return;
4921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 final long origId = Binder.clearCallingIdentity();
4923 try {
4924 int N = mRecentTasks.size();
4925 for (int i=0; i<N; i++) {
4926 TaskRecord tr = mRecentTasks.get(i);
4927 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004928 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 return;
4930 }
4931 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004932 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4933 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004934 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004935 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 return;
4937 }
4938 }
4939 } finally {
4940 Binder.restoreCallingIdentity(origId);
4941 }
4942 }
4943 }
4944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 public void moveTaskToBack(int task) {
4946 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4947 "moveTaskToBack()");
4948
4949 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004950 if (mMainStack.mResumedActivity != null
4951 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004952 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4953 Binder.getCallingUid(), "Task to back")) {
4954 return;
4955 }
4956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004958 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 Binder.restoreCallingIdentity(origId);
4960 }
4961 }
4962
4963 /**
4964 * Moves an activity, and all of the other activities within the same task, to the bottom
4965 * of the history stack. The activity's order within the task is unchanged.
4966 *
4967 * @param token A reference to the activity we wish to move
4968 * @param nonRoot If false then this only works if the activity is the root
4969 * of a task; if true it will work for any activity in a task.
4970 * @return Returns true if the move completed, false if not.
4971 */
4972 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4973 synchronized(this) {
4974 final long origId = Binder.clearCallingIdentity();
4975 int taskId = getTaskForActivityLocked(token, !nonRoot);
4976 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004977 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 }
4979 Binder.restoreCallingIdentity(origId);
4980 }
4981 return false;
4982 }
4983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 public void moveTaskBackwards(int task) {
4985 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4986 "moveTaskBackwards()");
4987
4988 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004989 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4990 Binder.getCallingUid(), "Task backwards")) {
4991 return;
4992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 final long origId = Binder.clearCallingIdentity();
4994 moveTaskBackwardsLocked(task);
4995 Binder.restoreCallingIdentity(origId);
4996 }
4997 }
4998
4999 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005000 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 }
5002
5003 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5004 synchronized(this) {
5005 return getTaskForActivityLocked(token, onlyRoot);
5006 }
5007 }
5008
5009 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005010 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 TaskRecord lastTask = null;
5012 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005013 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 if (r == token) {
5015 if (!onlyRoot || lastTask != r.task) {
5016 return r.task.taskId;
5017 }
5018 return -1;
5019 }
5020 lastTask = r.task;
5021 }
5022
5023 return -1;
5024 }
5025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 public void finishOtherInstances(IBinder token, ComponentName className) {
5027 synchronized(this) {
5028 final long origId = Binder.clearCallingIdentity();
5029
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005030 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 TaskRecord lastTask = null;
5032 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005033 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 if (r.realActivity.equals(className)
5035 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005036 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 null, "others")) {
5038 i--;
5039 N--;
5040 }
5041 }
5042 lastTask = r.task;
5043 }
5044
5045 Binder.restoreCallingIdentity(origId);
5046 }
5047 }
5048
5049 // =========================================================
5050 // THUMBNAILS
5051 // =========================================================
5052
5053 public void reportThumbnail(IBinder token,
5054 Bitmap thumbnail, CharSequence description) {
5055 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5056 final long origId = Binder.clearCallingIdentity();
5057 sendPendingThumbnail(null, token, thumbnail, description, true);
5058 Binder.restoreCallingIdentity(origId);
5059 }
5060
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005061 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 Bitmap thumbnail, CharSequence description, boolean always) {
5063 TaskRecord task = null;
5064 ArrayList receivers = null;
5065
5066 //System.out.println("Send pending thumbnail: " + r);
5067
5068 synchronized(this) {
5069 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005070 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 if (index < 0) {
5072 return;
5073 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005074 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 }
5076 if (thumbnail == null) {
5077 thumbnail = r.thumbnail;
5078 description = r.description;
5079 }
5080 if (thumbnail == null && !always) {
5081 // If there is no thumbnail, and this entry is not actually
5082 // going away, then abort for now and pick up the next
5083 // thumbnail we get.
5084 return;
5085 }
5086 task = r.task;
5087
5088 int N = mPendingThumbnails.size();
5089 int i=0;
5090 while (i<N) {
5091 PendingThumbnailsRecord pr =
5092 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5093 //System.out.println("Looking in " + pr.pendingRecords);
5094 if (pr.pendingRecords.remove(r)) {
5095 if (receivers == null) {
5096 receivers = new ArrayList();
5097 }
5098 receivers.add(pr);
5099 if (pr.pendingRecords.size() == 0) {
5100 pr.finished = true;
5101 mPendingThumbnails.remove(i);
5102 N--;
5103 continue;
5104 }
5105 }
5106 i++;
5107 }
5108 }
5109
5110 if (receivers != null) {
5111 final int N = receivers.size();
5112 for (int i=0; i<N; i++) {
5113 try {
5114 PendingThumbnailsRecord pr =
5115 (PendingThumbnailsRecord)receivers.get(i);
5116 pr.receiver.newThumbnail(
5117 task != null ? task.taskId : -1, thumbnail, description);
5118 if (pr.finished) {
5119 pr.receiver.finished();
5120 }
5121 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005122 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 }
5124 }
5125 }
5126 }
5127
5128 // =========================================================
5129 // CONTENT PROVIDERS
5130 // =========================================================
5131
5132 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5133 List providers = null;
5134 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005135 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005137 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 } catch (RemoteException ex) {
5139 }
5140 if (providers != null) {
5141 final int N = providers.size();
5142 for (int i=0; i<N; i++) {
5143 ProviderInfo cpi =
5144 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005145 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 if (cpr == null) {
5147 cpr = new ContentProviderRecord(cpi, app.info);
5148 mProvidersByClass.put(cpi.name, cpr);
5149 }
5150 app.pubProviders.put(cpi.name, cpr);
5151 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005152 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
5154 }
5155 return providers;
5156 }
5157
5158 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005159 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5161 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5162 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5163 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005164 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 return null;
5166 }
5167 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5168 cpi.exported ? -1 : cpi.applicationInfo.uid)
5169 == PackageManager.PERMISSION_GRANTED) {
5170 return null;
5171 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005172
5173 PathPermission[] pps = cpi.pathPermissions;
5174 if (pps != null) {
5175 int i = pps.length;
5176 while (i > 0) {
5177 i--;
5178 PathPermission pp = pps[i];
5179 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5180 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005181 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005182 return null;
5183 }
5184 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5185 cpi.exported ? -1 : cpi.applicationInfo.uid)
5186 == PackageManager.PERMISSION_GRANTED) {
5187 return null;
5188 }
5189 }
5190 }
5191
Dianne Hackbornb424b632010-08-18 15:59:05 -07005192 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5193 if (perms != null) {
5194 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5195 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5196 return null;
5197 }
5198 }
5199 }
5200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 String msg = "Permission Denial: opening provider " + cpi.name
5202 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5203 + ", uid=" + callingUid + ") requires "
5204 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005205 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 return msg;
5207 }
5208
5209 private final ContentProviderHolder getContentProviderImpl(
5210 IApplicationThread caller, String name) {
5211 ContentProviderRecord cpr;
5212 ProviderInfo cpi = null;
5213
5214 synchronized(this) {
5215 ProcessRecord r = null;
5216 if (caller != null) {
5217 r = getRecordForAppLocked(caller);
5218 if (r == null) {
5219 throw new SecurityException(
5220 "Unable to find app for caller " + caller
5221 + " (pid=" + Binder.getCallingPid()
5222 + ") when getting content provider " + name);
5223 }
5224 }
5225
5226 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005227 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 if (cpr != null) {
5229 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005230 String msg;
5231 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5232 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 }
5234
5235 if (r != null && cpr.canRunHere(r)) {
5236 // This provider has been published or is in the process
5237 // of being published... but it is also allowed to run
5238 // in the caller's process, so don't make a connection
5239 // and just let the caller instantiate its own instance.
5240 if (cpr.provider != null) {
5241 // don't give caller the provider object, it needs
5242 // to make its own.
5243 cpr = new ContentProviderRecord(cpr);
5244 }
5245 return cpr;
5246 }
5247
5248 final long origId = Binder.clearCallingIdentity();
5249
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005250 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 // return it right away.
5252 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005253 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005254 "Adding provider requested by "
5255 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005256 + cpr.info.processName);
5257 Integer cnt = r.conProviders.get(cpr);
5258 if (cnt == null) {
5259 r.conProviders.put(cpr, new Integer(1));
5260 } else {
5261 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005264 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5265 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005266 // make sure to count it as being accessed and thus
5267 // back up on the LRU list. This is good because
5268 // content providers are often expensive to start.
5269 updateLruProcessLocked(cpr.app, false, true);
5270 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005271 } else {
5272 cpr.externals++;
5273 }
5274
5275 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 updateOomAdjLocked(cpr.app);
5277 }
5278
5279 Binder.restoreCallingIdentity(origId);
5280
5281 } else {
5282 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005283 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005284 resolveContentProvider(name,
5285 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 } catch (RemoteException ex) {
5287 }
5288 if (cpi == null) {
5289 return null;
5290 }
5291
Dianne Hackbornb424b632010-08-18 15:59:05 -07005292 String msg;
5293 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5294 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005297 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005298 && !cpi.processName.equals("system")) {
5299 // If this content provider does not run in the system
5300 // process, and the system is not yet ready to run other
5301 // processes, then fail fast instead of hanging.
5302 throw new IllegalArgumentException(
5303 "Attempt to launch content provider before system ready");
5304 }
5305
Dianne Hackborn860755f2010-06-03 18:47:52 -07005306 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 final boolean firstClass = cpr == null;
5308 if (firstClass) {
5309 try {
5310 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005311 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 getApplicationInfo(
5313 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005314 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005316 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 + cpi.name);
5318 return null;
5319 }
5320 cpr = new ContentProviderRecord(cpi, ai);
5321 } catch (RemoteException ex) {
5322 // pm is in same process, this will never happen.
5323 }
5324 }
5325
5326 if (r != null && cpr.canRunHere(r)) {
5327 // If this is a multiprocess provider, then just return its
5328 // info and allow the caller to instantiate it. Only do
5329 // this if the provider is the same user as the caller's
5330 // process, or can run as root (so can be in any process).
5331 return cpr;
5332 }
5333
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005334 if (DEBUG_PROVIDER) {
5335 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005336 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005337 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 }
5339
5340 // This is single process, and our app is now connecting to it.
5341 // See if we are already in the process of launching this
5342 // provider.
5343 final int N = mLaunchingProviders.size();
5344 int i;
5345 for (i=0; i<N; i++) {
5346 if (mLaunchingProviders.get(i) == cpr) {
5347 break;
5348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 }
5350
5351 // If the provider is not already being launched, then get it
5352 // started.
5353 if (i >= N) {
5354 final long origId = Binder.clearCallingIdentity();
5355 ProcessRecord proc = startProcessLocked(cpi.processName,
5356 cpr.appInfo, false, 0, "content provider",
5357 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005358 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005360 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 + cpi.applicationInfo.packageName + "/"
5362 + cpi.applicationInfo.uid + " for provider "
5363 + name + ": process is bad");
5364 return null;
5365 }
5366 cpr.launchingApp = proc;
5367 mLaunchingProviders.add(cpr);
5368 Binder.restoreCallingIdentity(origId);
5369 }
5370
5371 // Make sure the provider is published (the same provider class
5372 // may be published under multiple names).
5373 if (firstClass) {
5374 mProvidersByClass.put(cpi.name, cpr);
5375 }
5376 mProvidersByName.put(name, cpr);
5377
5378 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005379 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005380 "Adding provider requested by "
5381 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005382 + cpr.info.processName);
5383 Integer cnt = r.conProviders.get(cpr);
5384 if (cnt == null) {
5385 r.conProviders.put(cpr, new Integer(1));
5386 } else {
5387 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 cpr.clients.add(r);
5390 } else {
5391 cpr.externals++;
5392 }
5393 }
5394 }
5395
5396 // Wait for the provider to be published...
5397 synchronized (cpr) {
5398 while (cpr.provider == null) {
5399 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 + cpi.applicationInfo.packageName + "/"
5402 + cpi.applicationInfo.uid + " for provider "
5403 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005404 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 cpi.applicationInfo.packageName,
5406 cpi.applicationInfo.uid, name);
5407 return null;
5408 }
5409 try {
5410 cpr.wait();
5411 } catch (InterruptedException ex) {
5412 }
5413 }
5414 }
5415 return cpr;
5416 }
5417
5418 public final ContentProviderHolder getContentProvider(
5419 IApplicationThread caller, String name) {
5420 if (caller == null) {
5421 String msg = "null IApplicationThread when getting content provider "
5422 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 throw new SecurityException(msg);
5425 }
5426
5427 return getContentProviderImpl(caller, name);
5428 }
5429
5430 private ContentProviderHolder getContentProviderExternal(String name) {
5431 return getContentProviderImpl(null, name);
5432 }
5433
5434 /**
5435 * Drop a content provider from a ProcessRecord's bookkeeping
5436 * @param cpr
5437 */
5438 public void removeContentProvider(IApplicationThread caller, String name) {
5439 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005440 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005442 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005443 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005444 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 return;
5446 }
5447 final ProcessRecord r = getRecordForAppLocked(caller);
5448 if (r == null) {
5449 throw new SecurityException(
5450 "Unable to find app for caller " + caller +
5451 " when removing content provider " + name);
5452 }
5453 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005454 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005455 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005456 + r.info.processName + " from process "
5457 + localCpr.appInfo.processName);
5458 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005460 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005461 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 return;
5463 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005464 Integer cnt = r.conProviders.get(localCpr);
5465 if (cnt == null || cnt.intValue() <= 1) {
5466 localCpr.clients.remove(r);
5467 r.conProviders.remove(localCpr);
5468 } else {
5469 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 }
5472 updateOomAdjLocked();
5473 }
5474 }
5475
5476 private void removeContentProviderExternal(String name) {
5477 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005478 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 if(cpr == null) {
5480 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005481 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 return;
5483 }
5484
5485 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005486 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 localCpr.externals--;
5488 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005489 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 }
5491 updateOomAdjLocked();
5492 }
5493 }
5494
5495 public final void publishContentProviders(IApplicationThread caller,
5496 List<ContentProviderHolder> providers) {
5497 if (providers == null) {
5498 return;
5499 }
5500
5501 synchronized(this) {
5502 final ProcessRecord r = getRecordForAppLocked(caller);
5503 if (r == null) {
5504 throw new SecurityException(
5505 "Unable to find app for caller " + caller
5506 + " (pid=" + Binder.getCallingPid()
5507 + ") when publishing content providers");
5508 }
5509
5510 final long origId = Binder.clearCallingIdentity();
5511
5512 final int N = providers.size();
5513 for (int i=0; i<N; i++) {
5514 ContentProviderHolder src = providers.get(i);
5515 if (src == null || src.info == null || src.provider == null) {
5516 continue;
5517 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005518 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 if (dst != null) {
5520 mProvidersByClass.put(dst.info.name, dst);
5521 String names[] = dst.info.authority.split(";");
5522 for (int j = 0; j < names.length; j++) {
5523 mProvidersByName.put(names[j], dst);
5524 }
5525
5526 int NL = mLaunchingProviders.size();
5527 int j;
5528 for (j=0; j<NL; j++) {
5529 if (mLaunchingProviders.get(j) == dst) {
5530 mLaunchingProviders.remove(j);
5531 j--;
5532 NL--;
5533 }
5534 }
5535 synchronized (dst) {
5536 dst.provider = src.provider;
5537 dst.app = r;
5538 dst.notifyAll();
5539 }
5540 updateOomAdjLocked(r);
5541 }
5542 }
5543
5544 Binder.restoreCallingIdentity(origId);
5545 }
5546 }
5547
5548 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005549 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005550 synchronized (mSelf) {
5551 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5552 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005553 if (providers != null) {
5554 for (int i=providers.size()-1; i>=0; i--) {
5555 ProviderInfo pi = (ProviderInfo)providers.get(i);
5556 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5557 Slog.w(TAG, "Not installing system proc provider " + pi.name
5558 + ": not system .apk");
5559 providers.remove(i);
5560 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005561 }
5562 }
5563 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005564 if (providers != null) {
5565 mSystemThread.installSystemProviders(providers);
5566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 }
5568
Dianne Hackborn8313fc72010-09-26 18:34:53 -07005569 /**
5570 * Allows app to retrieve the MIME type of a URI without having permission
5571 * to access its content provider.
5572 *
5573 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5574 *
5575 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5576 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5577 */
5578 public String getProviderMimeType(Uri uri) {
5579 final String name = uri.getAuthority();
5580 final long ident = Binder.clearCallingIdentity();
5581 ContentProviderHolder holder = null;
5582
5583 try {
5584 holder = getContentProviderExternal(name);
5585 if (holder != null) {
5586 return holder.provider.getType(uri);
5587 }
5588 } catch (RemoteException e) {
5589 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5590 return null;
5591 } finally {
5592 if (holder != null) {
5593 removeContentProviderExternal(name);
5594 }
5595 Binder.restoreCallingIdentity(ident);
5596 }
5597
5598 return null;
5599 }
5600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 // =========================================================
5602 // GLOBAL MANAGEMENT
5603 // =========================================================
5604
5605 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5606 ApplicationInfo info, String customProcess) {
5607 String proc = customProcess != null ? customProcess : info.processName;
5608 BatteryStatsImpl.Uid.Proc ps = null;
5609 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5610 synchronized (stats) {
5611 ps = stats.getProcessStatsLocked(info.uid, proc);
5612 }
5613 return new ProcessRecord(ps, thread, info, proc);
5614 }
5615
5616 final ProcessRecord addAppLocked(ApplicationInfo info) {
5617 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5618
5619 if (app == null) {
5620 app = newProcessRecordLocked(null, info, null);
5621 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005622 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 }
5624
5625 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5626 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5627 app.persistent = true;
5628 app.maxAdj = CORE_SERVER_ADJ;
5629 }
5630 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5631 mPersistentStartingProcesses.add(app);
5632 startProcessLocked(app, "added application", app.processName);
5633 }
5634
5635 return app;
5636 }
5637
5638 public void unhandledBack() {
5639 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5640 "unhandledBack()");
5641
5642 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005643 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005644 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 TAG, "Performing unhandledBack(): stack size = " + count);
5646 if (count > 1) {
5647 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005648 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5650 Binder.restoreCallingIdentity(origId);
5651 }
5652 }
5653 }
5654
5655 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5656 String name = uri.getAuthority();
5657 ContentProviderHolder cph = getContentProviderExternal(name);
5658 ParcelFileDescriptor pfd = null;
5659 if (cph != null) {
5660 // We record the binder invoker's uid in thread-local storage before
5661 // going to the content provider to open the file. Later, in the code
5662 // that handles all permissions checks, we look for this uid and use
5663 // that rather than the Activity Manager's own uid. The effect is that
5664 // we do the check against the caller's permissions even though it looks
5665 // to the content provider like the Activity Manager itself is making
5666 // the request.
5667 sCallerIdentity.set(new Identity(
5668 Binder.getCallingPid(), Binder.getCallingUid()));
5669 try {
5670 pfd = cph.provider.openFile(uri, "r");
5671 } catch (FileNotFoundException e) {
5672 // do nothing; pfd will be returned null
5673 } finally {
5674 // Ensure that whatever happens, we clean up the identity state
5675 sCallerIdentity.remove();
5676 }
5677
5678 // We've got the fd now, so we're done with the provider.
5679 removeContentProviderExternal(name);
5680 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005681 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683 return pfd;
5684 }
5685
5686 public void goingToSleep() {
5687 synchronized(this) {
5688 mSleeping = true;
5689 mWindowManager.setEventDispatching(false);
5690
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005691 if (mMainStack.mResumedActivity != null) {
5692 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005694 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005696
5697 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005698 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005699 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5700 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005701 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 }
5703 }
5704
Dianne Hackborn55280a92009-05-07 15:53:46 -07005705 public boolean shutdown(int timeout) {
5706 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5707 != PackageManager.PERMISSION_GRANTED) {
5708 throw new SecurityException("Requires permission "
5709 + android.Manifest.permission.SHUTDOWN);
5710 }
5711
5712 boolean timedout = false;
5713
5714 synchronized(this) {
5715 mShuttingDown = true;
5716 mWindowManager.setEventDispatching(false);
5717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005718 if (mMainStack.mResumedActivity != null) {
5719 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005720 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005721 while (mMainStack.mResumedActivity != null
5722 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005723 long delay = endTime - System.currentTimeMillis();
5724 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005725 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005726 timedout = true;
5727 break;
5728 }
5729 try {
5730 this.wait();
5731 } catch (InterruptedException e) {
5732 }
5733 }
5734 }
5735 }
5736
5737 mUsageStatsService.shutdown();
5738 mBatteryStatsService.shutdown();
5739
5740 return timedout;
5741 }
5742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 public void wakingUp() {
5744 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005745 if (mMainStack.mGoingToSleep.isHeld()) {
5746 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747 }
5748 mWindowManager.setEventDispatching(true);
5749 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005750 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 }
5752 }
5753
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005754 public void stopAppSwitches() {
5755 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5756 != PackageManager.PERMISSION_GRANTED) {
5757 throw new SecurityException("Requires permission "
5758 + android.Manifest.permission.STOP_APP_SWITCHES);
5759 }
5760
5761 synchronized(this) {
5762 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5763 + APP_SWITCH_DELAY_TIME;
5764 mDidAppSwitch = false;
5765 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5766 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5767 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5768 }
5769 }
5770
5771 public void resumeAppSwitches() {
5772 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5773 != PackageManager.PERMISSION_GRANTED) {
5774 throw new SecurityException("Requires permission "
5775 + android.Manifest.permission.STOP_APP_SWITCHES);
5776 }
5777
5778 synchronized(this) {
5779 // Note that we don't execute any pending app switches... we will
5780 // let those wait until either the timeout, or the next start
5781 // activity request.
5782 mAppSwitchesAllowedTime = 0;
5783 }
5784 }
5785
5786 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5787 String name) {
5788 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5789 return true;
5790 }
5791
5792 final int perm = checkComponentPermission(
5793 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5794 callingUid, -1);
5795 if (perm == PackageManager.PERMISSION_GRANTED) {
5796 return true;
5797 }
5798
Joe Onorato8a9b2202010-02-26 18:56:32 -08005799 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005800 return false;
5801 }
5802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 public void setDebugApp(String packageName, boolean waitForDebugger,
5804 boolean persistent) {
5805 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5806 "setDebugApp()");
5807
5808 // Note that this is not really thread safe if there are multiple
5809 // callers into it at the same time, but that's not a situation we
5810 // care about.
5811 if (persistent) {
5812 final ContentResolver resolver = mContext.getContentResolver();
5813 Settings.System.putString(
5814 resolver, Settings.System.DEBUG_APP,
5815 packageName);
5816 Settings.System.putInt(
5817 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5818 waitForDebugger ? 1 : 0);
5819 }
5820
5821 synchronized (this) {
5822 if (!persistent) {
5823 mOrigDebugApp = mDebugApp;
5824 mOrigWaitForDebugger = mWaitForDebugger;
5825 }
5826 mDebugApp = packageName;
5827 mWaitForDebugger = waitForDebugger;
5828 mDebugTransient = !persistent;
5829 if (packageName != null) {
5830 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005831 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 Binder.restoreCallingIdentity(origId);
5833 }
5834 }
5835 }
5836
5837 public void setAlwaysFinish(boolean enabled) {
5838 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5839 "setAlwaysFinish()");
5840
5841 Settings.System.putInt(
5842 mContext.getContentResolver(),
5843 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5844
5845 synchronized (this) {
5846 mAlwaysFinishActivities = enabled;
5847 }
5848 }
5849
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005850 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005852 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005854 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005855 }
5856 }
5857
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005858 public boolean isUserAMonkey() {
5859 // For now the fact that there is a controller implies
5860 // we have a monkey.
5861 synchronized (this) {
5862 return mController != null;
5863 }
5864 }
5865
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005866 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005867 synchronized (this) {
5868 mWatchers.register(watcher);
5869 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005870 }
5871
5872 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005873 synchronized (this) {
5874 mWatchers.unregister(watcher);
5875 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005876 }
5877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 public final void enterSafeMode() {
5879 synchronized(this) {
5880 // It only makes sense to do this before the system is ready
5881 // and started launching other packages.
5882 if (!mSystemReady) {
5883 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005884 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 } catch (RemoteException e) {
5886 }
5887
5888 View v = LayoutInflater.from(mContext).inflate(
5889 com.android.internal.R.layout.safe_mode, null);
5890 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown2d3f1592010-10-15 00:54:27 -07005891 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5893 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5894 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5895 lp.format = v.getBackground().getOpacity();
5896 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5897 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5898 ((WindowManager)mContext.getSystemService(
5899 Context.WINDOW_SERVICE)).addView(v, lp);
5900 }
5901 }
5902 }
5903
5904 public void noteWakeupAlarm(IIntentSender sender) {
5905 if (!(sender instanceof PendingIntentRecord)) {
5906 return;
5907 }
5908 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5909 synchronized (stats) {
5910 if (mBatteryStatsService.isOnBattery()) {
5911 mBatteryStatsService.enforceCallingPermission();
5912 PendingIntentRecord rec = (PendingIntentRecord)sender;
5913 int MY_UID = Binder.getCallingUid();
5914 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5915 BatteryStatsImpl.Uid.Pkg pkg =
5916 stats.getPackageStatsLocked(uid, rec.key.packageName);
5917 pkg.incWakeupsLocked();
5918 }
5919 }
5920 }
5921
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005922 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005924 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005926 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005927 // XXX Note: don't acquire main activity lock here, because the window
5928 // manager calls in with its locks held.
5929
5930 boolean killed = false;
5931 synchronized (mPidsSelfLocked) {
5932 int[] types = new int[pids.length];
5933 int worstType = 0;
5934 for (int i=0; i<pids.length; i++) {
5935 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5936 if (proc != null) {
5937 int type = proc.setAdj;
5938 types[i] = type;
5939 if (type > worstType) {
5940 worstType = type;
5941 }
5942 }
5943 }
5944
5945 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5946 // then constrain it so we will kill all hidden procs.
5947 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5948 worstType = HIDDEN_APP_MIN_ADJ;
5949 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005950 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 for (int i=0; i<pids.length; i++) {
5952 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5953 if (proc == null) {
5954 continue;
5955 }
5956 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005957 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005958 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005959 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5960 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005962 proc.killedBackground = true;
5963 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 }
5965 }
5966 }
5967 return killed;
5968 }
5969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 public final void startRunning(String pkg, String cls, String action,
5971 String data) {
5972 synchronized(this) {
5973 if (mStartRunning) {
5974 return;
5975 }
5976 mStartRunning = true;
5977 mTopComponent = pkg != null && cls != null
5978 ? new ComponentName(pkg, cls) : null;
5979 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5980 mTopData = data;
5981 if (!mSystemReady) {
5982 return;
5983 }
5984 }
5985
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005986 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 }
5988
5989 private void retrieveSettings() {
5990 final ContentResolver resolver = mContext.getContentResolver();
5991 String debugApp = Settings.System.getString(
5992 resolver, Settings.System.DEBUG_APP);
5993 boolean waitForDebugger = Settings.System.getInt(
5994 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5995 boolean alwaysFinishActivities = Settings.System.getInt(
5996 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5997
5998 Configuration configuration = new Configuration();
5999 Settings.System.getConfiguration(resolver, configuration);
6000
6001 synchronized (this) {
6002 mDebugApp = mOrigDebugApp = debugApp;
6003 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6004 mAlwaysFinishActivities = alwaysFinishActivities;
6005 // This happens before any activities are started, so we can
6006 // change mConfiguration in-place.
6007 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006008 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006009 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 }
6011 }
6012
6013 public boolean testIsSystemReady() {
6014 // no need to synchronize(this) just to read & return the value
6015 return mSystemReady;
6016 }
6017
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006018 private static File getCalledPreBootReceiversFile() {
6019 File dataDir = Environment.getDataDirectory();
6020 File systemDir = new File(dataDir, "system");
6021 File fname = new File(systemDir, "called_pre_boots.dat");
6022 return fname;
6023 }
6024
6025 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6026 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6027 File file = getCalledPreBootReceiversFile();
6028 FileInputStream fis = null;
6029 try {
6030 fis = new FileInputStream(file);
6031 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6032 int vers = dis.readInt();
6033 String codename = dis.readUTF();
6034 if (vers == android.os.Build.VERSION.SDK_INT
6035 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6036 int num = dis.readInt();
6037 while (num > 0) {
6038 num--;
6039 String pkg = dis.readUTF();
6040 String cls = dis.readUTF();
6041 lastDoneReceivers.add(new ComponentName(pkg, cls));
6042 }
6043 }
6044 } catch (FileNotFoundException e) {
6045 } catch (IOException e) {
6046 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6047 } finally {
6048 if (fis != null) {
6049 try {
6050 fis.close();
6051 } catch (IOException e) {
6052 }
6053 }
6054 }
6055 return lastDoneReceivers;
6056 }
6057
6058 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6059 File file = getCalledPreBootReceiversFile();
6060 FileOutputStream fos = null;
6061 DataOutputStream dos = null;
6062 try {
6063 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6064 fos = new FileOutputStream(file);
6065 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6066 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6067 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6068 dos.writeInt(list.size());
6069 for (int i=0; i<list.size(); i++) {
6070 dos.writeUTF(list.get(i).getPackageName());
6071 dos.writeUTF(list.get(i).getClassName());
6072 }
6073 } catch (IOException e) {
6074 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6075 file.delete();
6076 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006077 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006078 if (dos != null) {
6079 try {
6080 dos.close();
6081 } catch (IOException e) {
6082 // TODO Auto-generated catch block
6083 e.printStackTrace();
6084 }
6085 }
6086 }
6087 }
6088
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006089 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 // In the simulator, startRunning will never have been called, which
6091 // normally sets a few crucial variables. Do it here instead.
6092 if (!Process.supportsProcesses()) {
6093 mStartRunning = true;
6094 mTopAction = Intent.ACTION_MAIN;
6095 }
6096
6097 synchronized(this) {
6098 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006099 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 return;
6101 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006102
6103 // Check to see if there are any update receivers to run.
6104 if (!mDidUpdate) {
6105 if (mWaitingUpdate) {
6106 return;
6107 }
6108 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6109 List<ResolveInfo> ris = null;
6110 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006111 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006112 intent, null, 0);
6113 } catch (RemoteException e) {
6114 }
6115 if (ris != null) {
6116 for (int i=ris.size()-1; i>=0; i--) {
6117 if ((ris.get(i).activityInfo.applicationInfo.flags
6118 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6119 ris.remove(i);
6120 }
6121 }
6122 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006123
6124 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6125
6126 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006127 for (int i=0; i<ris.size(); i++) {
6128 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006129 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6130 if (lastDoneReceivers.contains(comp)) {
6131 ris.remove(i);
6132 i--;
6133 }
6134 }
6135
6136 for (int i=0; i<ris.size(); i++) {
6137 ActivityInfo ai = ris.get(i).activityInfo;
6138 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6139 doneReceivers.add(comp);
6140 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006141 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006142 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006143 finisher = new IIntentReceiver.Stub() {
6144 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006145 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006146 boolean sticky) {
6147 // The raw IIntentReceiver interface is called
6148 // with the AM lock held, so redispatch to
6149 // execute our code without the lock.
6150 mHandler.post(new Runnable() {
6151 public void run() {
6152 synchronized (ActivityManagerService.this) {
6153 mDidUpdate = true;
6154 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006155 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006156 systemReady(goingCallback);
6157 }
6158 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006159 }
6160 };
6161 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006162 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006163 broadcastIntentLocked(null, null, intent, null, finisher,
6164 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006165 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006166 mWaitingUpdate = true;
6167 }
6168 }
6169 }
6170 if (mWaitingUpdate) {
6171 return;
6172 }
6173 mDidUpdate = true;
6174 }
6175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 mSystemReady = true;
6177 if (!mStartRunning) {
6178 return;
6179 }
6180 }
6181
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006182 ArrayList<ProcessRecord> procsToKill = null;
6183 synchronized(mPidsSelfLocked) {
6184 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6185 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6186 if (!isAllowedWhileBooting(proc.info)){
6187 if (procsToKill == null) {
6188 procsToKill = new ArrayList<ProcessRecord>();
6189 }
6190 procsToKill.add(proc);
6191 }
6192 }
6193 }
6194
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006195 synchronized(this) {
6196 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006197 for (int i=procsToKill.size()-1; i>=0; i--) {
6198 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006199 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006200 removeProcessLocked(proc, true);
6201 }
6202 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006203
6204 // Now that we have cleaned up any update processes, we
6205 // are ready to start launching real processes and know that
6206 // we won't trample on them any more.
6207 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006208 }
6209
Joe Onorato8a9b2202010-02-26 18:56:32 -08006210 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006211 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 SystemClock.uptimeMillis());
6213
6214 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006215 // Make sure we have no pre-ready processes sitting around.
6216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006217 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6218 ResolveInfo ri = mContext.getPackageManager()
6219 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006220 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 CharSequence errorMsg = null;
6222 if (ri != null) {
6223 ActivityInfo ai = ri.activityInfo;
6224 ApplicationInfo app = ai.applicationInfo;
6225 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6226 mTopAction = Intent.ACTION_FACTORY_TEST;
6227 mTopData = null;
6228 mTopComponent = new ComponentName(app.packageName,
6229 ai.name);
6230 } else {
6231 errorMsg = mContext.getResources().getText(
6232 com.android.internal.R.string.factorytest_not_system);
6233 }
6234 } else {
6235 errorMsg = mContext.getResources().getText(
6236 com.android.internal.R.string.factorytest_no_action);
6237 }
6238 if (errorMsg != null) {
6239 mTopAction = null;
6240 mTopData = null;
6241 mTopComponent = null;
6242 Message msg = Message.obtain();
6243 msg.what = SHOW_FACTORY_ERROR_MSG;
6244 msg.getData().putCharSequence("msg", errorMsg);
6245 mHandler.sendMessage(msg);
6246 }
6247 }
6248 }
6249
6250 retrieveSettings();
6251
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006252 if (goingCallback != null) goingCallback.run();
6253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006254 synchronized (this) {
6255 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6256 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006257 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006258 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 if (apps != null) {
6260 int N = apps.size();
6261 int i;
6262 for (i=0; i<N; i++) {
6263 ApplicationInfo info
6264 = (ApplicationInfo)apps.get(i);
6265 if (info != null &&
6266 !info.packageName.equals("android")) {
6267 addAppLocked(info);
6268 }
6269 }
6270 }
6271 } catch (RemoteException ex) {
6272 // pm is in same process, this will never happen.
6273 }
6274 }
6275
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006276 // Start up initial activity.
6277 mBooting = true;
6278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006280 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 Message msg = Message.obtain();
6282 msg.what = SHOW_UID_ERROR_MSG;
6283 mHandler.sendMessage(msg);
6284 }
6285 } catch (RemoteException e) {
6286 }
6287
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006288 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 }
6290 }
6291
Dan Egnorb7f03672009-12-09 16:22:32 -08006292 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006293 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006295 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006296 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 startAppProblemLocked(app);
6298 app.stopFreezingAllLocked();
6299 return handleAppCrashLocked(app);
6300 }
6301
Dan Egnorb7f03672009-12-09 16:22:32 -08006302 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006303 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006305 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006306 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6307 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 startAppProblemLocked(app);
6309 app.stopFreezingAllLocked();
6310 }
6311
6312 /**
6313 * Generate a process error record, suitable for attachment to a ProcessRecord.
6314 *
6315 * @param app The ProcessRecord in which the error occurred.
6316 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6317 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006318 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319 * @param shortMsg Short message describing the crash.
6320 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006321 * @param stackTrace Full crash stack trace, may be null.
6322 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006323 * @return Returns a fully-formed AppErrorStateInfo record.
6324 */
6325 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006326 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 report.condition = condition;
6330 report.processName = app.processName;
6331 report.pid = app.pid;
6332 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006333 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 report.shortMsg = shortMsg;
6335 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006336 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337
6338 return report;
6339 }
6340
Dan Egnor42471dd2010-01-07 17:25:22 -08006341 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 synchronized (this) {
6343 app.crashing = false;
6344 app.crashingReport = null;
6345 app.notResponding = false;
6346 app.notRespondingReport = null;
6347 if (app.anrDialog == fromDialog) {
6348 app.anrDialog = null;
6349 }
6350 if (app.waitDialog == fromDialog) {
6351 app.waitDialog = null;
6352 }
6353 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006354 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006355 Slog.i(ActivityManagerService.TAG, "Killing "
6356 + app.processName + " (pid=" + app.pid + "): user's request");
6357 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6358 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 Process.killProcess(app.pid);
6360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 }
6362 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006363
Dan Egnorb7f03672009-12-09 16:22:32 -08006364 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 long now = SystemClock.uptimeMillis();
6366
6367 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6368 app.info.uid);
6369 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6370 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006371 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006373 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 app.info.processName, app.info.uid);
6375 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006376 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6377 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006379 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006381 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 }
6383 }
6384 if (!app.persistent) {
6385 // We don't want to start this process again until the user
6386 // explicitly does so... but for persistent process, we really
6387 // need to keep it running. If a persistent process is actually
6388 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006389 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006390 app.info.processName);
6391 mBadProcesses.put(app.info.processName, app.info.uid, now);
6392 app.bad = true;
6393 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6394 app.removed = true;
6395 removeProcessLocked(app, false);
6396 return false;
6397 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006398 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006399 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006400 if (r.app == app) {
6401 // If the top running activity is from this crashing
6402 // process, then terminate it to avoid getting in a loop.
6403 Slog.w(TAG, " Force finishing activity "
6404 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006405 int index = mMainStack.indexOfTokenLocked(r);
6406 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006407 Activity.RESULT_CANCELED, null, "crashed");
6408 // Also terminate an activities below it that aren't yet
6409 // stopped, to avoid a situation where one will get
6410 // re-start our crashing activity once it gets resumed again.
6411 index--;
6412 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006413 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006414 if (r.state == ActivityState.RESUMED
6415 || r.state == ActivityState.PAUSING
6416 || r.state == ActivityState.PAUSED) {
6417 if (!r.isHomeActivity) {
6418 Slog.w(TAG, " Force finishing activity "
6419 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006420 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006421 Activity.RESULT_CANCELED, null, "crashed");
6422 }
6423 }
6424 }
6425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 }
6427
6428 // Bump up the crash count of any services currently running in the proc.
6429 if (app.services.size() != 0) {
6430 // Any services running in the application need to be placed
6431 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006432 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006434 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006435 sr.crashCount++;
6436 }
6437 }
6438
6439 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6440 return true;
6441 }
6442
6443 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006444 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6445 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 skipCurrentReceiverLocked(app);
6447 }
6448
6449 void skipCurrentReceiverLocked(ProcessRecord app) {
6450 boolean reschedule = false;
6451 BroadcastRecord r = app.curReceiver;
6452 if (r != null) {
6453 // The current broadcast is waiting for this app's receiver
6454 // to be finished. Looks like that's not going to happen, so
6455 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006456 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6458 r.resultExtras, r.resultAbort, true);
6459 reschedule = true;
6460 }
6461 r = mPendingBroadcast;
6462 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006463 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006465 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6467 r.resultExtras, r.resultAbort, true);
6468 reschedule = true;
6469 }
6470 if (reschedule) {
6471 scheduleBroadcastsLocked();
6472 }
6473 }
6474
Dan Egnor60d87622009-12-16 16:32:58 -08006475 /**
6476 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6477 * The application process will exit immediately after this call returns.
6478 * @param app object of the crashing app, null for the system server
6479 * @param crashInfo describing the exception
6480 */
6481 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6482 ProcessRecord r = findAppProcess(app);
6483
6484 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6485 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006486 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006487 crashInfo.exceptionClassName,
6488 crashInfo.exceptionMessage,
6489 crashInfo.throwFileName,
6490 crashInfo.throwLineNumber);
6491
Dan Egnor42471dd2010-01-07 17:25:22 -08006492 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006493
6494 crashApplication(r, crashInfo);
6495 }
6496
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006497 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006498 IBinder app,
6499 int violationMask,
6500 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006501 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006502
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006503 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006504 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006505 boolean logIt = true;
6506 synchronized (mAlreadyLoggedViolatedStacks) {
6507 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6508 logIt = false;
6509 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006510 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006511 // the relative pain numbers, without logging all
6512 // the stack traces repeatedly. We'd want to do
6513 // likewise in the client code, which also does
6514 // dup suppression, before the Binder call.
6515 } else {
6516 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6517 mAlreadyLoggedViolatedStacks.clear();
6518 }
6519 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6520 }
6521 }
6522 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006523 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006524 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006525 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006526
6527 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6528 AppErrorResult result = new AppErrorResult();
6529 synchronized (this) {
6530 final long origId = Binder.clearCallingIdentity();
6531
6532 Message msg = Message.obtain();
6533 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6534 HashMap<String, Object> data = new HashMap<String, Object>();
6535 data.put("result", result);
6536 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006537 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006538 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006539 msg.obj = data;
6540 mHandler.sendMessage(msg);
6541
6542 Binder.restoreCallingIdentity(origId);
6543 }
6544 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006545 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006546 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006547 }
6548
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006549 // Depending on the policy in effect, there could be a bunch of
6550 // these in quick succession so we try to batch these together to
6551 // minimize disk writes, number of dropbox entries, and maximize
6552 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006553 private void logStrictModeViolationToDropBox(
6554 ProcessRecord process,
6555 StrictMode.ViolationInfo info) {
6556 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006557 return;
6558 }
6559 final boolean isSystemApp = process == null ||
6560 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6561 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6562 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6563 final DropBoxManager dbox = (DropBoxManager)
6564 mContext.getSystemService(Context.DROPBOX_SERVICE);
6565
6566 // Exit early if the dropbox isn't configured to accept this report type.
6567 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6568
6569 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006570 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006571 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6572 synchronized (sb) {
6573 bufferWasEmpty = sb.length() == 0;
6574 appendDropBoxProcessHeaders(process, sb);
6575 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6576 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006577 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6578 if (info.violationNumThisLoop != 0) {
6579 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6580 }
6581 if (info != null && info.durationMillis != -1) {
6582 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006583 }
6584 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006585 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6586 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006587 }
6588 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006589
6590 // Only buffer up to ~64k. Various logging bits truncate
6591 // things at 128k.
6592 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006593 }
6594
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006595 // Flush immediately if the buffer's grown too large, or this
6596 // is a non-system app. Non-system apps are isolated with a
6597 // different tag & policy and not batched.
6598 //
6599 // Batching is useful during internal testing with
6600 // StrictMode settings turned up high. Without batching,
6601 // thousands of separate files could be created on boot.
6602 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006603 new Thread("Error dump: " + dropboxTag) {
6604 @Override
6605 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006606 String report;
6607 synchronized (sb) {
6608 report = sb.toString();
6609 sb.delete(0, sb.length());
6610 sb.trimToSize();
6611 }
6612 if (report.length() != 0) {
6613 dbox.addText(dropboxTag, report);
6614 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006615 }
6616 }.start();
6617 return;
6618 }
6619
6620 // System app batching:
6621 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006622 // An existing dropbox-writing thread is outstanding, so
6623 // we don't need to start it up. The existing thread will
6624 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006625 return;
6626 }
6627
6628 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6629 // (After this point, we shouldn't access AMS internal data structures.)
6630 new Thread("Error dump: " + dropboxTag) {
6631 @Override
6632 public void run() {
6633 // 5 second sleep to let stacks arrive and be batched together
6634 try {
6635 Thread.sleep(5000); // 5 seconds
6636 } catch (InterruptedException e) {}
6637
6638 String errorReport;
6639 synchronized (mStrictModeBuffer) {
6640 errorReport = mStrictModeBuffer.toString();
6641 if (errorReport.length() == 0) {
6642 return;
6643 }
6644 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6645 mStrictModeBuffer.trimToSize();
6646 }
6647 dbox.addText(dropboxTag, errorReport);
6648 }
6649 }.start();
6650 }
6651
Dan Egnor60d87622009-12-16 16:32:58 -08006652 /**
6653 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6654 * @param app object of the crashing app, null for the system server
6655 * @param tag reported by the caller
6656 * @param crashInfo describing the context of the error
6657 * @return true if the process should exit immediately (WTF is fatal)
6658 */
6659 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006660 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006661 ProcessRecord r = findAppProcess(app);
6662
6663 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6664 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006665 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006666 tag, crashInfo.exceptionMessage);
6667
Dan Egnor42471dd2010-01-07 17:25:22 -08006668 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006669
Dianne Hackborn1ab43772011-03-15 14:38:02 -07006670 if (r != null && r.pid != Process.myPid() &&
6671 Settings.Secure.getInt(mContext.getContentResolver(),
6672 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006673 crashApplication(r, crashInfo);
6674 return true;
6675 } else {
6676 return false;
6677 }
6678 }
6679
6680 /**
6681 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6682 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6683 */
6684 private ProcessRecord findAppProcess(IBinder app) {
6685 if (app == null) {
6686 return null;
6687 }
6688
6689 synchronized (this) {
6690 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6691 final int NA = apps.size();
6692 for (int ia=0; ia<NA; ia++) {
6693 ProcessRecord p = apps.valueAt(ia);
6694 if (p.thread != null && p.thread.asBinder() == app) {
6695 return p;
6696 }
6697 }
6698 }
6699
Joe Onorato8a9b2202010-02-26 18:56:32 -08006700 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006701 return null;
6702 }
6703 }
6704
6705 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006706 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6707 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006708 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006709 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6710 // Note: ProcessRecord 'process' is guarded by the service
6711 // instance. (notably process.pkgList, which could otherwise change
6712 // concurrently during execution of this method)
6713 synchronized (this) {
6714 if (process == null || process.pid == MY_PID) {
6715 sb.append("Process: system_server\n");
6716 } else {
6717 sb.append("Process: ").append(process.processName).append("\n");
6718 }
6719 if (process == null) {
6720 return;
6721 }
Dan Egnora455d192010-03-12 08:52:28 -08006722 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006723 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006724 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6725 for (String pkg : process.pkgList) {
6726 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006727 try {
Dan Egnora455d192010-03-12 08:52:28 -08006728 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6729 if (pi != null) {
6730 sb.append(" v").append(pi.versionCode);
6731 if (pi.versionName != null) {
6732 sb.append(" (").append(pi.versionName).append(")");
6733 }
6734 }
6735 } catch (RemoteException e) {
6736 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006737 }
Dan Egnora455d192010-03-12 08:52:28 -08006738 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006739 }
Dan Egnora455d192010-03-12 08:52:28 -08006740 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006741 }
6742
6743 private static String processClass(ProcessRecord process) {
6744 if (process == null || process.pid == MY_PID) {
6745 return "system_server";
6746 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6747 return "system_app";
6748 } else {
6749 return "data_app";
6750 }
6751 }
6752
6753 /**
6754 * Write a description of an error (crash, WTF, ANR) to the drop box.
6755 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6756 * @param process which caused the error, null means the system server
6757 * @param activity which triggered the error, null if unknown
6758 * @param parent activity related to the error, null if unknown
6759 * @param subject line related to the error, null if absent
6760 * @param report in long form describing the error, null if absent
6761 * @param logFile to include in the report, null if none
6762 * @param crashInfo giving an application stack trace, null if absent
6763 */
6764 public void addErrorToDropBox(String eventType,
6765 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6766 final String report, final File logFile,
6767 final ApplicationErrorReport.CrashInfo crashInfo) {
6768 // NOTE -- this must never acquire the ActivityManagerService lock,
6769 // otherwise the watchdog may be prevented from resetting the system.
6770
6771 final String dropboxTag = processClass(process) + "_" + eventType;
6772 final DropBoxManager dbox = (DropBoxManager)
6773 mContext.getSystemService(Context.DROPBOX_SERVICE);
6774
6775 // Exit early if the dropbox isn't configured to accept this report type.
6776 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6777
6778 final StringBuilder sb = new StringBuilder(1024);
6779 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006780 if (activity != null) {
6781 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6782 }
6783 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6784 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6785 }
6786 if (parent != null && parent != activity) {
6787 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6788 }
6789 if (subject != null) {
6790 sb.append("Subject: ").append(subject).append("\n");
6791 }
6792 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6793 sb.append("\n");
6794
6795 // Do the rest in a worker thread to avoid blocking the caller on I/O
6796 // (After this point, we shouldn't access AMS internal data structures.)
6797 Thread worker = new Thread("Error dump: " + dropboxTag) {
6798 @Override
6799 public void run() {
6800 if (report != null) {
6801 sb.append(report);
6802 }
6803 if (logFile != null) {
6804 try {
6805 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6806 } catch (IOException e) {
6807 Slog.e(TAG, "Error reading " + logFile, e);
6808 }
6809 }
6810 if (crashInfo != null && crashInfo.stackTrace != null) {
6811 sb.append(crashInfo.stackTrace);
6812 }
6813
6814 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6815 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6816 if (lines > 0) {
6817 sb.append("\n");
6818
6819 // Merge several logcat streams, and take the last N lines
6820 InputStreamReader input = null;
6821 try {
6822 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6823 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6824 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6825
6826 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6827 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6828 input = new InputStreamReader(logcat.getInputStream());
6829
6830 int num;
6831 char[] buf = new char[8192];
6832 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6833 } catch (IOException e) {
6834 Slog.e(TAG, "Error running logcat", e);
6835 } finally {
6836 if (input != null) try { input.close(); } catch (IOException e) {}
6837 }
6838 }
6839
6840 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006841 }
Dan Egnora455d192010-03-12 08:52:28 -08006842 };
6843
6844 if (process == null || process.pid == MY_PID) {
6845 worker.run(); // We may be about to die -- need to run this synchronously
6846 } else {
6847 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006848 }
6849 }
6850
6851 /**
6852 * Bring up the "unexpected error" dialog box for a crashing app.
6853 * Deal with edge cases (intercepts from instrumented applications,
6854 * ActivityController, error intent receivers, that sort of thing).
6855 * @param r the application crashing
6856 * @param crashInfo describing the failure
6857 */
6858 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006859 long timeMillis = System.currentTimeMillis();
6860 String shortMsg = crashInfo.exceptionClassName;
6861 String longMsg = crashInfo.exceptionMessage;
6862 String stackTrace = crashInfo.stackTrace;
6863 if (shortMsg != null && longMsg != null) {
6864 longMsg = shortMsg + ": " + longMsg;
6865 } else if (shortMsg != null) {
6866 longMsg = shortMsg;
6867 }
6868
Dan Egnor60d87622009-12-16 16:32:58 -08006869 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006871 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 try {
6873 String name = r != null ? r.processName : null;
6874 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006875 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006876 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006877 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006878 + " at watcher's request");
6879 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006880 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 }
6882 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006883 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 }
6885 }
6886
6887 final long origId = Binder.clearCallingIdentity();
6888
6889 // If this process is running instrumentation, finish it.
6890 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006891 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006893 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6894 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006895 Bundle info = new Bundle();
6896 info.putString("shortMsg", shortMsg);
6897 info.putString("longMsg", longMsg);
6898 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6899 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006900 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006901 }
6902
Dan Egnor60d87622009-12-16 16:32:58 -08006903 // If we can't identify the process or it's already exceeded its crash quota,
6904 // quit right away without showing a crash dialog.
6905 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006907 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006908 }
6909
6910 Message msg = Message.obtain();
6911 msg.what = SHOW_ERROR_MSG;
6912 HashMap data = new HashMap();
6913 data.put("result", result);
6914 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 msg.obj = data;
6916 mHandler.sendMessage(msg);
6917
6918 Binder.restoreCallingIdentity(origId);
6919 }
6920
6921 int res = result.get();
6922
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006923 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 synchronized (this) {
6925 if (r != null) {
6926 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6927 SystemClock.uptimeMillis());
6928 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006929 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006930 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006931 }
6932 }
6933
6934 if (appErrorIntent != null) {
6935 try {
6936 mContext.startActivity(appErrorIntent);
6937 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006938 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006942
6943 Intent createAppErrorIntentLocked(ProcessRecord r,
6944 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6945 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006946 if (report == null) {
6947 return null;
6948 }
6949 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6950 result.setComponent(r.errorReportReceiver);
6951 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6952 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6953 return result;
6954 }
6955
Dan Egnorb7f03672009-12-09 16:22:32 -08006956 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6957 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006958 if (r.errorReportReceiver == null) {
6959 return null;
6960 }
6961
6962 if (!r.crashing && !r.notResponding) {
6963 return null;
6964 }
6965
Dan Egnorb7f03672009-12-09 16:22:32 -08006966 ApplicationErrorReport report = new ApplicationErrorReport();
6967 report.packageName = r.info.packageName;
6968 report.installerPackageName = r.errorReportReceiver.getPackageName();
6969 report.processName = r.processName;
6970 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006971 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006972
Dan Egnorb7f03672009-12-09 16:22:32 -08006973 if (r.crashing) {
6974 report.type = ApplicationErrorReport.TYPE_CRASH;
6975 report.crashInfo = crashInfo;
6976 } else if (r.notResponding) {
6977 report.type = ApplicationErrorReport.TYPE_ANR;
6978 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006979
Dan Egnorb7f03672009-12-09 16:22:32 -08006980 report.anrInfo.activity = r.notRespondingReport.tag;
6981 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6982 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006983 }
6984
Dan Egnorb7f03672009-12-09 16:22:32 -08006985 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006986 }
6987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006988 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6989 // assume our apps are happy - lazy create the list
6990 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6991
6992 synchronized (this) {
6993
6994 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006995 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6996 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006997 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6998 // This one's in trouble, so we'll generate a report for it
6999 // crashes are higher priority (in case there's a crash *and* an anr)
7000 ActivityManager.ProcessErrorStateInfo report = null;
7001 if (app.crashing) {
7002 report = app.crashingReport;
7003 } else if (app.notResponding) {
7004 report = app.notRespondingReport;
7005 }
7006
7007 if (report != null) {
7008 if (errList == null) {
7009 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7010 }
7011 errList.add(report);
7012 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007013 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 " crashing = " + app.crashing +
7015 " notResponding = " + app.notResponding);
7016 }
7017 }
7018 }
7019 }
7020
7021 return errList;
7022 }
7023
7024 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7025 // Lazy instantiation of list
7026 List<ActivityManager.RunningAppProcessInfo> runList = null;
7027 synchronized (this) {
7028 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007029 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7030 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007031 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7032 // Generate process state info for running application
7033 ActivityManager.RunningAppProcessInfo currApp =
7034 new ActivityManager.RunningAppProcessInfo(app.processName,
7035 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007036 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007037 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007038 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007039 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007040 if (app.persistent) {
7041 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007044 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7046 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7047 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007048 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7049 } else if (adj >= HOME_APP_ADJ) {
7050 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7051 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007052 } else if (adj >= SECONDARY_SERVER_ADJ) {
7053 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007054 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007055 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007056 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7057 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 } else if (adj >= VISIBLE_APP_ADJ) {
7059 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7060 } else {
7061 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7062 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007063 currApp.importanceReasonCode = app.adjTypeCode;
7064 if (app.adjSource instanceof ProcessRecord) {
7065 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007066 } else if (app.adjSource instanceof ActivityRecord) {
7067 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007068 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7069 }
7070 if (app.adjTarget instanceof ComponentName) {
7071 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7072 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007073 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 // + " lru=" + currApp.lru);
7075 if (runList == null) {
7076 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7077 }
7078 runList.add(currApp);
7079 }
7080 }
7081 }
7082 return runList;
7083 }
7084
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007085 public List<ApplicationInfo> getRunningExternalApplications() {
7086 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7087 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7088 if (runningApps != null && runningApps.size() > 0) {
7089 Set<String> extList = new HashSet<String>();
7090 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7091 if (app.pkgList != null) {
7092 for (String pkg : app.pkgList) {
7093 extList.add(pkg);
7094 }
7095 }
7096 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007097 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007098 for (String pkg : extList) {
7099 try {
7100 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7101 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7102 retList.add(info);
7103 }
7104 } catch (RemoteException e) {
7105 }
7106 }
7107 }
7108 return retList;
7109 }
7110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007111 @Override
7112 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007113 if (checkCallingPermission(android.Manifest.permission.DUMP)
7114 != PackageManager.PERMISSION_GRANTED) {
7115 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7116 + Binder.getCallingPid()
7117 + ", uid=" + Binder.getCallingUid()
7118 + " without permission "
7119 + android.Manifest.permission.DUMP);
7120 return;
7121 }
7122
7123 boolean dumpAll = false;
7124
7125 int opti = 0;
7126 while (opti < args.length) {
7127 String opt = args[opti];
7128 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7129 break;
7130 }
7131 opti++;
7132 if ("-a".equals(opt)) {
7133 dumpAll = true;
7134 } else if ("-h".equals(opt)) {
7135 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007136 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007137 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007138 pw.println(" a[ctivities]: activity stack state");
7139 pw.println(" b[roadcasts]: broadcast state");
7140 pw.println(" i[ntents]: pending intent state");
7141 pw.println(" p[rocesses]: process state");
7142 pw.println(" o[om]: out of memory management");
7143 pw.println(" prov[iders]: content provider state");
7144 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007145 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007147 } else {
7148 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007150 }
7151
7152 // Is the caller requesting to dump a particular piece of data?
7153 if (opti < args.length) {
7154 String cmd = args[opti];
7155 opti++;
7156 if ("activities".equals(cmd) || "a".equals(cmd)) {
7157 synchronized (this) {
7158 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007159 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007160 return;
7161 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7162 synchronized (this) {
7163 dumpBroadcastsLocked(fd, pw, args, opti, true);
7164 }
7165 return;
7166 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7167 synchronized (this) {
7168 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7169 }
7170 return;
7171 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7172 synchronized (this) {
7173 dumpProcessesLocked(fd, pw, args, opti, true);
7174 }
7175 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007176 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7177 synchronized (this) {
7178 dumpOomLocked(fd, pw, args, opti, true);
7179 }
7180 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007181 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7182 synchronized (this) {
7183 dumpProvidersLocked(fd, pw, args, opti, true);
7184 }
7185 return;
7186 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007187 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007188 return;
7189 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7190 synchronized (this) {
7191 dumpServicesLocked(fd, pw, args, opti, true);
7192 }
7193 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007195 }
7196
7197 // No piece of data specified, dump everything.
7198 synchronized (this) {
7199 boolean needSep;
7200 if (dumpAll) {
7201 pw.println("Providers in Current Activity Manager State:");
7202 }
7203 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7204 if (needSep) {
7205 pw.println(" ");
7206 }
7207 if (dumpAll) {
7208 pw.println("-------------------------------------------------------------------------------");
7209 pw.println("Broadcasts in Current Activity Manager State:");
7210 }
7211 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7212 if (needSep) {
7213 pw.println(" ");
7214 }
7215 if (dumpAll) {
7216 pw.println("-------------------------------------------------------------------------------");
7217 pw.println("Services in Current Activity Manager State:");
7218 }
7219 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7220 if (needSep) {
7221 pw.println(" ");
7222 }
7223 if (dumpAll) {
7224 pw.println("-------------------------------------------------------------------------------");
7225 pw.println("PendingIntents in Current Activity Manager State:");
7226 }
7227 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7228 if (needSep) {
7229 pw.println(" ");
7230 }
7231 if (dumpAll) {
7232 pw.println("-------------------------------------------------------------------------------");
7233 pw.println("Activities in Current Activity Manager State:");
7234 }
7235 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7236 if (needSep) {
7237 pw.println(" ");
7238 }
7239 if (dumpAll) {
7240 pw.println("-------------------------------------------------------------------------------");
7241 pw.println("Processes in Current Activity Manager State:");
7242 }
7243 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7244 }
7245 }
7246
7247 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7248 int opti, boolean dumpAll, boolean needHeader) {
7249 if (needHeader) {
7250 pw.println(" Activity stack:");
7251 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007252 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 pw.println(" ");
7254 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007255 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7256 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007257 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007258 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007259 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007260 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007261 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007263 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007264 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007265 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007266 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007267 pw.println(" ");
7268 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007269 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007273 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7274 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007275 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007276 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007277
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007278 if (dumpAll && mRecentTasks.size() > 0) {
7279 pw.println(" ");
7280 pw.println("Recent tasks in Current Activity Manager State:");
7281
7282 final int N = mRecentTasks.size();
7283 for (int i=0; i<N; i++) {
7284 TaskRecord tr = mRecentTasks.get(i);
7285 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7286 pw.println(tr);
7287 mRecentTasks.get(i).dump(pw, " ");
7288 }
7289 }
7290
7291 pw.println(" ");
7292 pw.println(" mCurTask: " + mCurTask);
7293
7294 return true;
7295 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007296
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007297 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7298 int opti, boolean dumpAll) {
7299 boolean needSep = false;
7300 int numPers = 0;
7301
7302 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7304 final int NA = procs.size();
7305 for (int ia=0; ia<NA; ia++) {
7306 if (!needSep) {
7307 pw.println(" All known processes:");
7308 needSep = true;
7309 }
7310 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007311 pw.print(r.persistent ? " *PERS*" : " *APP*");
7312 pw.print(" UID "); pw.print(procs.keyAt(ia));
7313 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 r.dump(pw, " ");
7315 if (r.persistent) {
7316 numPers++;
7317 }
7318 }
7319 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007320 }
7321
7322 if (mLruProcesses.size() > 0) {
7323 if (needSep) pw.println(" ");
7324 needSep = true;
7325 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007326 dumpProcessOomList(pw, this, mLruProcesses, " ",
7327 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007328 needSep = true;
7329 }
7330
7331 synchronized (mPidsSelfLocked) {
7332 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 if (needSep) pw.println(" ");
7334 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007335 pw.println(" PID mappings:");
7336 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7337 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7338 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 }
7340 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007341 }
7342
7343 if (mForegroundProcesses.size() > 0) {
7344 if (needSep) pw.println(" ");
7345 needSep = true;
7346 pw.println(" Foreground Processes:");
7347 for (int i=0; i<mForegroundProcesses.size(); i++) {
7348 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7349 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007351 }
7352
7353 if (mPersistentStartingProcesses.size() > 0) {
7354 if (needSep) pw.println(" ");
7355 needSep = true;
7356 pw.println(" Persisent processes that are starting:");
7357 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007358 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007361 if (mStartingProcesses.size() > 0) {
7362 if (needSep) pw.println(" ");
7363 needSep = true;
7364 pw.println(" Processes that are starting:");
7365 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007366 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369 if (mRemovedProcesses.size() > 0) {
7370 if (needSep) pw.println(" ");
7371 needSep = true;
7372 pw.println(" Processes that are being removed:");
7373 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007374 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007375 }
7376
7377 if (mProcessesOnHold.size() > 0) {
7378 if (needSep) pw.println(" ");
7379 needSep = true;
7380 pw.println(" Processes that are on old until the system is ready:");
7381 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007382 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384
Dianne Hackborn287952c2010-09-22 22:34:31 -07007385 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007386
7387 if (mProcessCrashTimes.getMap().size() > 0) {
7388 if (needSep) pw.println(" ");
7389 needSep = true;
7390 pw.println(" Time since processes crashed:");
7391 long now = SystemClock.uptimeMillis();
7392 for (Map.Entry<String, SparseArray<Long>> procs
7393 : mProcessCrashTimes.getMap().entrySet()) {
7394 SparseArray<Long> uids = procs.getValue();
7395 final int N = uids.size();
7396 for (int i=0; i<N; i++) {
7397 pw.print(" Process "); pw.print(procs.getKey());
7398 pw.print(" uid "); pw.print(uids.keyAt(i));
7399 pw.print(": last crashed ");
7400 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007401 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007402 }
7403 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007405
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007406 if (mBadProcesses.getMap().size() > 0) {
7407 if (needSep) pw.println(" ");
7408 needSep = true;
7409 pw.println(" Bad processes:");
7410 for (Map.Entry<String, SparseArray<Long>> procs
7411 : mBadProcesses.getMap().entrySet()) {
7412 SparseArray<Long> uids = procs.getValue();
7413 final int N = uids.size();
7414 for (int i=0; i<N; i++) {
7415 pw.print(" Bad process "); pw.print(procs.getKey());
7416 pw.print(" uid "); pw.print(uids.keyAt(i));
7417 pw.print(": crashed at time ");
7418 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 }
7420 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007423 pw.println(" ");
7424 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007425 if (mHeavyWeightProcess != null) {
7426 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7427 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007428 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007429 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007430 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7431 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7432 || mOrigWaitForDebugger) {
7433 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7434 + " mDebugTransient=" + mDebugTransient
7435 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7436 }
7437 if (mAlwaysFinishActivities || mController != null) {
7438 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7439 + " mController=" + mController);
7440 }
7441 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007444 + " mProcessesReady=" + mProcessesReady
7445 + " mSystemReady=" + mSystemReady);
7446 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007447 + " mBooted=" + mBooted
7448 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007449 pw.print(" mLastPowerCheckRealtime=");
7450 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7451 pw.println("");
7452 pw.print(" mLastPowerCheckUptime=");
7453 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7454 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007455 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7456 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007457 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007459
7460 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 }
7462
Dianne Hackborn287952c2010-09-22 22:34:31 -07007463 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7464 int opti, boolean needSep, boolean dumpAll) {
7465 if (mProcessesToGc.size() > 0) {
7466 if (needSep) pw.println(" ");
7467 needSep = true;
7468 pw.println(" Processes that are waiting to GC:");
7469 long now = SystemClock.uptimeMillis();
7470 for (int i=0; i<mProcessesToGc.size(); i++) {
7471 ProcessRecord proc = mProcessesToGc.get(i);
7472 pw.print(" Process "); pw.println(proc);
7473 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7474 pw.print(", last gced=");
7475 pw.print(now-proc.lastRequestedGc);
7476 pw.print(" ms ago, last lowMem=");
7477 pw.print(now-proc.lastLowMemory);
7478 pw.println(" ms ago");
7479
7480 }
7481 }
7482 return needSep;
7483 }
7484
7485 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7486 int opti, boolean dumpAll) {
7487 boolean needSep = false;
7488
7489 if (mLruProcesses.size() > 0) {
7490 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7491
7492 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7493 @Override
7494 public int compare(ProcessRecord object1, ProcessRecord object2) {
7495 if (object1.setAdj != object2.setAdj) {
7496 return object1.setAdj > object2.setAdj ? -1 : 1;
7497 }
7498 if (object1.setSchedGroup != object2.setSchedGroup) {
7499 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7500 }
7501 if (object1.keeping != object2.keeping) {
7502 return object1.keeping ? -1 : 1;
7503 }
7504 if (object1.pid != object2.pid) {
7505 return object1.pid > object2.pid ? -1 : 1;
7506 }
7507 return 0;
7508 }
7509 };
7510
7511 Collections.sort(procs, comparator);
7512
7513 if (needSep) pw.println(" ");
7514 needSep = true;
7515 pw.println(" Process OOM control:");
7516 dumpProcessOomList(pw, this, procs, " ",
7517 "Proc", "PERS", true);
7518 needSep = true;
7519 }
7520
7521 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7522
7523 pw.println(" ");
7524 pw.println(" mHomeProcess: " + mHomeProcess);
7525 if (mHeavyWeightProcess != null) {
7526 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7527 }
7528
7529 return true;
7530 }
7531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 /**
7533 * There are three ways to call this:
7534 * - no service specified: dump all the services
7535 * - a flattened component name that matched an existing service was specified as the
7536 * first arg: dump that one service
7537 * - the first arg isn't the flattened component name of an existing service:
7538 * dump all services whose component contains the first arg as a substring
7539 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007540 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7541 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 String[] newArgs;
7543 String componentNameString;
7544 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007545 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 componentNameString = null;
7547 newArgs = EMPTY_STRING_ARRAY;
7548 r = null;
7549 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007550 componentNameString = args[opti];
7551 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007553 synchronized (this) {
7554 r = componentName != null ? mServices.get(componentName) : null;
7555 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007556 newArgs = new String[args.length - opti];
7557 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 }
7559
7560 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007561 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007563 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7564 synchronized (this) {
7565 for (ServiceRecord r1 : mServices.values()) {
7566 if (componentNameString == null
7567 || r1.name.flattenToString().contains(componentNameString)) {
7568 services.add(r1);
7569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
7571 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007572 for (int i=0; i<services.size(); i++) {
7573 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 }
7576 }
7577
7578 /**
7579 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7580 * there is a thread associated with the service.
7581 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007582 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7583 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007585 if (dumpAll) {
7586 synchronized (this) {
7587 pw.print(" * "); pw.println(r);
7588 r.dump(pw, " ");
7589 }
7590 pw.println("");
7591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 if (r.app != null && r.app.thread != null) {
7593 try {
7594 // flush anything that is already in the PrintWriter since the thread is going
7595 // to write to the file descriptor directly
7596 pw.flush();
7597 r.app.thread.dumpService(fd, r, args);
7598 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007599 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 } catch (RemoteException e) {
7601 pw.println("got a RemoteException while dumping the service");
7602 }
7603 }
7604 }
7605
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007606 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7607 int opti, boolean dumpAll) {
7608 boolean needSep = false;
7609
7610 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 if (mRegisteredReceivers.size() > 0) {
7612 pw.println(" ");
7613 pw.println(" Registered Receivers:");
7614 Iterator it = mRegisteredReceivers.values().iterator();
7615 while (it.hasNext()) {
7616 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007617 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 r.dump(pw, " ");
7619 }
7620 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007622 pw.println(" ");
7623 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007624 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007625 needSep = true;
7626 }
7627
7628 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7629 || mPendingBroadcast != null) {
7630 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007632 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007634 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7635 pw.println(" Broadcast #" + i + ":");
7636 mParallelBroadcasts.get(i).dump(pw, " ");
7637 }
7638 if (mOrderedBroadcasts.size() > 0) {
7639 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007640 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007641 }
7642 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7643 pw.println(" Serialized Broadcast #" + i + ":");
7644 mOrderedBroadcasts.get(i).dump(pw, " ");
7645 }
7646 pw.println(" ");
7647 pw.println(" Pending broadcast:");
7648 if (mPendingBroadcast != null) {
7649 mPendingBroadcast.dump(pw, " ");
7650 } else {
7651 pw.println(" (null)");
7652 }
7653 needSep = true;
7654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007656 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007658 pw.println(" Historical broadcasts:");
7659 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7660 BroadcastRecord r = mBroadcastHistory[i];
7661 if (r == null) {
7662 break;
7663 }
7664 pw.println(" Historical Broadcast #" + i + ":");
7665 r.dump(pw, " ");
7666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 needSep = true;
7668 }
7669
7670 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007671 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007672 pw.println(" Sticky broadcasts:");
7673 StringBuilder sb = new StringBuilder(128);
7674 for (Map.Entry<String, ArrayList<Intent>> ent
7675 : mStickyBroadcasts.entrySet()) {
7676 pw.print(" * Sticky action "); pw.print(ent.getKey());
7677 pw.println(":");
7678 ArrayList<Intent> intents = ent.getValue();
7679 final int N = intents.size();
7680 for (int i=0; i<N; i++) {
7681 sb.setLength(0);
7682 sb.append(" Intent: ");
7683 intents.get(i).toShortString(sb, true, false);
7684 pw.println(sb.toString());
7685 Bundle bundle = intents.get(i).getExtras();
7686 if (bundle != null) {
7687 pw.print(" ");
7688 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 }
7690 }
7691 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007692 needSep = true;
7693 }
7694
7695 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007696 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007697 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 pw.println(" mHandler:");
7699 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007700 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007702
7703 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704 }
7705
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007706 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7707 int opti, boolean dumpAll) {
7708 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007710 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 if (mServices.size() > 0) {
7712 pw.println(" Active services:");
7713 Iterator<ServiceRecord> it = mServices.values().iterator();
7714 while (it.hasNext()) {
7715 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007716 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 r.dump(pw, " ");
7718 }
7719 needSep = true;
7720 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007723 if (mPendingServices.size() > 0) {
7724 if (needSep) pw.println(" ");
7725 pw.println(" Pending services:");
7726 for (int i=0; i<mPendingServices.size(); i++) {
7727 ServiceRecord r = mPendingServices.get(i);
7728 pw.print(" * Pending "); pw.println(r);
7729 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007731 needSep = true;
7732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007734 if (mRestartingServices.size() > 0) {
7735 if (needSep) pw.println(" ");
7736 pw.println(" Restarting services:");
7737 for (int i=0; i<mRestartingServices.size(); i++) {
7738 ServiceRecord r = mRestartingServices.get(i);
7739 pw.print(" * Restarting "); pw.println(r);
7740 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007742 needSep = true;
7743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007745 if (mStoppingServices.size() > 0) {
7746 if (needSep) pw.println(" ");
7747 pw.println(" Stopping services:");
7748 for (int i=0; i<mStoppingServices.size(); i++) {
7749 ServiceRecord r = mStoppingServices.get(i);
7750 pw.print(" * Stopping "); pw.println(r);
7751 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 needSep = true;
7754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007756 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007757 if (mServiceConnections.size() > 0) {
7758 if (needSep) pw.println(" ");
7759 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007760 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007761 = mServiceConnections.values().iterator();
7762 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007763 ArrayList<ConnectionRecord> r = it.next();
7764 for (int i=0; i<r.size(); i++) {
7765 pw.print(" * "); pw.println(r.get(i));
7766 r.get(i).dump(pw, " ");
7767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007769 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007770 }
7771 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772
7773 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 }
7775
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007776 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7777 int opti, boolean dumpAll) {
7778 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007780 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 if (mProvidersByClass.size() > 0) {
7782 if (needSep) pw.println(" ");
7783 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007784 Iterator<Map.Entry<String, ContentProviderRecord>> it
7785 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007787 Map.Entry<String, ContentProviderRecord> e = it.next();
7788 ContentProviderRecord r = e.getValue();
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
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007795 if (mProvidersByName.size() > 0) {
7796 pw.println(" ");
7797 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007798 Iterator<Map.Entry<String, ContentProviderRecord>> it
7799 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007800 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007801 Map.Entry<String, ContentProviderRecord> e = it.next();
7802 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007803 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7804 pw.println(r);
7805 }
7806 needSep = true;
7807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007809
7810 if (mLaunchingProviders.size() > 0) {
7811 if (needSep) pw.println(" ");
7812 pw.println(" Launching content providers:");
7813 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7814 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7815 pw.println(mLaunchingProviders.get(i));
7816 }
7817 needSep = true;
7818 }
7819
7820 if (mGrantedUriPermissions.size() > 0) {
7821 pw.println();
7822 pw.println("Granted Uri Permissions:");
7823 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7824 int uid = mGrantedUriPermissions.keyAt(i);
7825 HashMap<Uri, UriPermission> perms
7826 = mGrantedUriPermissions.valueAt(i);
7827 pw.print(" * UID "); pw.print(uid);
7828 pw.println(" holds:");
7829 for (UriPermission perm : perms.values()) {
7830 pw.print(" "); pw.println(perm);
7831 perm.dump(pw, " ");
7832 }
7833 }
7834 needSep = true;
7835 }
7836
7837 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 }
7839
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007840 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7841 int opti, boolean dumpAll) {
7842 boolean needSep = false;
7843
7844 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 if (this.mIntentSenderRecords.size() > 0) {
7846 Iterator<WeakReference<PendingIntentRecord>> it
7847 = mIntentSenderRecords.values().iterator();
7848 while (it.hasNext()) {
7849 WeakReference<PendingIntentRecord> ref = it.next();
7850 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007851 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007853 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 rec.dump(pw, " ");
7855 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007856 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 }
7858 }
7859 }
7860 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007861
7862 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 }
7864
7865 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007866 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 TaskRecord lastTask = null;
7868 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007869 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007870 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 if (lastTask != r.task) {
7872 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007873 pw.print(prefix);
7874 pw.print(full ? "* " : " ");
7875 pw.println(lastTask);
7876 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007877 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007880 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7881 pw.print(" #"); pw.print(i); pw.print(": ");
7882 pw.println(r);
7883 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007884 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 }
7887 }
7888
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007889 private static String buildOomTag(String prefix, String space, int val, int base) {
7890 if (val == base) {
7891 if (space == null) return prefix;
7892 return prefix + " ";
7893 }
7894 return prefix + "+" + Integer.toString(val-base);
7895 }
7896
7897 private static final int dumpProcessList(PrintWriter pw,
7898 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007899 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007901 final int N = list.size()-1;
7902 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007904 pw.println(String.format("%s%s #%2d: %s",
7905 prefix, (r.persistent ? persistentLabel : normalLabel),
7906 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 if (r.persistent) {
7908 numPers++;
7909 }
7910 }
7911 return numPers;
7912 }
7913
Dianne Hackborn287952c2010-09-22 22:34:31 -07007914 private static final void dumpProcessOomList(PrintWriter pw,
7915 ActivityManagerService service, List<ProcessRecord> list,
7916 String prefix, String normalLabel, String persistentLabel,
7917 boolean inclDetails) {
7918
7919 final long curRealtime = SystemClock.elapsedRealtime();
7920 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7921 final long curUptime = SystemClock.uptimeMillis();
7922 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7923
7924 final int N = list.size()-1;
7925 for (int i=N; i>=0; i--) {
7926 ProcessRecord r = list.get(i);
7927 String oomAdj;
7928 if (r.setAdj >= EMPTY_APP_ADJ) {
7929 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7930 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7931 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7932 } else if (r.setAdj >= HOME_APP_ADJ) {
7933 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7934 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7935 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7936 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7937 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7938 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7939 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7940 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7941 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7942 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7943 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7944 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7945 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7946 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7947 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7948 } else if (r.setAdj >= SYSTEM_ADJ) {
7949 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7950 } else {
7951 oomAdj = Integer.toString(r.setAdj);
7952 }
7953 String schedGroup;
7954 switch (r.setSchedGroup) {
7955 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7956 schedGroup = "B";
7957 break;
7958 case Process.THREAD_GROUP_DEFAULT:
7959 schedGroup = "F";
7960 break;
7961 default:
7962 schedGroup = Integer.toString(r.setSchedGroup);
7963 break;
7964 }
7965 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7966 prefix, (r.persistent ? persistentLabel : normalLabel),
7967 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
7968 if (r.adjSource != null || r.adjTarget != null) {
7969 pw.print(prefix);
7970 pw.print(" ");
7971 if (r.adjTarget instanceof ComponentName) {
7972 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7973 } else if (r.adjTarget != null) {
7974 pw.print(r.adjTarget.toString());
7975 } else {
7976 pw.print("{null}");
7977 }
7978 pw.print("<=");
7979 if (r.adjSource instanceof ProcessRecord) {
7980 pw.print("Proc{");
7981 pw.print(((ProcessRecord)r.adjSource).toShortString());
7982 pw.println("}");
7983 } else if (r.adjSource != null) {
7984 pw.println(r.adjSource.toString());
7985 } else {
7986 pw.println("{null}");
7987 }
7988 }
7989 if (inclDetails) {
7990 pw.print(prefix);
7991 pw.print(" ");
7992 pw.print("oom: max="); pw.print(r.maxAdj);
7993 pw.print(" hidden="); pw.print(r.hiddenAdj);
7994 pw.print(" curRaw="); pw.print(r.curRawAdj);
7995 pw.print(" setRaw="); pw.print(r.setRawAdj);
7996 pw.print(" cur="); pw.print(r.curAdj);
7997 pw.print(" set="); pw.println(r.setAdj);
7998 pw.print(prefix);
7999 pw.print(" ");
8000 pw.print("keeping="); pw.print(r.keeping);
8001 pw.print(" hidden="); pw.print(r.hidden);
8002 pw.print(" empty="); pw.println(r.empty);
8003
8004 if (!r.keeping) {
8005 if (r.lastWakeTime != 0) {
8006 long wtime;
8007 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8008 synchronized (stats) {
8009 wtime = stats.getProcessWakeTime(r.info.uid,
8010 r.pid, curRealtime);
8011 }
8012 long timeUsed = wtime - r.lastWakeTime;
8013 pw.print(prefix);
8014 pw.print(" ");
8015 pw.print("keep awake over ");
8016 TimeUtils.formatDuration(realtimeSince, pw);
8017 pw.print(" used ");
8018 TimeUtils.formatDuration(timeUsed, pw);
8019 pw.print(" (");
8020 pw.print((timeUsed*100)/realtimeSince);
8021 pw.println("%)");
8022 }
8023 if (r.lastCpuTime != 0) {
8024 long timeUsed = r.curCpuTime - r.lastCpuTime;
8025 pw.print(prefix);
8026 pw.print(" ");
8027 pw.print("run cpu over ");
8028 TimeUtils.formatDuration(uptimeSince, pw);
8029 pw.print(" used ");
8030 TimeUtils.formatDuration(timeUsed, pw);
8031 pw.print(" (");
8032 pw.print((timeUsed*100)/uptimeSince);
8033 pw.println("%)");
8034 }
8035 }
8036 }
8037 }
8038 }
8039
Dianne Hackborn472ad872010-04-07 17:31:48 -07008040 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008042 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 long uptime = SystemClock.uptimeMillis();
8044 long realtime = SystemClock.elapsedRealtime();
8045
8046 if (isCheckinRequest) {
8047 // short checkin version
8048 pw.println(uptime + "," + realtime);
8049 pw.flush();
8050 } else {
8051 pw.println("Applications Memory Usage (kB):");
8052 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8053 }
8054 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8055 ProcessRecord r = (ProcessRecord)list.get(i);
8056 if (r.thread != null) {
8057 if (!isCheckinRequest) {
8058 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8059 pw.flush();
8060 }
8061 try {
8062 r.thread.asBinder().dump(fd, args);
8063 } catch (RemoteException e) {
8064 if (!isCheckinRequest) {
8065 pw.println("Got RemoteException!");
8066 pw.flush();
8067 }
8068 }
8069 }
8070 }
8071 }
8072
8073 /**
8074 * Searches array of arguments for the specified string
8075 * @param args array of argument strings
8076 * @param value value to search for
8077 * @return true if the value is contained in the array
8078 */
8079 private static boolean scanArgs(String[] args, String value) {
8080 if (args != null) {
8081 for (String arg : args) {
8082 if (value.equals(arg)) {
8083 return true;
8084 }
8085 }
8086 }
8087 return false;
8088 }
8089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008090 private final void killServicesLocked(ProcessRecord app,
8091 boolean allowRestart) {
8092 // Report disconnected services.
8093 if (false) {
8094 // XXX we are letting the client link to the service for
8095 // death notifications.
8096 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008097 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008099 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008101 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008102 = r.connections.values().iterator();
8103 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008104 ArrayList<ConnectionRecord> cl = jt.next();
8105 for (int i=0; i<cl.size(); i++) {
8106 ConnectionRecord c = cl.get(i);
8107 if (c.binding.client != app) {
8108 try {
8109 //c.conn.connected(r.className, null);
8110 } catch (Exception e) {
8111 // todo: this should be asynchronous!
8112 Slog.w(TAG, "Exception thrown disconnected servce "
8113 + r.shortName
8114 + " from app " + app.processName, e);
8115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 }
8117 }
8118 }
8119 }
8120 }
8121 }
8122 }
8123
8124 // Clean up any connections this application has to other services.
8125 if (app.connections.size() > 0) {
8126 Iterator<ConnectionRecord> it = app.connections.iterator();
8127 while (it.hasNext()) {
8128 ConnectionRecord r = it.next();
8129 removeConnectionLocked(r, app, null);
8130 }
8131 }
8132 app.connections.clear();
8133
8134 if (app.services.size() != 0) {
8135 // Any services running in the application need to be placed
8136 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008137 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008138 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008139 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008140 synchronized (sr.stats.getBatteryStats()) {
8141 sr.stats.stopLaunchedLocked();
8142 }
8143 sr.app = null;
8144 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008145 if (mStoppingServices.remove(sr)) {
8146 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8147 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008148
8149 boolean hasClients = sr.bindings.size() > 0;
8150 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 Iterator<IntentBindRecord> bindings
8152 = sr.bindings.values().iterator();
8153 while (bindings.hasNext()) {
8154 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008155 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156 + ": shouldUnbind=" + b.hasBound);
8157 b.binder = null;
8158 b.requested = b.received = b.hasBound = false;
8159 }
8160 }
8161
8162 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008163 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008164 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008165 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008166 sr.crashCount, sr.shortName, app.pid);
8167 bringDownServiceLocked(sr, true);
8168 } else if (!allowRestart) {
8169 bringDownServiceLocked(sr, true);
8170 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008171 boolean canceled = scheduleServiceRestartLocked(sr, true);
8172
8173 // Should the service remain running? Note that in the
8174 // extreme case of so many attempts to deliver a command
8175 // that it failed, that we also will stop it here.
8176 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8177 if (sr.pendingStarts.size() == 0) {
8178 sr.startRequested = false;
8179 if (!hasClients) {
8180 // Whoops, no reason to restart!
8181 bringDownServiceLocked(sr, true);
8182 }
8183 }
8184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 }
8186 }
8187
8188 if (!allowRestart) {
8189 app.services.clear();
8190 }
8191 }
8192
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008193 // Make sure we have no more records on the stopping list.
8194 int i = mStoppingServices.size();
8195 while (i > 0) {
8196 i--;
8197 ServiceRecord sr = mStoppingServices.get(i);
8198 if (sr.app == app) {
8199 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008200 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008201 }
8202 }
8203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 app.executingServices.clear();
8205 }
8206
8207 private final void removeDyingProviderLocked(ProcessRecord proc,
8208 ContentProviderRecord cpr) {
8209 synchronized (cpr) {
8210 cpr.launchingApp = null;
8211 cpr.notifyAll();
8212 }
8213
8214 mProvidersByClass.remove(cpr.info.name);
8215 String names[] = cpr.info.authority.split(";");
8216 for (int j = 0; j < names.length; j++) {
8217 mProvidersByName.remove(names[j]);
8218 }
8219
8220 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8221 while (cit.hasNext()) {
8222 ProcessRecord capp = cit.next();
8223 if (!capp.persistent && capp.thread != null
8224 && capp.pid != 0
8225 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008226 Slog.i(TAG, "Kill " + capp.processName
8227 + " (pid " + capp.pid + "): provider " + cpr.info.name
8228 + " in dying process " + proc.processName);
8229 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8230 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008231 Process.killProcess(capp.pid);
8232 }
8233 }
8234
8235 mLaunchingProviders.remove(cpr);
8236 }
8237
8238 /**
8239 * Main code for cleaning up a process when it has gone away. This is
8240 * called both as a result of the process dying, or directly when stopping
8241 * a process when running in single process mode.
8242 */
8243 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8244 boolean restarting, int index) {
8245 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008246 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 }
8248
Dianne Hackborn36124872009-10-08 16:22:03 -07008249 mProcessesToGc.remove(app);
8250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008251 // Dismiss any open dialogs.
8252 if (app.crashDialog != null) {
8253 app.crashDialog.dismiss();
8254 app.crashDialog = null;
8255 }
8256 if (app.anrDialog != null) {
8257 app.anrDialog.dismiss();
8258 app.anrDialog = null;
8259 }
8260 if (app.waitDialog != null) {
8261 app.waitDialog.dismiss();
8262 app.waitDialog = null;
8263 }
8264
8265 app.crashing = false;
8266 app.notResponding = false;
8267
8268 app.resetPackageList();
8269 app.thread = null;
8270 app.forcingToForeground = null;
8271 app.foregroundServices = false;
8272
8273 killServicesLocked(app, true);
8274
8275 boolean restart = false;
8276
8277 int NL = mLaunchingProviders.size();
8278
8279 // Remove published content providers.
8280 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008281 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008283 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 cpr.provider = null;
8285 cpr.app = null;
8286
8287 // See if someone is waiting for this provider... in which
8288 // case we don't remove it, but just let it restart.
8289 int i = 0;
8290 if (!app.bad) {
8291 for (; i<NL; i++) {
8292 if (mLaunchingProviders.get(i) == cpr) {
8293 restart = true;
8294 break;
8295 }
8296 }
8297 } else {
8298 i = NL;
8299 }
8300
8301 if (i >= NL) {
8302 removeDyingProviderLocked(app, cpr);
8303 NL = mLaunchingProviders.size();
8304 }
8305 }
8306 app.pubProviders.clear();
8307 }
8308
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008309 // Take care of any launching providers waiting for this process.
8310 if (checkAppInLaunchingProvidersLocked(app, false)) {
8311 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 // Unregister from connected content providers.
8315 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008316 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 while (it.hasNext()) {
8318 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8319 cpr.clients.remove(app);
8320 }
8321 app.conProviders.clear();
8322 }
8323
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008324 // At this point there may be remaining entries in mLaunchingProviders
8325 // where we were the only one waiting, so they are no longer of use.
8326 // Look for these and clean up if found.
8327 // XXX Commented out for now. Trying to figure out a way to reproduce
8328 // the actual situation to identify what is actually going on.
8329 if (false) {
8330 for (int i=0; i<NL; i++) {
8331 ContentProviderRecord cpr = (ContentProviderRecord)
8332 mLaunchingProviders.get(i);
8333 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8334 synchronized (cpr) {
8335 cpr.launchingApp = null;
8336 cpr.notifyAll();
8337 }
8338 }
8339 }
8340 }
8341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008342 skipCurrentReceiverLocked(app);
8343
8344 // Unregister any receivers.
8345 if (app.receivers.size() > 0) {
8346 Iterator<ReceiverList> it = app.receivers.iterator();
8347 while (it.hasNext()) {
8348 removeReceiverLocked(it.next());
8349 }
8350 app.receivers.clear();
8351 }
8352
Christopher Tate181fafa2009-05-14 11:12:14 -07008353 // If the app is undergoing backup, tell the backup manager about it
8354 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008355 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008356 try {
8357 IBackupManager bm = IBackupManager.Stub.asInterface(
8358 ServiceManager.getService(Context.BACKUP_SERVICE));
8359 bm.agentDisconnected(app.info.packageName);
8360 } catch (RemoteException e) {
8361 // can't happen; backup manager is local
8362 }
8363 }
8364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 // If the caller is restarting this app, then leave it in its
8366 // current lists and let the caller take care of it.
8367 if (restarting) {
8368 return;
8369 }
8370
8371 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008372 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008373 "Removing non-persistent process during cleanup: " + app);
8374 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008375 if (mHeavyWeightProcess == app) {
8376 mHeavyWeightProcess = null;
8377 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379 } else if (!app.removed) {
8380 // This app is persistent, so we need to keep its record around.
8381 // If it is not already on the pending app list, add it there
8382 // and start a new process for it.
8383 app.thread = null;
8384 app.forcingToForeground = null;
8385 app.foregroundServices = false;
8386 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8387 mPersistentStartingProcesses.add(app);
8388 restart = true;
8389 }
8390 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008391 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8392 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 mProcessesOnHold.remove(app);
8394
The Android Open Source Project4df24232009-03-05 14:34:35 -08008395 if (app == mHomeProcess) {
8396 mHomeProcess = null;
8397 }
8398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 if (restart) {
8400 // We have components that still need to be running in the
8401 // process, so re-launch it.
8402 mProcessNames.put(app.processName, app.info.uid, app);
8403 startProcessLocked(app, "restart", app.processName);
8404 } else if (app.pid > 0 && app.pid != MY_PID) {
8405 // Goodbye!
8406 synchronized (mPidsSelfLocked) {
8407 mPidsSelfLocked.remove(app.pid);
8408 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8409 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008410 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008411 }
8412 }
8413
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008414 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8415 // Look through the content providers we are waiting to have launched,
8416 // and if any run in this process then either schedule a restart of
8417 // the process or kill the client waiting for it if this process has
8418 // gone bad.
8419 int NL = mLaunchingProviders.size();
8420 boolean restart = false;
8421 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008422 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008423 if (cpr.launchingApp == app) {
8424 if (!alwaysBad && !app.bad) {
8425 restart = true;
8426 } else {
8427 removeDyingProviderLocked(app, cpr);
8428 NL = mLaunchingProviders.size();
8429 }
8430 }
8431 }
8432 return restart;
8433 }
8434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 // =========================================================
8436 // SERVICES
8437 // =========================================================
8438
8439 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8440 ActivityManager.RunningServiceInfo info =
8441 new ActivityManager.RunningServiceInfo();
8442 info.service = r.name;
8443 if (r.app != null) {
8444 info.pid = r.app.pid;
8445 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008446 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 info.process = r.processName;
8448 info.foreground = r.isForeground;
8449 info.activeSince = r.createTime;
8450 info.started = r.startRequested;
8451 info.clientCount = r.connections.size();
8452 info.crashCount = r.crashCount;
8453 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008454 if (r.isForeground) {
8455 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8456 }
8457 if (r.startRequested) {
8458 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8459 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008460 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008461 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8462 }
8463 if (r.app != null && r.app.persistent) {
8464 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8465 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008466
8467 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8468 for (int i=0; i<connl.size(); i++) {
8469 ConnectionRecord conn = connl.get(i);
8470 if (conn.clientLabel != 0) {
8471 info.clientPackage = conn.binding.client.info.packageName;
8472 info.clientLabel = conn.clientLabel;
8473 return info;
8474 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008475 }
8476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008477 return info;
8478 }
8479
8480 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8481 int flags) {
8482 synchronized (this) {
8483 ArrayList<ActivityManager.RunningServiceInfo> res
8484 = new ArrayList<ActivityManager.RunningServiceInfo>();
8485
8486 if (mServices.size() > 0) {
8487 Iterator<ServiceRecord> it = mServices.values().iterator();
8488 while (it.hasNext() && res.size() < maxNum) {
8489 res.add(makeRunningServiceInfoLocked(it.next()));
8490 }
8491 }
8492
8493 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8494 ServiceRecord r = mRestartingServices.get(i);
8495 ActivityManager.RunningServiceInfo info =
8496 makeRunningServiceInfoLocked(r);
8497 info.restarting = r.nextRestartTime;
8498 res.add(info);
8499 }
8500
8501 return res;
8502 }
8503 }
8504
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008505 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8506 synchronized (this) {
8507 ServiceRecord r = mServices.get(name);
8508 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008509 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8510 for (int i=0; i<conn.size(); i++) {
8511 if (conn.get(i).clientIntent != null) {
8512 return conn.get(i).clientIntent;
8513 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008514 }
8515 }
8516 }
8517 }
8518 return null;
8519 }
8520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 private final ServiceRecord findServiceLocked(ComponentName name,
8522 IBinder token) {
8523 ServiceRecord r = mServices.get(name);
8524 return r == token ? r : null;
8525 }
8526
8527 private final class ServiceLookupResult {
8528 final ServiceRecord record;
8529 final String permission;
8530
8531 ServiceLookupResult(ServiceRecord _record, String _permission) {
8532 record = _record;
8533 permission = _permission;
8534 }
8535 };
8536
8537 private ServiceLookupResult findServiceLocked(Intent service,
8538 String resolvedType) {
8539 ServiceRecord r = null;
8540 if (service.getComponent() != null) {
8541 r = mServices.get(service.getComponent());
8542 }
8543 if (r == null) {
8544 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8545 r = mServicesByIntent.get(filter);
8546 }
8547
8548 if (r == null) {
8549 try {
8550 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008551 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 service, resolvedType, 0);
8553 ServiceInfo sInfo =
8554 rInfo != null ? rInfo.serviceInfo : null;
8555 if (sInfo == null) {
8556 return null;
8557 }
8558
8559 ComponentName name = new ComponentName(
8560 sInfo.applicationInfo.packageName, sInfo.name);
8561 r = mServices.get(name);
8562 } catch (RemoteException ex) {
8563 // pm is in same process, this will never happen.
8564 }
8565 }
8566 if (r != null) {
8567 int callingPid = Binder.getCallingPid();
8568 int callingUid = Binder.getCallingUid();
8569 if (checkComponentPermission(r.permission,
8570 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8571 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008572 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 + " from pid=" + callingPid
8574 + ", uid=" + callingUid
8575 + " requires " + r.permission);
8576 return new ServiceLookupResult(null, r.permission);
8577 }
8578 return new ServiceLookupResult(r, null);
8579 }
8580 return null;
8581 }
8582
8583 private class ServiceRestarter implements Runnable {
8584 private ServiceRecord mService;
8585
8586 void setService(ServiceRecord service) {
8587 mService = service;
8588 }
8589
8590 public void run() {
8591 synchronized(ActivityManagerService.this) {
8592 performServiceRestartLocked(mService);
8593 }
8594 }
8595 }
8596
8597 private ServiceLookupResult retrieveServiceLocked(Intent service,
8598 String resolvedType, int callingPid, int callingUid) {
8599 ServiceRecord r = null;
8600 if (service.getComponent() != null) {
8601 r = mServices.get(service.getComponent());
8602 }
8603 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8604 r = mServicesByIntent.get(filter);
8605 if (r == null) {
8606 try {
8607 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008608 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008609 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008610 ServiceInfo sInfo =
8611 rInfo != null ? rInfo.serviceInfo : null;
8612 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008613 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 ": not found");
8615 return null;
8616 }
8617
8618 ComponentName name = new ComponentName(
8619 sInfo.applicationInfo.packageName, sInfo.name);
8620 r = mServices.get(name);
8621 if (r == null) {
8622 filter = new Intent.FilterComparison(service.cloneFilter());
8623 ServiceRestarter res = new ServiceRestarter();
8624 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8625 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8626 synchronized (stats) {
8627 ss = stats.getServiceStatsLocked(
8628 sInfo.applicationInfo.uid, sInfo.packageName,
8629 sInfo.name);
8630 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008631 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 res.setService(r);
8633 mServices.put(name, r);
8634 mServicesByIntent.put(filter, r);
8635
8636 // Make sure this component isn't in the pending list.
8637 int N = mPendingServices.size();
8638 for (int i=0; i<N; i++) {
8639 ServiceRecord pr = mPendingServices.get(i);
8640 if (pr.name.equals(name)) {
8641 mPendingServices.remove(i);
8642 i--;
8643 N--;
8644 }
8645 }
8646 }
8647 } catch (RemoteException ex) {
8648 // pm is in same process, this will never happen.
8649 }
8650 }
8651 if (r != null) {
8652 if (checkComponentPermission(r.permission,
8653 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8654 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008655 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 + " from pid=" + Binder.getCallingPid()
8657 + ", uid=" + Binder.getCallingUid()
8658 + " requires " + r.permission);
8659 return new ServiceLookupResult(null, r.permission);
8660 }
8661 return new ServiceLookupResult(r, null);
8662 }
8663 return null;
8664 }
8665
Dianne Hackborn287952c2010-09-22 22:34:31 -07008666 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8667 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8668 + why + " of " + r + " in app " + r.app);
8669 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8670 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 long now = SystemClock.uptimeMillis();
8672 if (r.executeNesting == 0 && r.app != null) {
8673 if (r.app.executingServices.size() == 0) {
8674 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8675 msg.obj = r.app;
8676 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8677 }
8678 r.app.executingServices.add(r);
8679 }
8680 r.executeNesting++;
8681 r.executingStart = now;
8682 }
8683
8684 private final void sendServiceArgsLocked(ServiceRecord r,
8685 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008686 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 if (N == 0) {
8688 return;
8689 }
8690
Dianne Hackborn39792d22010-08-19 18:01:52 -07008691 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008693 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008694 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8695 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008696 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008697 // If somehow we got a dummy start at the front, then
8698 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008699 continue;
8700 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008701 si.deliveredTime = SystemClock.uptimeMillis();
8702 r.deliveredStarts.add(si);
8703 si.deliveryCount++;
8704 if (si.targetPermissionUid >= 0) {
8705 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008706 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008707 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008708 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 if (!oomAdjusted) {
8710 oomAdjusted = true;
8711 updateOomAdjLocked(r.app);
8712 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008713 int flags = 0;
8714 if (si.deliveryCount > 0) {
8715 flags |= Service.START_FLAG_RETRY;
8716 }
8717 if (si.doneExecutingCount > 0) {
8718 flags |= Service.START_FLAG_REDELIVERY;
8719 }
8720 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008721 } catch (RemoteException e) {
8722 // Remote process gone... we'll let the normal cleanup take
8723 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008724 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008725 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008727 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 break;
8729 }
8730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 }
8732
8733 private final boolean requestServiceBindingLocked(ServiceRecord r,
8734 IntentBindRecord i, boolean rebind) {
8735 if (r.app == null || r.app.thread == null) {
8736 // If service is not currently running, can't yet bind.
8737 return false;
8738 }
8739 if ((!i.requested || rebind) && i.apps.size() > 0) {
8740 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008741 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8743 if (!rebind) {
8744 i.requested = true;
8745 }
8746 i.hasBound = true;
8747 i.doRebind = false;
8748 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008749 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008750 return false;
8751 }
8752 }
8753 return true;
8754 }
8755
8756 private final void requestServiceBindingsLocked(ServiceRecord r) {
8757 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8758 while (bindings.hasNext()) {
8759 IntentBindRecord i = bindings.next();
8760 if (!requestServiceBindingLocked(r, i, false)) {
8761 break;
8762 }
8763 }
8764 }
8765
8766 private final void realStartServiceLocked(ServiceRecord r,
8767 ProcessRecord app) throws RemoteException {
8768 if (app.thread == null) {
8769 throw new RemoteException();
8770 }
8771
8772 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008773 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008774
8775 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008776 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008777 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778
8779 boolean created = false;
8780 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008781 mStringBuilder.setLength(0);
8782 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008783 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008785 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 synchronized (r.stats.getBatteryStats()) {
8787 r.stats.startLaunchedLocked();
8788 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008789 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008791 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 created = true;
8793 } finally {
8794 if (!created) {
8795 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008796 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008797 }
8798 }
8799
8800 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008801
8802 // If the service is in the started state, and there are no
8803 // pending arguments, then fake up one so its onStartCommand() will
8804 // be called.
8805 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8806 r.lastStartId++;
8807 if (r.lastStartId < 1) {
8808 r.lastStartId = 1;
8809 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008810 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008811 }
8812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 sendServiceArgsLocked(r, true);
8814 }
8815
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008816 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8817 boolean allowCancel) {
8818 boolean canceled = false;
8819
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008820 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008821 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008822 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008823
8824 // Any delivered but not yet finished starts should be put back
8825 // on the pending list.
8826 final int N = r.deliveredStarts.size();
8827 if (N > 0) {
8828 for (int i=N-1; i>=0; i--) {
8829 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008830 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008831 if (si.intent == null) {
8832 // We'll generate this again if needed.
8833 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8834 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8835 r.pendingStarts.add(0, si);
8836 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8837 dur *= 2;
8838 if (minDuration < dur) minDuration = dur;
8839 if (resetTime < dur) resetTime = dur;
8840 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008841 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008842 + r.name);
8843 canceled = true;
8844 }
8845 }
8846 r.deliveredStarts.clear();
8847 }
8848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 r.totalRestartCount++;
8850 if (r.restartDelay == 0) {
8851 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008852 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 } else {
8854 // If it has been a "reasonably long time" since the service
8855 // was started, then reset our restart duration back to
8856 // the beginning, so we don't infinitely increase the duration
8857 // on a service that just occasionally gets killed (which is
8858 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008859 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008861 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008863 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008864 if (r.restartDelay < minDuration) {
8865 r.restartDelay = minDuration;
8866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008867 }
8868 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008869
8870 r.nextRestartTime = now + r.restartDelay;
8871
8872 // Make sure that we don't end up restarting a bunch of services
8873 // all at the same time.
8874 boolean repeat;
8875 do {
8876 repeat = false;
8877 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8878 ServiceRecord r2 = mRestartingServices.get(i);
8879 if (r2 != r && r.nextRestartTime
8880 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8881 && r.nextRestartTime
8882 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8883 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8884 r.restartDelay = r.nextRestartTime - now;
8885 repeat = true;
8886 break;
8887 }
8888 }
8889 } while (repeat);
8890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008891 if (!mRestartingServices.contains(r)) {
8892 mRestartingServices.add(r);
8893 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008894
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008895 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008898 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008899 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008900 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008901 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008902 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008903 r.shortName, r.restartDelay);
8904
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008905 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008906 }
8907
8908 final void performServiceRestartLocked(ServiceRecord r) {
8909 if (!mRestartingServices.contains(r)) {
8910 return;
8911 }
8912 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8913 }
8914
8915 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8916 if (r.restartDelay == 0) {
8917 return false;
8918 }
8919 r.resetRestartCounter();
8920 mRestartingServices.remove(r);
8921 mHandler.removeCallbacks(r.restarter);
8922 return true;
8923 }
8924
8925 private final boolean bringUpServiceLocked(ServiceRecord r,
8926 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008927 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 //r.dump(" ");
8929
Dianne Hackborn36124872009-10-08 16:22:03 -07008930 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 sendServiceArgsLocked(r, false);
8932 return true;
8933 }
8934
8935 if (!whileRestarting && r.restartDelay > 0) {
8936 // If waiting for a restart, then do nothing.
8937 return true;
8938 }
8939
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008940 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008941
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008942 // We are now bringing the service up, so no longer in the
8943 // restarting state.
8944 mRestartingServices.remove(r);
8945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 final String appName = r.processName;
8947 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8948 if (app != null && app.thread != null) {
8949 try {
8950 realStartServiceLocked(r, app);
8951 return true;
8952 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008953 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 }
8955
8956 // If a dead object exception was thrown -- fall through to
8957 // restart the application.
8958 }
8959
Dianne Hackborn36124872009-10-08 16:22:03 -07008960 // Not running -- get it started, and enqueue this service record
8961 // to be executed when the app comes up.
8962 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8963 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008964 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008965 + r.appInfo.packageName + "/"
8966 + r.appInfo.uid + " for service "
8967 + r.intent.getIntent() + ": process is bad");
8968 bringDownServiceLocked(r, true);
8969 return false;
8970 }
8971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008972 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 mPendingServices.add(r);
8974 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 return true;
8977 }
8978
8979 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008980 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008981 //r.dump(" ");
8982
8983 // Does it still need to run?
8984 if (!force && r.startRequested) {
8985 return;
8986 }
8987 if (r.connections.size() > 0) {
8988 if (!force) {
8989 // XXX should probably keep a count of the number of auto-create
8990 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008991 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008993 ArrayList<ConnectionRecord> cr = it.next();
8994 for (int i=0; i<cr.size(); i++) {
8995 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8996 return;
8997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 }
8999 }
9000 }
9001
9002 // Report to all of the connections that the service is no longer
9003 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009004 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009006 ArrayList<ConnectionRecord> c = it.next();
9007 for (int i=0; i<c.size(); i++) {
9008 try {
9009 c.get(i).conn.connected(r.name, null);
9010 } catch (Exception e) {
9011 Slog.w(TAG, "Failure disconnecting service " + r.name +
9012 " to connection " + c.get(i).conn.asBinder() +
9013 " (in " + c.get(i).binding.client.processName + ")", e);
9014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009015 }
9016 }
9017 }
9018
9019 // Tell the service that it has been unbound.
9020 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9021 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9022 while (it.hasNext()) {
9023 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009024 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 + ": hasBound=" + ibr.hasBound);
9026 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9027 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009028 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009029 updateOomAdjLocked(r.app);
9030 ibr.hasBound = false;
9031 r.app.thread.scheduleUnbindService(r,
9032 ibr.intent.getIntent());
9033 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009034 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009035 + r.shortName, e);
9036 serviceDoneExecutingLocked(r, true);
9037 }
9038 }
9039 }
9040 }
9041
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009042 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009043 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 System.identityHashCode(r), r.shortName,
9045 (r.app != null) ? r.app.pid : -1);
9046
9047 mServices.remove(r.name);
9048 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 r.totalRestartCount = 0;
9050 unscheduleServiceRestartLocked(r);
9051
9052 // Also make sure it is not on the pending list.
9053 int N = mPendingServices.size();
9054 for (int i=0; i<N; i++) {
9055 if (mPendingServices.get(i) == r) {
9056 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009057 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 i--;
9059 N--;
9060 }
9061 }
9062
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009063 r.cancelNotification();
9064 r.isForeground = false;
9065 r.foregroundId = 0;
9066 r.foregroundNoti = null;
9067
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009068 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009069 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009070 r.pendingStarts.clear();
9071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 if (r.app != null) {
9073 synchronized (r.stats.getBatteryStats()) {
9074 r.stats.stopLaunchedLocked();
9075 }
9076 r.app.services.remove(r);
9077 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009078 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009079 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 mStoppingServices.add(r);
9081 updateOomAdjLocked(r.app);
9082 r.app.thread.scheduleStopService(r);
9083 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009084 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 + r.shortName, e);
9086 serviceDoneExecutingLocked(r, true);
9087 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009088 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009090 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009091 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 }
9093 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009094 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009095 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009097
9098 if (r.bindings.size() > 0) {
9099 r.bindings.clear();
9100 }
9101
9102 if (r.restarter instanceof ServiceRestarter) {
9103 ((ServiceRestarter)r.restarter).setService(null);
9104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009105 }
9106
9107 ComponentName startServiceLocked(IApplicationThread caller,
9108 Intent service, String resolvedType,
9109 int callingPid, int callingUid) {
9110 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009111 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 + " type=" + resolvedType + " args=" + service.getExtras());
9113
9114 if (caller != null) {
9115 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9116 if (callerApp == null) {
9117 throw new SecurityException(
9118 "Unable to find app for caller " + caller
9119 + " (pid=" + Binder.getCallingPid()
9120 + ") when starting service " + service);
9121 }
9122 }
9123
9124 ServiceLookupResult res =
9125 retrieveServiceLocked(service, resolvedType,
9126 callingPid, callingUid);
9127 if (res == null) {
9128 return null;
9129 }
9130 if (res.record == null) {
9131 return new ComponentName("!", res.permission != null
9132 ? res.permission : "private to package");
9133 }
9134 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009135 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9136 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009138 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 }
9140 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009141 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009142 r.lastStartId++;
9143 if (r.lastStartId < 1) {
9144 r.lastStartId = 1;
9145 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009146 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9147 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 r.lastActivity = SystemClock.uptimeMillis();
9149 synchronized (r.stats.getBatteryStats()) {
9150 r.stats.startRunningLocked();
9151 }
9152 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9153 return new ComponentName("!", "Service process is bad");
9154 }
9155 return r.name;
9156 }
9157 }
9158
9159 public ComponentName startService(IApplicationThread caller, Intent service,
9160 String resolvedType) {
9161 // Refuse possible leaked file descriptors
9162 if (service != null && service.hasFileDescriptors() == true) {
9163 throw new IllegalArgumentException("File descriptors passed in Intent");
9164 }
9165
9166 synchronized(this) {
9167 final int callingPid = Binder.getCallingPid();
9168 final int callingUid = Binder.getCallingUid();
9169 final long origId = Binder.clearCallingIdentity();
9170 ComponentName res = startServiceLocked(caller, service,
9171 resolvedType, callingPid, callingUid);
9172 Binder.restoreCallingIdentity(origId);
9173 return res;
9174 }
9175 }
9176
9177 ComponentName startServiceInPackage(int uid,
9178 Intent service, String resolvedType) {
9179 synchronized(this) {
9180 final long origId = Binder.clearCallingIdentity();
9181 ComponentName res = startServiceLocked(null, service,
9182 resolvedType, -1, uid);
9183 Binder.restoreCallingIdentity(origId);
9184 return res;
9185 }
9186 }
9187
9188 public int stopService(IApplicationThread caller, Intent service,
9189 String resolvedType) {
9190 // Refuse possible leaked file descriptors
9191 if (service != null && service.hasFileDescriptors() == true) {
9192 throw new IllegalArgumentException("File descriptors passed in Intent");
9193 }
9194
9195 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009196 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009197 + " type=" + resolvedType);
9198
9199 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9200 if (caller != null && callerApp == null) {
9201 throw new SecurityException(
9202 "Unable to find app for caller " + caller
9203 + " (pid=" + Binder.getCallingPid()
9204 + ") when stopping service " + service);
9205 }
9206
9207 // If this service is active, make sure it is stopped.
9208 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9209 if (r != null) {
9210 if (r.record != null) {
9211 synchronized (r.record.stats.getBatteryStats()) {
9212 r.record.stats.stopRunningLocked();
9213 }
9214 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009215 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009216 final long origId = Binder.clearCallingIdentity();
9217 bringDownServiceLocked(r.record, false);
9218 Binder.restoreCallingIdentity(origId);
9219 return 1;
9220 }
9221 return -1;
9222 }
9223 }
9224
9225 return 0;
9226 }
9227
9228 public IBinder peekService(Intent service, String resolvedType) {
9229 // Refuse possible leaked file descriptors
9230 if (service != null && service.hasFileDescriptors() == true) {
9231 throw new IllegalArgumentException("File descriptors passed in Intent");
9232 }
9233
9234 IBinder ret = null;
9235
9236 synchronized(this) {
9237 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9238
9239 if (r != null) {
9240 // r.record is null if findServiceLocked() failed the caller permission check
9241 if (r.record == null) {
9242 throw new SecurityException(
lge-aospc7122042011-01-07 13:45:37 +09009243 "Permission Denial: Accessing service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009244 + " from pid=" + Binder.getCallingPid()
9245 + ", uid=" + Binder.getCallingUid()
9246 + " requires " + r.permission);
9247 }
9248 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9249 if (ib != null) {
9250 ret = ib.binder;
9251 }
9252 }
9253 }
9254
9255 return ret;
9256 }
9257
9258 public boolean stopServiceToken(ComponentName className, IBinder token,
9259 int startId) {
9260 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009261 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 + " " + token + " startId=" + startId);
9263 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009264 if (r != null) {
9265 if (startId >= 0) {
9266 // Asked to only stop if done with all work. Note that
9267 // to avoid leaks, we will take this as dropping all
9268 // start items up to and including this one.
9269 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9270 if (si != null) {
9271 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009272 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9273 cur.removeUriPermissionsLocked();
9274 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009275 break;
9276 }
9277 }
9278 }
9279
9280 if (r.lastStartId != startId) {
9281 return false;
9282 }
9283
9284 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009285 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009286 + " is last, but have " + r.deliveredStarts.size()
9287 + " remaining args");
9288 }
9289 }
9290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 synchronized (r.stats.getBatteryStats()) {
9292 r.stats.stopRunningLocked();
9293 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009294 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 }
9296 final long origId = Binder.clearCallingIdentity();
9297 bringDownServiceLocked(r, false);
9298 Binder.restoreCallingIdentity(origId);
9299 return true;
9300 }
9301 }
9302 return false;
9303 }
9304
9305 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009306 int id, Notification notification, boolean removeNotification) {
9307 final long origId = Binder.clearCallingIdentity();
9308 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 synchronized(this) {
9310 ServiceRecord r = findServiceLocked(className, token);
9311 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009312 if (id != 0) {
9313 if (notification == null) {
9314 throw new IllegalArgumentException("null notification");
9315 }
9316 if (r.foregroundId != id) {
9317 r.cancelNotification();
9318 r.foregroundId = id;
9319 }
9320 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9321 r.foregroundNoti = notification;
9322 r.isForeground = true;
9323 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 if (r.app != null) {
9325 updateServiceForegroundLocked(r.app, true);
9326 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009327 } else {
9328 if (r.isForeground) {
9329 r.isForeground = false;
9330 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009331 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009332 updateServiceForegroundLocked(r.app, true);
9333 }
9334 }
9335 if (removeNotification) {
9336 r.cancelNotification();
9337 r.foregroundId = 0;
9338 r.foregroundNoti = null;
9339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 }
9341 }
9342 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009343 } finally {
9344 Binder.restoreCallingIdentity(origId);
9345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 }
9347
9348 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9349 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009350 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009351 if (sr.isForeground) {
9352 anyForeground = true;
9353 break;
9354 }
9355 }
9356 if (anyForeground != proc.foregroundServices) {
9357 proc.foregroundServices = anyForeground;
9358 if (oomAdj) {
9359 updateOomAdjLocked();
9360 }
9361 }
9362 }
9363
9364 public int bindService(IApplicationThread caller, IBinder token,
9365 Intent service, String resolvedType,
9366 IServiceConnection connection, int flags) {
9367 // Refuse possible leaked file descriptors
9368 if (service != null && service.hasFileDescriptors() == true) {
9369 throw new IllegalArgumentException("File descriptors passed in Intent");
9370 }
9371
9372 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009373 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 + " type=" + resolvedType + " conn=" + connection.asBinder()
9375 + " flags=0x" + Integer.toHexString(flags));
9376 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9377 if (callerApp == null) {
9378 throw new SecurityException(
9379 "Unable to find app for caller " + caller
9380 + " (pid=" + Binder.getCallingPid()
9381 + ") when binding service " + service);
9382 }
9383
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009384 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009386 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009388 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 return 0;
9390 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009391 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 }
9393
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009394 int clientLabel = 0;
9395 PendingIntent clientIntent = null;
9396
9397 if (callerApp.info.uid == Process.SYSTEM_UID) {
9398 // Hacky kind of thing -- allow system stuff to tell us
9399 // what they are, so we can report this elsewhere for
9400 // others to know why certain services are running.
9401 try {
9402 clientIntent = (PendingIntent)service.getParcelableExtra(
9403 Intent.EXTRA_CLIENT_INTENT);
9404 } catch (RuntimeException e) {
9405 }
9406 if (clientIntent != null) {
9407 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9408 if (clientLabel != 0) {
9409 // There are no useful extras in the intent, trash them.
9410 // System code calling with this stuff just needs to know
9411 // this will happen.
9412 service = service.cloneFilter();
9413 }
9414 }
9415 }
9416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417 ServiceLookupResult res =
9418 retrieveServiceLocked(service, resolvedType,
9419 Binder.getCallingPid(), Binder.getCallingUid());
9420 if (res == null) {
9421 return 0;
9422 }
9423 if (res.record == null) {
9424 return -1;
9425 }
9426 ServiceRecord s = res.record;
9427
9428 final long origId = Binder.clearCallingIdentity();
9429
9430 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009431 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009432 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009433 }
9434
9435 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9436 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009437 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438
9439 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009440 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9441 if (clist == null) {
9442 clist = new ArrayList<ConnectionRecord>();
9443 s.connections.put(binder, clist);
9444 }
9445 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 b.connections.add(c);
9447 if (activity != null) {
9448 if (activity.connections == null) {
9449 activity.connections = new HashSet<ConnectionRecord>();
9450 }
9451 activity.connections.add(c);
9452 }
9453 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009454 clist = mServiceConnections.get(binder);
9455 if (clist == null) {
9456 clist = new ArrayList<ConnectionRecord>();
9457 mServiceConnections.put(binder, clist);
9458 }
9459 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460
9461 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9462 s.lastActivity = SystemClock.uptimeMillis();
9463 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9464 return 0;
9465 }
9466 }
9467
9468 if (s.app != null) {
9469 // This could have made the service more important.
9470 updateOomAdjLocked(s.app);
9471 }
9472
Joe Onorato8a9b2202010-02-26 18:56:32 -08009473 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009474 + ": received=" + b.intent.received
9475 + " apps=" + b.intent.apps.size()
9476 + " doRebind=" + b.intent.doRebind);
9477
9478 if (s.app != null && b.intent.received) {
9479 // Service is already running, so we can immediately
9480 // publish the connection.
9481 try {
9482 c.conn.connected(s.name, b.intent.binder);
9483 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009484 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009485 + " to connection " + c.conn.asBinder()
9486 + " (in " + c.binding.client.processName + ")", e);
9487 }
9488
9489 // If this is the first app connected back to this binding,
9490 // and the service had previously asked to be told when
9491 // rebound, then do so.
9492 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9493 requestServiceBindingLocked(s, b.intent, true);
9494 }
9495 } else if (!b.intent.requested) {
9496 requestServiceBindingLocked(s, b.intent, false);
9497 }
9498
9499 Binder.restoreCallingIdentity(origId);
9500 }
9501
9502 return 1;
9503 }
9504
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009505 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009506 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 IBinder binder = c.conn.asBinder();
9508 AppBindRecord b = c.binding;
9509 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009510 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9511 if (clist != null) {
9512 clist.remove(c);
9513 if (clist.size() == 0) {
9514 s.connections.remove(binder);
9515 }
9516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 b.connections.remove(c);
9518 if (c.activity != null && c.activity != skipAct) {
9519 if (c.activity.connections != null) {
9520 c.activity.connections.remove(c);
9521 }
9522 }
9523 if (b.client != skipApp) {
9524 b.client.connections.remove(c);
9525 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009526 clist = mServiceConnections.get(binder);
9527 if (clist != null) {
9528 clist.remove(c);
9529 if (clist.size() == 0) {
9530 mServiceConnections.remove(binder);
9531 }
9532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009533
9534 if (b.connections.size() == 0) {
9535 b.intent.apps.remove(b.client);
9536 }
9537
Joe Onorato8a9b2202010-02-26 18:56:32 -08009538 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 + ": shouldUnbind=" + b.intent.hasBound);
9540 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9541 && b.intent.hasBound) {
9542 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009543 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 updateOomAdjLocked(s.app);
9545 b.intent.hasBound = false;
9546 // Assume the client doesn't want to know about a rebind;
9547 // we will deal with that later if it asks for one.
9548 b.intent.doRebind = false;
9549 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9550 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009551 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 serviceDoneExecutingLocked(s, true);
9553 }
9554 }
9555
9556 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9557 bringDownServiceLocked(s, false);
9558 }
9559 }
9560
9561 public boolean unbindService(IServiceConnection connection) {
9562 synchronized (this) {
9563 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009564 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009565 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9566 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009567 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 + connection.asBinder());
9569 return false;
9570 }
9571
9572 final long origId = Binder.clearCallingIdentity();
9573
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009574 while (clist.size() > 0) {
9575 ConnectionRecord r = clist.get(0);
9576 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009578 if (r.binding.service.app != null) {
9579 // This could have made the service less important.
9580 updateOomAdjLocked(r.binding.service.app);
9581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 }
9583
9584 Binder.restoreCallingIdentity(origId);
9585 }
9586
9587 return true;
9588 }
9589
9590 public void publishService(IBinder token, Intent intent, IBinder service) {
9591 // Refuse possible leaked file descriptors
9592 if (intent != null && intent.hasFileDescriptors() == true) {
9593 throw new IllegalArgumentException("File descriptors passed in Intent");
9594 }
9595
9596 synchronized(this) {
9597 if (!(token instanceof ServiceRecord)) {
9598 throw new IllegalArgumentException("Invalid service token");
9599 }
9600 ServiceRecord r = (ServiceRecord)token;
9601
9602 final long origId = Binder.clearCallingIdentity();
9603
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009604 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009605 + " " + intent + ": " + service);
9606 if (r != null) {
9607 Intent.FilterComparison filter
9608 = new Intent.FilterComparison(intent);
9609 IntentBindRecord b = r.bindings.get(filter);
9610 if (b != null && !b.received) {
9611 b.binder = service;
9612 b.requested = true;
9613 b.received = true;
9614 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009615 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 = r.connections.values().iterator();
9617 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009618 ArrayList<ConnectionRecord> clist = it.next();
9619 for (int i=0; i<clist.size(); i++) {
9620 ConnectionRecord c = clist.get(i);
9621 if (!filter.equals(c.binding.intent.intent)) {
9622 if (DEBUG_SERVICE) Slog.v(
9623 TAG, "Not publishing to: " + c);
9624 if (DEBUG_SERVICE) Slog.v(
9625 TAG, "Bound intent: " + c.binding.intent.intent);
9626 if (DEBUG_SERVICE) Slog.v(
9627 TAG, "Published intent: " + intent);
9628 continue;
9629 }
9630 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9631 try {
9632 c.conn.connected(r.name, service);
9633 } catch (Exception e) {
9634 Slog.w(TAG, "Failure sending service " + r.name +
9635 " to connection " + c.conn.asBinder() +
9636 " (in " + c.binding.client.processName + ")", e);
9637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 }
9639 }
9640 }
9641 }
9642
9643 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9644
9645 Binder.restoreCallingIdentity(origId);
9646 }
9647 }
9648 }
9649
9650 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9651 // Refuse possible leaked file descriptors
9652 if (intent != null && intent.hasFileDescriptors() == true) {
9653 throw new IllegalArgumentException("File descriptors passed in Intent");
9654 }
9655
9656 synchronized(this) {
9657 if (!(token instanceof ServiceRecord)) {
9658 throw new IllegalArgumentException("Invalid service token");
9659 }
9660 ServiceRecord r = (ServiceRecord)token;
9661
9662 final long origId = Binder.clearCallingIdentity();
9663
9664 if (r != null) {
9665 Intent.FilterComparison filter
9666 = new Intent.FilterComparison(intent);
9667 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009668 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009669 + " at " + b + ": apps="
9670 + (b != null ? b.apps.size() : 0));
9671 if (b != null) {
9672 if (b.apps.size() > 0) {
9673 // Applications have already bound since the last
9674 // unbind, so just rebind right here.
9675 requestServiceBindingLocked(r, b, true);
9676 } else {
9677 // Note to tell the service the next time there is
9678 // a new client.
9679 b.doRebind = true;
9680 }
9681 }
9682
9683 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9684
9685 Binder.restoreCallingIdentity(origId);
9686 }
9687 }
9688 }
9689
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009690 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 synchronized(this) {
9692 if (!(token instanceof ServiceRecord)) {
9693 throw new IllegalArgumentException("Invalid service token");
9694 }
9695 ServiceRecord r = (ServiceRecord)token;
9696 boolean inStopping = mStoppingServices.contains(token);
9697 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009699 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 + " with incorrect token: given " + token
9701 + ", expected " + r);
9702 return;
9703 }
9704
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009705 if (type == 1) {
9706 // This is a call from a service start... take care of
9707 // book-keeping.
9708 r.callStart = true;
9709 switch (res) {
9710 case Service.START_STICKY_COMPATIBILITY:
9711 case Service.START_STICKY: {
9712 // We are done with the associated start arguments.
9713 r.findDeliveredStart(startId, true);
9714 // Don't stop if killed.
9715 r.stopIfKilled = false;
9716 break;
9717 }
9718 case Service.START_NOT_STICKY: {
9719 // We are done with the associated start arguments.
9720 r.findDeliveredStart(startId, true);
9721 if (r.lastStartId == startId) {
9722 // There is no more work, and this service
9723 // doesn't want to hang around if killed.
9724 r.stopIfKilled = true;
9725 }
9726 break;
9727 }
9728 case Service.START_REDELIVER_INTENT: {
9729 // We'll keep this item until they explicitly
9730 // call stop for it, but keep track of the fact
9731 // that it was delivered.
9732 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9733 if (si != null) {
9734 si.deliveryCount = 0;
9735 si.doneExecutingCount++;
9736 // Don't stop if killed.
9737 r.stopIfKilled = true;
9738 }
9739 break;
9740 }
9741 default:
9742 throw new IllegalArgumentException(
9743 "Unknown service start result: " + res);
9744 }
9745 if (res == Service.START_STICKY_COMPATIBILITY) {
9746 r.callStart = false;
9747 }
9748 }
9749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 final long origId = Binder.clearCallingIdentity();
9751 serviceDoneExecutingLocked(r, inStopping);
9752 Binder.restoreCallingIdentity(origId);
9753 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009754 Slog.w(TAG, "Done executing unknown service from pid "
9755 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756 }
9757 }
9758 }
9759
9760 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009761 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9762 + ": nesting=" + r.executeNesting
9763 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009764 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 r.executeNesting--;
9766 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009767 if (DEBUG_SERVICE) Slog.v(TAG,
9768 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009769 r.app.executingServices.remove(r);
9770 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009771 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9772 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9774 }
9775 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009776 if (DEBUG_SERVICE) Slog.v(TAG,
9777 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +02009779 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 }
9781 updateOomAdjLocked(r.app);
9782 }
9783 }
9784
9785 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009786 String anrMessage = null;
9787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 synchronized(this) {
9789 if (proc.executingServices.size() == 0 || proc.thread == null) {
9790 return;
9791 }
9792 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9793 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9794 ServiceRecord timeout = null;
9795 long nextTime = 0;
9796 while (it.hasNext()) {
9797 ServiceRecord sr = it.next();
9798 if (sr.executingStart < maxTime) {
9799 timeout = sr;
9800 break;
9801 }
9802 if (sr.executingStart > nextTime) {
9803 nextTime = sr.executingStart;
9804 }
9805 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009806 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009807 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009808 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809 } else {
9810 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9811 msg.obj = proc;
9812 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9813 }
9814 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009815
9816 if (anrMessage != null) {
9817 appNotResponding(proc, null, null, anrMessage);
9818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 }
9820
9821 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009822 // BACKUP AND RESTORE
9823 // =========================================================
9824
9825 // Cause the target app to be launched if necessary and its backup agent
9826 // instantiated. The backup agent will invoke backupAgentCreated() on the
9827 // activity manager to announce its creation.
9828 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009829 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009830 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9831
9832 synchronized(this) {
9833 // !!! TODO: currently no check here that we're already bound
9834 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9835 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9836 synchronized (stats) {
9837 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9838 }
9839
9840 BackupRecord r = new BackupRecord(ss, app, backupMode);
9841 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9842 // startProcessLocked() returns existing proc's record if it's already running
9843 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009844 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009845 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009846 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009847 return false;
9848 }
9849
9850 r.app = proc;
9851 mBackupTarget = r;
9852 mBackupAppName = app.packageName;
9853
Christopher Tate6fa95972009-06-05 18:43:55 -07009854 // Try not to kill the process during backup
9855 updateOomAdjLocked(proc);
9856
Christopher Tate181fafa2009-05-14 11:12:14 -07009857 // If the process is already attached, schedule the creation of the backup agent now.
9858 // If it is not yet live, this will be done when it attaches to the framework.
9859 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009860 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009861 try {
9862 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9863 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009864 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009865 }
9866 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009867 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009868 }
9869 // Invariants: at this point, the target app process exists and the application
9870 // is either already running or in the process of coming up. mBackupTarget and
9871 // mBackupAppName describe the app, so that when it binds back to the AM we
9872 // know that it's scheduled for a backup-agent operation.
9873 }
9874
9875 return true;
9876 }
9877
9878 // A backup agent has just come up
9879 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009880 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009881 + " = " + agent);
9882
9883 synchronized(this) {
9884 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009885 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009886 return;
9887 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009888 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009889
Dianne Hackborn06740692010-09-22 22:46:21 -07009890 long oldIdent = Binder.clearCallingIdentity();
9891 try {
9892 IBackupManager bm = IBackupManager.Stub.asInterface(
9893 ServiceManager.getService(Context.BACKUP_SERVICE));
9894 bm.agentConnected(agentPackageName, agent);
9895 } catch (RemoteException e) {
9896 // can't happen; the backup manager service is local
9897 } catch (Exception e) {
9898 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9899 e.printStackTrace();
9900 } finally {
9901 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009902 }
9903 }
9904
9905 // done with this agent
9906 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009907 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009908 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009909 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009910 return;
9911 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009912
9913 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009914 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009915 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009916 return;
9917 }
9918
Christopher Tate181fafa2009-05-14 11:12:14 -07009919 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009920 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009921 return;
9922 }
9923
Christopher Tate6fa95972009-06-05 18:43:55 -07009924 ProcessRecord proc = mBackupTarget.app;
9925 mBackupTarget = null;
9926 mBackupAppName = null;
9927
9928 // Not backing this app up any more; reset its OOM adjustment
9929 updateOomAdjLocked(proc);
9930
Christopher Tatec7b31e32009-06-10 15:49:30 -07009931 // If the app crashed during backup, 'thread' will be null here
9932 if (proc.thread != null) {
9933 try {
9934 proc.thread.scheduleDestroyBackupAgent(appInfo);
9935 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009936 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009937 e.printStackTrace();
9938 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009939 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009940 }
9941 }
9942 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 // BROADCASTS
9944 // =========================================================
9945
Josh Bartel7f208742010-02-25 11:01:44 -06009946 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009947 List cur) {
9948 final ContentResolver resolver = mContext.getContentResolver();
9949 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9950 if (list == null) {
9951 return cur;
9952 }
9953 int N = list.size();
9954 for (int i=0; i<N; i++) {
9955 Intent intent = list.get(i);
9956 if (filter.match(resolver, intent, true, TAG) >= 0) {
9957 if (cur == null) {
9958 cur = new ArrayList<Intent>();
9959 }
9960 cur.add(intent);
9961 }
9962 }
9963 return cur;
9964 }
9965
9966 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009967 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009968 + mBroadcastsScheduled);
9969
9970 if (mBroadcastsScheduled) {
9971 return;
9972 }
9973 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9974 mBroadcastsScheduled = true;
9975 }
9976
9977 public Intent registerReceiver(IApplicationThread caller,
9978 IIntentReceiver receiver, IntentFilter filter, String permission) {
9979 synchronized(this) {
9980 ProcessRecord callerApp = null;
9981 if (caller != null) {
9982 callerApp = getRecordForAppLocked(caller);
9983 if (callerApp == null) {
9984 throw new SecurityException(
9985 "Unable to find app for caller " + caller
9986 + " (pid=" + Binder.getCallingPid()
9987 + ") when registering receiver " + receiver);
9988 }
9989 }
9990
9991 List allSticky = null;
9992
9993 // Look for any matching sticky broadcasts...
9994 Iterator actions = filter.actionsIterator();
9995 if (actions != null) {
9996 while (actions.hasNext()) {
9997 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009998 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009999 }
10000 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010001 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 }
10003
10004 // The first sticky in the list is returned directly back to
10005 // the client.
10006 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10007
Joe Onorato8a9b2202010-02-26 18:56:32 -080010008 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 + ": " + sticky);
10010
10011 if (receiver == null) {
10012 return sticky;
10013 }
10014
10015 ReceiverList rl
10016 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10017 if (rl == null) {
10018 rl = new ReceiverList(this, callerApp,
10019 Binder.getCallingPid(),
10020 Binder.getCallingUid(), receiver);
10021 if (rl.app != null) {
10022 rl.app.receivers.add(rl);
10023 } else {
10024 try {
10025 receiver.asBinder().linkToDeath(rl, 0);
10026 } catch (RemoteException e) {
10027 return sticky;
10028 }
10029 rl.linkedToDeath = true;
10030 }
10031 mRegisteredReceivers.put(receiver.asBinder(), rl);
10032 }
10033 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10034 rl.add(bf);
10035 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010036 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010037 }
10038 mReceiverResolver.addFilter(bf);
10039
10040 // Enqueue broadcasts for all existing stickies that match
10041 // this filter.
10042 if (allSticky != null) {
10043 ArrayList receivers = new ArrayList();
10044 receivers.add(bf);
10045
10046 int N = allSticky.size();
10047 for (int i=0; i<N; i++) {
10048 Intent intent = (Intent)allSticky.get(i);
10049 BroadcastRecord r = new BroadcastRecord(intent, null,
10050 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010051 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 if (mParallelBroadcasts.size() == 0) {
10053 scheduleBroadcastsLocked();
10054 }
10055 mParallelBroadcasts.add(r);
10056 }
10057 }
10058
10059 return sticky;
10060 }
10061 }
10062
10063 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010064 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065
10066 boolean doNext = false;
10067
10068 synchronized(this) {
10069 ReceiverList rl
10070 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10071 if (rl != null) {
10072 if (rl.curBroadcast != null) {
10073 BroadcastRecord r = rl.curBroadcast;
10074 doNext = finishReceiverLocked(
10075 receiver.asBinder(), r.resultCode, r.resultData,
10076 r.resultExtras, r.resultAbort, true);
10077 }
10078
10079 if (rl.app != null) {
10080 rl.app.receivers.remove(rl);
10081 }
10082 removeReceiverLocked(rl);
10083 if (rl.linkedToDeath) {
10084 rl.linkedToDeath = false;
10085 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10086 }
10087 }
10088 }
10089
10090 if (!doNext) {
10091 return;
10092 }
10093
10094 final long origId = Binder.clearCallingIdentity();
10095 processNextBroadcast(false);
10096 trimApplications();
10097 Binder.restoreCallingIdentity(origId);
10098 }
10099
10100 void removeReceiverLocked(ReceiverList rl) {
10101 mRegisteredReceivers.remove(rl.receiver.asBinder());
10102 int N = rl.size();
10103 for (int i=0; i<N; i++) {
10104 mReceiverResolver.removeFilter(rl.get(i));
10105 }
10106 }
10107
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010108 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10109 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10110 ProcessRecord r = mLruProcesses.get(i);
10111 if (r.thread != null) {
10112 try {
10113 r.thread.dispatchPackageBroadcast(cmd, packages);
10114 } catch (RemoteException ex) {
10115 }
10116 }
10117 }
10118 }
10119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010120 private final int broadcastIntentLocked(ProcessRecord callerApp,
10121 String callerPackage, Intent intent, String resolvedType,
10122 IIntentReceiver resultTo, int resultCode, String resultData,
10123 Bundle map, String requiredPermission,
10124 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10125 intent = new Intent(intent);
10126
Joe Onorato8a9b2202010-02-26 18:56:32 -080010127 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010128 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10129 + " ordered=" + ordered);
10130 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010131 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010132 }
10133
10134 // Handle special intents: if this broadcast is from the package
10135 // manager about a package being removed, we need to remove all of
10136 // its activities from the history stack.
10137 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10138 intent.getAction());
10139 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10140 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010141 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 || uidRemoved) {
10143 if (checkComponentPermission(
10144 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10145 callingPid, callingUid, -1)
10146 == PackageManager.PERMISSION_GRANTED) {
10147 if (uidRemoved) {
10148 final Bundle intentExtras = intent.getExtras();
10149 final int uid = intentExtras != null
10150 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10151 if (uid >= 0) {
10152 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10153 synchronized (bs) {
10154 bs.removeUidStatsLocked(uid);
10155 }
10156 }
10157 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010158 // If resources are unvailble just force stop all
10159 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010160 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010161 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10162 if (list != null && (list.length > 0)) {
10163 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010164 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010165 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010166 sendPackageBroadcastLocked(
10167 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010168 }
10169 } else {
10170 Uri data = intent.getData();
10171 String ssp;
10172 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10173 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10174 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010175 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010176 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010177 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10178 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10179 new String[] {ssp});
10180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010181 }
10182 }
10183 }
10184 } else {
10185 String msg = "Permission Denial: " + intent.getAction()
10186 + " broadcast from " + callerPackage + " (pid=" + callingPid
10187 + ", uid=" + callingUid + ")"
10188 + " requires "
10189 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010190 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 throw new SecurityException(msg);
10192 }
10193 }
10194
10195 /*
10196 * If this is the time zone changed action, queue up a message that will reset the timezone
10197 * of all currently running processes. This message will get queued up before the broadcast
10198 * happens.
10199 */
10200 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10201 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10202 }
10203
Dianne Hackborn854060af2009-07-09 18:14:31 -070010204 /*
10205 * Prevent non-system code (defined here to be non-persistent
10206 * processes) from sending protected broadcasts.
10207 */
10208 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10209 || callingUid == Process.SHELL_UID || callingUid == 0) {
10210 // Always okay.
10211 } else if (callerApp == null || !callerApp.persistent) {
10212 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010213 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010214 intent.getAction())) {
10215 String msg = "Permission Denial: not allowed to send broadcast "
10216 + intent.getAction() + " from pid="
10217 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010218 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010219 throw new SecurityException(msg);
10220 }
10221 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010222 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010223 return BROADCAST_SUCCESS;
10224 }
10225 }
10226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 // Add to the sticky list if requested.
10228 if (sticky) {
10229 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10230 callingPid, callingUid)
10231 != PackageManager.PERMISSION_GRANTED) {
10232 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10233 + callingPid + ", uid=" + callingUid
10234 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010235 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 throw new SecurityException(msg);
10237 }
10238 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010239 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010240 + " and enforce permission " + requiredPermission);
10241 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10242 }
10243 if (intent.getComponent() != null) {
10244 throw new SecurityException(
10245 "Sticky broadcasts can't target a specific component");
10246 }
10247 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10248 if (list == null) {
10249 list = new ArrayList<Intent>();
10250 mStickyBroadcasts.put(intent.getAction(), list);
10251 }
10252 int N = list.size();
10253 int i;
10254 for (i=0; i<N; i++) {
10255 if (intent.filterEquals(list.get(i))) {
10256 // This sticky already exists, replace it.
10257 list.set(i, new Intent(intent));
10258 break;
10259 }
10260 }
10261 if (i >= N) {
10262 list.add(new Intent(intent));
10263 }
10264 }
10265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 // Figure out who all will receive this broadcast.
10267 List receivers = null;
10268 List<BroadcastFilter> registeredReceivers = null;
10269 try {
10270 if (intent.getComponent() != null) {
10271 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010272 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010273 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 if (ai != null) {
10275 receivers = new ArrayList();
10276 ResolveInfo ri = new ResolveInfo();
10277 ri.activityInfo = ai;
10278 receivers.add(ri);
10279 }
10280 } else {
10281 // Need to resolve the intent to interested receivers...
10282 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10283 == 0) {
10284 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010285 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010286 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 }
Mihai Preda074edef2009-05-18 17:13:31 +020010288 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 }
10290 } catch (RemoteException ex) {
10291 // pm is in same process, this will never happen.
10292 }
10293
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010294 final boolean replacePending =
10295 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10296
Joe Onorato8a9b2202010-02-26 18:56:32 -080010297 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010298 + " replacePending=" + replacePending);
10299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10301 if (!ordered && NR > 0) {
10302 // If we are not serializing this broadcast, then send the
10303 // registered receivers separately so they don't wait for the
10304 // components to be launched.
10305 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10306 callerPackage, callingPid, callingUid, requiredPermission,
10307 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010308 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010309 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310 TAG, "Enqueueing parallel broadcast " + r
10311 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010312 boolean replaced = false;
10313 if (replacePending) {
10314 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10315 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010316 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010317 "***** DROPPING PARALLEL: " + intent);
10318 mParallelBroadcasts.set(i, r);
10319 replaced = true;
10320 break;
10321 }
10322 }
10323 }
10324 if (!replaced) {
10325 mParallelBroadcasts.add(r);
10326 scheduleBroadcastsLocked();
10327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 registeredReceivers = null;
10329 NR = 0;
10330 }
10331
10332 // Merge into one list.
10333 int ir = 0;
10334 if (receivers != null) {
10335 // A special case for PACKAGE_ADDED: do not allow the package
10336 // being added to see this broadcast. This prevents them from
10337 // using this as a back door to get run as soon as they are
10338 // installed. Maybe in the future we want to have a special install
10339 // broadcast or such for apps, but we'd like to deliberately make
10340 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010341 String skipPackages[] = null;
10342 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10343 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10344 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10345 Uri data = intent.getData();
10346 if (data != null) {
10347 String pkgName = data.getSchemeSpecificPart();
10348 if (pkgName != null) {
10349 skipPackages = new String[] { pkgName };
10350 }
10351 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010352 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010353 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010354 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010355 if (skipPackages != null && (skipPackages.length > 0)) {
10356 for (String skipPackage : skipPackages) {
10357 if (skipPackage != null) {
10358 int NT = receivers.size();
10359 for (int it=0; it<NT; it++) {
10360 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10361 if (curt.activityInfo.packageName.equals(skipPackage)) {
10362 receivers.remove(it);
10363 it--;
10364 NT--;
10365 }
10366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 }
10368 }
10369 }
10370
10371 int NT = receivers != null ? receivers.size() : 0;
10372 int it = 0;
10373 ResolveInfo curt = null;
10374 BroadcastFilter curr = null;
10375 while (it < NT && ir < NR) {
10376 if (curt == null) {
10377 curt = (ResolveInfo)receivers.get(it);
10378 }
10379 if (curr == null) {
10380 curr = registeredReceivers.get(ir);
10381 }
10382 if (curr.getPriority() >= curt.priority) {
10383 // Insert this broadcast record into the final list.
10384 receivers.add(it, curr);
10385 ir++;
10386 curr = null;
10387 it++;
10388 NT++;
10389 } else {
10390 // Skip to the next ResolveInfo in the final list.
10391 it++;
10392 curt = null;
10393 }
10394 }
10395 }
10396 while (ir < NR) {
10397 if (receivers == null) {
10398 receivers = new ArrayList();
10399 }
10400 receivers.add(registeredReceivers.get(ir));
10401 ir++;
10402 }
10403
10404 if ((receivers != null && receivers.size() > 0)
10405 || resultTo != null) {
10406 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10407 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010408 receivers, resultTo, resultCode, resultData, map, ordered,
10409 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010410 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010411 TAG, "Enqueueing ordered broadcast " + r
10412 + ": prev had " + mOrderedBroadcasts.size());
10413 if (DEBUG_BROADCAST) {
10414 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010417 boolean replaced = false;
10418 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010419 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010420 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010421 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010422 "***** DROPPING ORDERED: " + intent);
10423 mOrderedBroadcasts.set(i, r);
10424 replaced = true;
10425 break;
10426 }
10427 }
10428 }
10429 if (!replaced) {
10430 mOrderedBroadcasts.add(r);
10431 scheduleBroadcastsLocked();
10432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010433 }
10434
10435 return BROADCAST_SUCCESS;
10436 }
10437
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010438 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439 // Refuse possible leaked file descriptors
10440 if (intent != null && intent.hasFileDescriptors() == true) {
10441 throw new IllegalArgumentException("File descriptors passed in Intent");
10442 }
10443
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010444 int flags = intent.getFlags();
10445
10446 if (!mProcessesReady) {
10447 // if the caller really truly claims to know what they're doing, go
10448 // ahead and allow the broadcast without launching any receivers
10449 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10450 intent = new Intent(intent);
10451 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10452 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10453 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10454 + " before boot completion");
10455 throw new IllegalStateException("Cannot broadcast before boot completed");
10456 }
10457 }
10458
10459 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10460 throw new IllegalArgumentException(
10461 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10462 }
10463
10464 return intent;
10465 }
10466
10467 public final int broadcastIntent(IApplicationThread caller,
10468 Intent intent, String resolvedType, IIntentReceiver resultTo,
10469 int resultCode, String resultData, Bundle map,
10470 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010471 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010472 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10475 final int callingPid = Binder.getCallingPid();
10476 final int callingUid = Binder.getCallingUid();
10477 final long origId = Binder.clearCallingIdentity();
10478 int res = broadcastIntentLocked(callerApp,
10479 callerApp != null ? callerApp.info.packageName : null,
10480 intent, resolvedType, resultTo,
10481 resultCode, resultData, map, requiredPermission, serialized,
10482 sticky, callingPid, callingUid);
10483 Binder.restoreCallingIdentity(origId);
10484 return res;
10485 }
10486 }
10487
10488 int broadcastIntentInPackage(String packageName, int uid,
10489 Intent intent, String resolvedType, IIntentReceiver resultTo,
10490 int resultCode, String resultData, Bundle map,
10491 String requiredPermission, boolean serialized, boolean sticky) {
10492 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010493 intent = verifyBroadcastLocked(intent);
10494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 final long origId = Binder.clearCallingIdentity();
10496 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10497 resultTo, resultCode, resultData, map, requiredPermission,
10498 serialized, sticky, -1, uid);
10499 Binder.restoreCallingIdentity(origId);
10500 return res;
10501 }
10502 }
10503
10504 public final void unbroadcastIntent(IApplicationThread caller,
10505 Intent intent) {
10506 // Refuse possible leaked file descriptors
10507 if (intent != null && intent.hasFileDescriptors() == true) {
10508 throw new IllegalArgumentException("File descriptors passed in Intent");
10509 }
10510
10511 synchronized(this) {
10512 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10513 != PackageManager.PERMISSION_GRANTED) {
10514 String msg = "Permission Denial: unbroadcastIntent() from pid="
10515 + Binder.getCallingPid()
10516 + ", uid=" + Binder.getCallingUid()
10517 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010518 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010519 throw new SecurityException(msg);
10520 }
10521 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10522 if (list != null) {
10523 int N = list.size();
10524 int i;
10525 for (i=0; i<N; i++) {
10526 if (intent.filterEquals(list.get(i))) {
10527 list.remove(i);
10528 break;
10529 }
10530 }
10531 }
10532 }
10533 }
10534
10535 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10536 String resultData, Bundle resultExtras, boolean resultAbort,
10537 boolean explicit) {
10538 if (mOrderedBroadcasts.size() == 0) {
10539 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010540 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541 }
10542 return false;
10543 }
10544 BroadcastRecord r = mOrderedBroadcasts.get(0);
10545 if (r.receiver == null) {
10546 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 }
10549 return false;
10550 }
10551 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010552 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 return false;
10554 }
10555 int state = r.state;
10556 r.state = r.IDLE;
10557 if (state == r.IDLE) {
10558 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010559 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 }
10561 }
10562 r.receiver = null;
10563 r.intent.setComponent(null);
10564 if (r.curApp != null) {
10565 r.curApp.curReceiver = null;
10566 }
10567 if (r.curFilter != null) {
10568 r.curFilter.receiverList.curBroadcast = null;
10569 }
10570 r.curFilter = null;
10571 r.curApp = null;
10572 r.curComponent = null;
10573 r.curReceiver = null;
10574 mPendingBroadcast = null;
10575
10576 r.resultCode = resultCode;
10577 r.resultData = resultData;
10578 r.resultExtras = resultExtras;
10579 r.resultAbort = resultAbort;
10580
10581 // We will process the next receiver right now if this is finishing
10582 // an app receiver (which is always asynchronous) or after we have
10583 // come back from calling a receiver.
10584 return state == BroadcastRecord.APP_RECEIVE
10585 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10586 }
10587
10588 public void finishReceiver(IBinder who, int resultCode, String resultData,
10589 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010590 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010591
10592 // Refuse possible leaked file descriptors
10593 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10594 throw new IllegalArgumentException("File descriptors passed in Bundle");
10595 }
10596
10597 boolean doNext;
10598
10599 final long origId = Binder.clearCallingIdentity();
10600
10601 synchronized(this) {
10602 doNext = finishReceiverLocked(
10603 who, resultCode, resultData, resultExtras, resultAbort, true);
10604 }
10605
10606 if (doNext) {
10607 processNextBroadcast(false);
10608 }
10609 trimApplications();
10610
10611 Binder.restoreCallingIdentity(origId);
10612 }
10613
Jeff Brown4d94a762010-09-23 11:33:28 -070010614 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 if (r.nextReceiver > 0) {
10616 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10617 if (curReceiver instanceof BroadcastFilter) {
10618 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010619 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 System.identityHashCode(r),
10621 r.intent.getAction(),
10622 r.nextReceiver - 1,
10623 System.identityHashCode(bf));
10624 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010625 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 System.identityHashCode(r),
10627 r.intent.getAction(),
10628 r.nextReceiver - 1,
10629 ((ResolveInfo)curReceiver).toString());
10630 }
10631 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010632 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010633 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010634 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 System.identityHashCode(r),
10636 r.intent.getAction(),
10637 r.nextReceiver,
10638 "NONE");
10639 }
10640 }
10641
Jeff Brown4d94a762010-09-23 11:33:28 -070010642 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10643 if (! mPendingBroadcastTimeoutMessage) {
10644 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10645 mHandler.sendMessageAtTime(msg, timeoutTime);
10646 mPendingBroadcastTimeoutMessage = true;
10647 }
10648 }
10649
10650 private final void cancelBroadcastTimeoutLocked() {
10651 if (mPendingBroadcastTimeoutMessage) {
10652 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10653 mPendingBroadcastTimeoutMessage = false;
10654 }
10655 }
10656
10657 private final void broadcastTimeoutLocked(boolean fromMsg) {
10658 if (fromMsg) {
10659 mPendingBroadcastTimeoutMessage = false;
10660 }
10661
10662 if (mOrderedBroadcasts.size() == 0) {
10663 return;
10664 }
10665
10666 long now = SystemClock.uptimeMillis();
10667 BroadcastRecord r = mOrderedBroadcasts.get(0);
10668 if (fromMsg) {
10669 if (mDidDexOpt) {
10670 // Delay timeouts until dexopt finishes.
10671 mDidDexOpt = false;
10672 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10673 setBroadcastTimeoutLocked(timeoutTime);
10674 return;
10675 }
10676 if (! mProcessesReady) {
10677 // Only process broadcast timeouts if the system is ready. That way
10678 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10679 // to do heavy lifting for system up.
10680 return;
10681 }
10682
10683 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10684 if (timeoutTime > now) {
10685 // We can observe premature timeouts because we do not cancel and reset the
10686 // broadcast timeout message after each receiver finishes. Instead, we set up
10687 // an initial timeout then kick it down the road a little further as needed
10688 // when it expires.
10689 if (DEBUG_BROADCAST) Slog.v(TAG,
10690 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10691 + timeoutTime);
10692 setBroadcastTimeoutLocked(timeoutTime);
10693 return;
10694 }
10695 }
10696
10697 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10698 + ", started " + (now - r.receiverTime) + "ms ago");
10699 r.receiverTime = now;
10700 r.anrCount++;
10701
10702 // Current receiver has passed its expiration date.
10703 if (r.nextReceiver <= 0) {
10704 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10705 return;
10706 }
10707
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010708 ProcessRecord app = null;
10709 String anrMessage = null;
10710
Jeff Brown4d94a762010-09-23 11:33:28 -070010711 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10712 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10713 logBroadcastReceiverDiscardLocked(r);
10714 if (curReceiver instanceof BroadcastFilter) {
10715 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10716 if (bf.receiverList.pid != 0
10717 && bf.receiverList.pid != MY_PID) {
10718 synchronized (this.mPidsSelfLocked) {
10719 app = this.mPidsSelfLocked.get(
10720 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010723 } else {
10724 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010726
Jeff Brown4d94a762010-09-23 11:33:28 -070010727 if (app != null) {
10728 anrMessage = "Broadcast of " + r.intent.toString();
10729 }
10730
10731 if (mPendingBroadcast == r) {
10732 mPendingBroadcast = null;
10733 }
10734
10735 // Move on to the next receiver.
10736 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10737 r.resultExtras, r.resultAbort, true);
10738 scheduleBroadcastsLocked();
10739
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010740 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010741 // Post the ANR to the handler since we do not want to process ANRs while
10742 // potentially holding our lock.
10743 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010745 }
10746
10747 private final void processCurBroadcastLocked(BroadcastRecord r,
10748 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010749 if (DEBUG_BROADCAST) Slog.v(TAG,
10750 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751 if (app.thread == null) {
10752 throw new RemoteException();
10753 }
10754 r.receiver = app.thread.asBinder();
10755 r.curApp = app;
10756 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010757 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758
10759 // Tell the application to launch this receiver.
10760 r.intent.setComponent(r.curComponent);
10761
10762 boolean started = false;
10763 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010764 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 "Delivering to component " + r.curComponent
10766 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010767 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10769 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010770 if (DEBUG_BROADCAST) Slog.v(TAG,
10771 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 started = true;
10773 } finally {
10774 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010775 if (DEBUG_BROADCAST) Slog.v(TAG,
10776 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010777 r.receiver = null;
10778 r.curApp = null;
10779 app.curReceiver = null;
10780 }
10781 }
10782
10783 }
10784
Jeff Brown4d94a762010-09-23 11:33:28 -070010785 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010786 Intent intent, int resultCode, String data, Bundle extras,
10787 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010788 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 if (app != null && app.thread != null) {
10790 // If we have an app thread, do the call through that so it is
10791 // correctly ordered with other one-way calls.
10792 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010793 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010795 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010796 }
10797 }
10798
Jeff Brown4d94a762010-09-23 11:33:28 -070010799 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 BroadcastFilter filter, boolean ordered) {
10801 boolean skip = false;
10802 if (filter.requiredPermission != null) {
10803 int perm = checkComponentPermission(filter.requiredPermission,
10804 r.callingPid, r.callingUid, -1);
10805 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010806 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 + r.intent.toString()
10808 + " from " + r.callerPackage + " (pid="
10809 + r.callingPid + ", uid=" + r.callingUid + ")"
10810 + " requires " + filter.requiredPermission
10811 + " due to registered receiver " + filter);
10812 skip = true;
10813 }
10814 }
10815 if (r.requiredPermission != null) {
10816 int perm = checkComponentPermission(r.requiredPermission,
10817 filter.receiverList.pid, filter.receiverList.uid, -1);
10818 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010819 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010820 + r.intent.toString()
10821 + " to " + filter.receiverList.app
10822 + " (pid=" + filter.receiverList.pid
10823 + ", uid=" + filter.receiverList.uid + ")"
10824 + " requires " + r.requiredPermission
10825 + " due to sender " + r.callerPackage
10826 + " (uid " + r.callingUid + ")");
10827 skip = true;
10828 }
10829 }
10830
10831 if (!skip) {
10832 // If this is not being sent as an ordered broadcast, then we
10833 // don't want to touch the fields that keep track of the current
10834 // state of ordered broadcasts.
10835 if (ordered) {
10836 r.receiver = filter.receiverList.receiver.asBinder();
10837 r.curFilter = filter;
10838 filter.receiverList.curBroadcast = r;
10839 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010840 if (filter.receiverList.app != null) {
10841 // Bump hosting application to no longer be in background
10842 // scheduling class. Note that we can't do that if there
10843 // isn't an app... but we can only be in that case for
10844 // things that directly call the IActivityManager API, which
10845 // are already core system stuff so don't matter for this.
10846 r.curApp = filter.receiverList.app;
10847 filter.receiverList.app.curReceiver = r;
10848 updateOomAdjLocked();
10849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010850 }
10851 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010852 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010854 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010855 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010856 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010857 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010859 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 if (ordered) {
10861 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10862 }
10863 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010864 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 if (ordered) {
10866 r.receiver = null;
10867 r.curFilter = null;
10868 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010869 if (filter.receiverList.app != null) {
10870 filter.receiverList.app.curReceiver = null;
10871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010872 }
10873 }
10874 }
10875 }
10876
Dianne Hackborn12527f92009-11-11 17:39:50 -080010877 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10878 if (r.callingUid < 0) {
10879 // This was from a registerReceiver() call; ignore it.
10880 return;
10881 }
10882 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10883 MAX_BROADCAST_HISTORY-1);
10884 r.finishTime = SystemClock.uptimeMillis();
10885 mBroadcastHistory[0] = r;
10886 }
10887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888 private final void processNextBroadcast(boolean fromMsg) {
10889 synchronized(this) {
10890 BroadcastRecord r;
10891
Joe Onorato8a9b2202010-02-26 18:56:32 -080010892 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010894 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895
10896 updateCpuStats();
10897
10898 if (fromMsg) {
10899 mBroadcastsScheduled = false;
10900 }
10901
10902 // First, deliver any non-serialized broadcasts right away.
10903 while (mParallelBroadcasts.size() > 0) {
10904 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010905 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010907 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010908 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010909 for (int i=0; i<N; i++) {
10910 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010911 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010912 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010914 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010916 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010917 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010918 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 }
10920
10921 // Now take care of the next serialized one...
10922
10923 // If we are waiting for a process to come up to handle the next
10924 // broadcast, then do nothing at this point. Just in case, we
10925 // check that the process we're waiting for still exists.
10926 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010927 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010928 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010929 + mPendingBroadcast.curApp);
10930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931
10932 boolean isDead;
10933 synchronized (mPidsSelfLocked) {
10934 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10935 }
10936 if (!isDead) {
10937 // It's still alive, so keep waiting
10938 return;
10939 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010940 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010942 mPendingBroadcast.state = BroadcastRecord.IDLE;
10943 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 mPendingBroadcast = null;
10945 }
10946 }
10947
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010948 boolean looped = false;
10949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 do {
10951 if (mOrderedBroadcasts.size() == 0) {
10952 // No more broadcasts pending, so all done!
10953 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010954 if (looped) {
10955 // If we had finished the last ordered broadcast, then
10956 // make sure all processes have correct oom and sched
10957 // adjustments.
10958 updateOomAdjLocked();
10959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 return;
10961 }
10962 r = mOrderedBroadcasts.get(0);
10963 boolean forceReceive = false;
10964
10965 // Ensure that even if something goes awry with the timeout
10966 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010967 // and continue to make progress.
10968 //
10969 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070010970 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010971 // one time heavy lifting after system upgrades and can take
10972 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010974 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010975 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 if ((numReceivers > 0) &&
10977 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010978 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 + " now=" + now
10980 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010981 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982 + " intent=" + r.intent
10983 + " numReceivers=" + numReceivers
10984 + " nextReceiver=" + r.nextReceiver
10985 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070010986 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 forceReceive = true;
10988 r.state = BroadcastRecord.IDLE;
10989 }
10990 }
10991
10992 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010993 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994 "processNextBroadcast() called when not idle (state="
10995 + r.state + ")");
10996 return;
10997 }
10998
10999 if (r.receivers == null || r.nextReceiver >= numReceivers
11000 || r.resultAbort || forceReceive) {
11001 // No more receivers for this broadcast! Send the final
11002 // result if requested...
11003 if (r.resultTo != null) {
11004 try {
11005 if (DEBUG_BROADCAST) {
11006 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 + " seq=" + seq + " app=" + r.callerApp);
11009 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011010 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011012 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011013 // Set this to null so that the reference
11014 // (local and remote) isnt kept in the mBroadcastHistory.
11015 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011017 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 }
11019 }
11020
Joe Onorato8a9b2202010-02-26 18:56:32 -080011021 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011022 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023
Joe Onorato8a9b2202010-02-26 18:56:32 -080011024 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011025 + r);
11026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011028 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 mOrderedBroadcasts.remove(0);
11030 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011031 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011032 continue;
11033 }
11034 } while (r == null);
11035
11036 // Get the next receiver...
11037 int recIdx = r.nextReceiver++;
11038
11039 // Keep track of when this receiver started, and make sure there
11040 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011041 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011043 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044
Joe Onorato8a9b2202010-02-26 18:56:32 -080011045 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011046 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011047 }
11048 if (! mPendingBroadcastTimeoutMessage) {
11049 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011050 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011051 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11052 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 }
11054
11055 Object nextReceiver = r.receivers.get(recIdx);
11056 if (nextReceiver instanceof BroadcastFilter) {
11057 // Simple case: this is a registered receiver who gets
11058 // a direct call.
11059 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011061 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011063 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 if (r.receiver == null || !r.ordered) {
11065 // The receiver has already finished, so schedule to
11066 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011067 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11068 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 r.state = BroadcastRecord.IDLE;
11070 scheduleBroadcastsLocked();
11071 }
11072 return;
11073 }
11074
11075 // Hard case: need to instantiate the receiver, possibly
11076 // starting its application process to host it.
11077
11078 ResolveInfo info =
11079 (ResolveInfo)nextReceiver;
11080
11081 boolean skip = false;
11082 int perm = checkComponentPermission(info.activityInfo.permission,
11083 r.callingPid, r.callingUid,
11084 info.activityInfo.exported
11085 ? -1 : info.activityInfo.applicationInfo.uid);
11086 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011087 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 + r.intent.toString()
11089 + " from " + r.callerPackage + " (pid=" + r.callingPid
11090 + ", uid=" + r.callingUid + ")"
11091 + " requires " + info.activityInfo.permission
11092 + " due to receiver " + info.activityInfo.packageName
11093 + "/" + info.activityInfo.name);
11094 skip = true;
11095 }
11096 if (r.callingUid != Process.SYSTEM_UID &&
11097 r.requiredPermission != null) {
11098 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011099 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 checkPermission(r.requiredPermission,
11101 info.activityInfo.applicationInfo.packageName);
11102 } catch (RemoteException e) {
11103 perm = PackageManager.PERMISSION_DENIED;
11104 }
11105 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011106 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 + r.intent + " to "
11108 + info.activityInfo.applicationInfo.packageName
11109 + " requires " + r.requiredPermission
11110 + " due to sender " + r.callerPackage
11111 + " (uid " + r.callingUid + ")");
11112 skip = true;
11113 }
11114 }
11115 if (r.curApp != null && r.curApp.crashing) {
11116 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011117 if (DEBUG_BROADCAST) Slog.v(TAG,
11118 "Skipping deliver ordered " + r + " to " + r.curApp
11119 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 skip = true;
11121 }
11122
11123 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011124 if (DEBUG_BROADCAST) Slog.v(TAG,
11125 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011126 r.receiver = null;
11127 r.curFilter = null;
11128 r.state = BroadcastRecord.IDLE;
11129 scheduleBroadcastsLocked();
11130 return;
11131 }
11132
11133 r.state = BroadcastRecord.APP_RECEIVE;
11134 String targetProcess = info.activityInfo.processName;
11135 r.curComponent = new ComponentName(
11136 info.activityInfo.applicationInfo.packageName,
11137 info.activityInfo.name);
11138 r.curReceiver = info.activityInfo;
11139
11140 // Is this receiver's application already running?
11141 ProcessRecord app = getProcessRecordLocked(targetProcess,
11142 info.activityInfo.applicationInfo.uid);
11143 if (app != null && app.thread != null) {
11144 try {
11145 processCurBroadcastLocked(r, app);
11146 return;
11147 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011148 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 + r.curComponent, e);
11150 }
11151
11152 // If a dead object exception was thrown -- fall through to
11153 // restart the application.
11154 }
11155
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011156 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011157 if (DEBUG_BROADCAST) Slog.v(TAG,
11158 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 if ((r.curApp=startProcessLocked(targetProcess,
11160 info.activityInfo.applicationInfo, true,
11161 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011162 "broadcast", r.curComponent,
11163 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11164 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 // Ah, this recipient is unavailable. Finish it if necessary,
11166 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011167 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 + info.activityInfo.applicationInfo.packageName + "/"
11169 + info.activityInfo.applicationInfo.uid + " for broadcast "
11170 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011171 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11173 r.resultExtras, r.resultAbort, true);
11174 scheduleBroadcastsLocked();
11175 r.state = BroadcastRecord.IDLE;
11176 return;
11177 }
11178
11179 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011180 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 }
11182 }
11183
11184 // =========================================================
11185 // INSTRUMENTATION
11186 // =========================================================
11187
11188 public boolean startInstrumentation(ComponentName className,
11189 String profileFile, int flags, Bundle arguments,
11190 IInstrumentationWatcher watcher) {
11191 // Refuse possible leaked file descriptors
11192 if (arguments != null && arguments.hasFileDescriptors()) {
11193 throw new IllegalArgumentException("File descriptors passed in Bundle");
11194 }
11195
11196 synchronized(this) {
11197 InstrumentationInfo ii = null;
11198 ApplicationInfo ai = null;
11199 try {
11200 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011201 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011203 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 } catch (PackageManager.NameNotFoundException e) {
11205 }
11206 if (ii == null) {
11207 reportStartInstrumentationFailure(watcher, className,
11208 "Unable to find instrumentation info for: " + className);
11209 return false;
11210 }
11211 if (ai == null) {
11212 reportStartInstrumentationFailure(watcher, className,
11213 "Unable to find instrumentation target package: " + ii.targetPackage);
11214 return false;
11215 }
11216
11217 int match = mContext.getPackageManager().checkSignatures(
11218 ii.targetPackage, ii.packageName);
11219 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11220 String msg = "Permission Denial: starting instrumentation "
11221 + className + " from pid="
11222 + Binder.getCallingPid()
11223 + ", uid=" + Binder.getCallingPid()
11224 + " not allowed because package " + ii.packageName
11225 + " does not have a signature matching the target "
11226 + ii.targetPackage;
11227 reportStartInstrumentationFailure(watcher, className, msg);
11228 throw new SecurityException(msg);
11229 }
11230
11231 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011232 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 ProcessRecord app = addAppLocked(ai);
11234 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011235 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 app.instrumentationProfileFile = profileFile;
11237 app.instrumentationArguments = arguments;
11238 app.instrumentationWatcher = watcher;
11239 app.instrumentationResultClass = className;
11240 Binder.restoreCallingIdentity(origId);
11241 }
11242
11243 return true;
11244 }
11245
11246 /**
11247 * Report errors that occur while attempting to start Instrumentation. Always writes the
11248 * error to the logs, but if somebody is watching, send the report there too. This enables
11249 * the "am" command to report errors with more information.
11250 *
11251 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11252 * @param cn The component name of the instrumentation.
11253 * @param report The error report.
11254 */
11255 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11256 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011257 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 try {
11259 if (watcher != null) {
11260 Bundle results = new Bundle();
11261 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11262 results.putString("Error", report);
11263 watcher.instrumentationStatus(cn, -1, results);
11264 }
11265 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011266 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 }
11268 }
11269
11270 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11271 if (app.instrumentationWatcher != null) {
11272 try {
11273 // NOTE: IInstrumentationWatcher *must* be oneway here
11274 app.instrumentationWatcher.instrumentationFinished(
11275 app.instrumentationClass,
11276 resultCode,
11277 results);
11278 } catch (RemoteException e) {
11279 }
11280 }
11281 app.instrumentationWatcher = null;
11282 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011283 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 app.instrumentationProfileFile = null;
11285 app.instrumentationArguments = null;
11286
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011287 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 }
11289
11290 public void finishInstrumentation(IApplicationThread target,
11291 int resultCode, Bundle results) {
11292 // Refuse possible leaked file descriptors
11293 if (results != null && results.hasFileDescriptors()) {
11294 throw new IllegalArgumentException("File descriptors passed in Intent");
11295 }
11296
11297 synchronized(this) {
11298 ProcessRecord app = getRecordForAppLocked(target);
11299 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 return;
11302 }
11303 final long origId = Binder.clearCallingIdentity();
11304 finishInstrumentationLocked(app, resultCode, results);
11305 Binder.restoreCallingIdentity(origId);
11306 }
11307 }
11308
11309 // =========================================================
11310 // CONFIGURATION
11311 // =========================================================
11312
11313 public ConfigurationInfo getDeviceConfigurationInfo() {
11314 ConfigurationInfo config = new ConfigurationInfo();
11315 synchronized (this) {
11316 config.reqTouchScreen = mConfiguration.touchscreen;
11317 config.reqKeyboardType = mConfiguration.keyboard;
11318 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011319 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11320 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11322 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011323 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11324 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11326 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011327 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 }
11329 return config;
11330 }
11331
11332 public Configuration getConfiguration() {
11333 Configuration ci;
11334 synchronized(this) {
11335 ci = new Configuration(mConfiguration);
11336 }
11337 return ci;
11338 }
11339
11340 public void updateConfiguration(Configuration values) {
11341 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11342 "updateConfiguration()");
11343
11344 synchronized(this) {
11345 if (values == null && mWindowManager != null) {
11346 // sentinel: fetch the current configuration from the window manager
11347 values = mWindowManager.computeNewConfiguration();
11348 }
11349
11350 final long origId = Binder.clearCallingIdentity();
11351 updateConfigurationLocked(values, null);
11352 Binder.restoreCallingIdentity(origId);
11353 }
11354 }
11355
11356 /**
11357 * Do either or both things: (1) change the current configuration, and (2)
11358 * make sure the given activity is running with the (now) current
11359 * configuration. Returns true if the activity has been left running, or
11360 * false if <var>starting</var> is being destroyed to match the new
11361 * configuration.
11362 */
11363 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011364 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011365 int changes = 0;
11366
11367 boolean kept = true;
11368
11369 if (values != null) {
11370 Configuration newConfig = new Configuration(mConfiguration);
11371 changes = newConfig.updateFrom(values);
11372 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011373 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011374 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 }
11376
Doug Zongker2bec3d42009-12-04 12:52:44 -080011377 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378
11379 if (values.locale != null) {
11380 saveLocaleLocked(values.locale,
11381 !values.locale.equals(mConfiguration.locale),
11382 values.userSetLocale);
11383 }
11384
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011385 mConfigurationSeq++;
11386 if (mConfigurationSeq <= 0) {
11387 mConfigurationSeq = 1;
11388 }
11389 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011391 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011392
11393 AttributeCache ac = AttributeCache.instance();
11394 if (ac != null) {
11395 ac.updateConfiguration(mConfiguration);
11396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011398 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11399 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11400 msg.obj = new Configuration(mConfiguration);
11401 mHandler.sendMessage(msg);
11402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011404 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11405 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011406 try {
11407 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011408 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011409 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 app.thread.scheduleConfigurationChanged(mConfiguration);
11411 }
11412 } catch (Exception e) {
11413 }
11414 }
11415 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011416 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11417 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11419 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011420 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11421 broadcastIntentLocked(null, null,
11422 new Intent(Intent.ACTION_LOCALE_CHANGED),
11423 null, null, 0, null, null,
11424 null, false, false, MY_PID, Process.SYSTEM_UID);
11425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 }
11427 }
11428
11429 if (changes != 0 && starting == null) {
11430 // If the configuration changed, and the caller is not already
11431 // in the process of starting an activity, then find the top
11432 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011433 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 }
11435
11436 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011437 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 if (kept) {
11439 // If this didn't result in the starting activity being
11440 // destroyed, then we need to make sure at this point that all
11441 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011442 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011444 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 }
11446 }
11447
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011448 if (values != null && mWindowManager != null) {
11449 mWindowManager.setNewConfiguration(mConfiguration);
11450 }
11451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 return kept;
11453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011454
11455 /**
11456 * Save the locale. You must be inside a synchronized (this) block.
11457 */
11458 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11459 if(isDiff) {
11460 SystemProperties.set("user.language", l.getLanguage());
11461 SystemProperties.set("user.region", l.getCountry());
11462 }
11463
11464 if(isPersist) {
11465 SystemProperties.set("persist.sys.language", l.getLanguage());
11466 SystemProperties.set("persist.sys.country", l.getCountry());
11467 SystemProperties.set("persist.sys.localevar", l.getVariant());
11468 }
11469 }
11470
11471 // =========================================================
11472 // LIFETIME MANAGEMENT
11473 // =========================================================
11474
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011475 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11476 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011478 // This adjustment has already been computed. If we are calling
11479 // from the top, we may have already computed our adjustment with
11480 // an earlier hidden adjustment that isn't really for us... if
11481 // so, use the new hidden adjustment.
11482 if (!recursed && app.hidden) {
11483 app.curAdj = hiddenAdj;
11484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 return app.curAdj;
11486 }
11487
11488 if (app.thread == null) {
11489 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011490 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011491 return (app.curAdj=EMPTY_APP_ADJ);
11492 }
11493
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011494 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11495 // The max adjustment doesn't allow this app to be anything
11496 // below foreground, so it is not worth doing work for it.
11497 app.adjType = "fixed";
11498 app.adjSeq = mAdjSeq;
11499 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011500 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011501 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11502 return (app.curAdj=app.maxAdj);
11503 }
11504
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011505 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011506 app.adjSource = null;
11507 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011508 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011509 app.empty = false;
11510 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511
The Android Open Source Project4df24232009-03-05 14:34:35 -080011512 // Determine the importance of the process, starting with most
11513 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011515 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011517 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 // The last app on the list is the foreground app.
11519 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011520 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011521 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011522 } else if (app.instrumentationClass != null) {
11523 // Don't want to kill running instrumentation.
11524 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011525 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011526 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011527 } else if (app.curReceiver != null ||
11528 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11529 // An app that is currently receiving a broadcast also
11530 // counts as being in the foreground.
11531 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011532 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011533 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 } else if (app.executingServices.size() > 0) {
11535 // An app that is currently executing a service callback also
11536 // counts as being in the foreground.
11537 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011538 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011539 app.adjType = "exec-service";
11540 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011542 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011543 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011544 app.adjType = "foreground-service";
11545 } else if (app.forcingToForeground != null) {
11546 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011547 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011548 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011549 app.adjType = "force-foreground";
11550 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011551 } else if (app == mHeavyWeightProcess) {
11552 // We don't want to kill the current heavy-weight process.
11553 adj = HEAVY_WEIGHT_APP_ADJ;
11554 schedGroup = Process.THREAD_GROUP_DEFAULT;
11555 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011556 } else if (app == mHomeProcess) {
11557 // This process is hosting what we currently consider to be the
11558 // home app, so we don't want to let it go into the background.
11559 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011560 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011561 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562 } else if ((N=app.activities.size()) != 0) {
11563 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011564 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011565 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011566 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011567 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011568 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011570 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011572 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011574 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011575 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 break;
11577 }
11578 }
11579 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011580 // A very not-needed process. If this is lower in the lru list,
11581 // we will push it in to the empty bucket.
11582 app.hidden = true;
11583 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011584 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011585 adj = hiddenAdj;
11586 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011587 }
11588
Joe Onorato8a9b2202010-02-26 18:56:32 -080011589 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011590
The Android Open Source Project4df24232009-03-05 14:34:35 -080011591 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011592 // there are applications dependent on our services or providers, but
11593 // this gives us a baseline and makes sure we don't get into an
11594 // infinite recursion.
11595 app.adjSeq = mAdjSeq;
11596 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011597
Christopher Tate6fa95972009-06-05 18:43:55 -070011598 if (mBackupTarget != null && app == mBackupTarget.app) {
11599 // If possible we want to avoid killing apps while they're being backed up
11600 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011601 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011602 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011603 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011604 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011605 }
11606 }
11607
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011608 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11609 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 final long now = SystemClock.uptimeMillis();
11611 // This process is more important if the top activity is
11612 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011613 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011615 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 if (s.startRequested) {
11617 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11618 // This service has seen some activity within
11619 // recent memory, so we will keep its process ahead
11620 // of the background processes.
11621 if (adj > SECONDARY_SERVER_ADJ) {
11622 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011623 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011624 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 }
11626 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011627 // If we have let the service slide into the background
11628 // state, still have some text describing what it is doing
11629 // even though the service no longer has an impact.
11630 if (adj > SECONDARY_SERVER_ADJ) {
11631 app.adjType = "started-bg-services";
11632 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011633 // Don't kill this process because it is doing work; it
11634 // has said it is doing work.
11635 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011637 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11638 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011639 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011640 = s.connections.values().iterator();
11641 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011642 ArrayList<ConnectionRecord> clist = kt.next();
11643 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11644 // XXX should compute this based on the max of
11645 // all connected clients.
11646 ConnectionRecord cr = clist.get(i);
11647 if (cr.binding.client == app) {
11648 // Binding to ourself is not interesting.
11649 continue;
11650 }
11651 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11652 ProcessRecord client = cr.binding.client;
11653 int myHiddenAdj = hiddenAdj;
11654 if (myHiddenAdj > client.hiddenAdj) {
11655 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11656 myHiddenAdj = client.hiddenAdj;
11657 } else {
11658 myHiddenAdj = VISIBLE_APP_ADJ;
11659 }
11660 }
11661 int clientAdj = computeOomAdjLocked(
11662 client, myHiddenAdj, TOP_APP, true);
11663 if (adj > clientAdj) {
11664 adj = clientAdj >= VISIBLE_APP_ADJ
11665 ? clientAdj : VISIBLE_APP_ADJ;
11666 if (!client.hidden) {
11667 app.hidden = false;
11668 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011669 if (client.keeping) {
11670 app.keeping = true;
11671 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011672 app.adjType = "service";
11673 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11674 .REASON_SERVICE_IN_USE;
11675 app.adjSource = cr.binding.client;
11676 app.adjTarget = s.name;
11677 }
11678 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11679 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11680 schedGroup = Process.THREAD_GROUP_DEFAULT;
11681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 }
11683 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011684 ActivityRecord a = cr.activity;
11685 //if (a != null) {
11686 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11687 //}
11688 if (a != null && adj > FOREGROUND_APP_ADJ &&
11689 (a.state == ActivityState.RESUMED
11690 || a.state == ActivityState.PAUSING)) {
11691 adj = FOREGROUND_APP_ADJ;
11692 schedGroup = Process.THREAD_GROUP_DEFAULT;
11693 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011694 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011695 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11696 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011697 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011698 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 }
11701 }
11702 }
11703 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011704
Dianne Hackborn287952c2010-09-22 22:34:31 -070011705 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011706 // would like to avoid killing it unless it would prevent the current
11707 // application from running. By default we put the process in
11708 // with the rest of the background processes; as we scan through
11709 // its services we may bump it up from there.
11710 if (adj > hiddenAdj) {
11711 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011712 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011713 app.adjType = "bg-services";
11714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 }
11716
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011717 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11718 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011719 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011720 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11721 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011722 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011723 if (cpr.clients.size() != 0) {
11724 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11725 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11726 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011727 if (client == app) {
11728 // Being our own client is not interesting.
11729 continue;
11730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 int myHiddenAdj = hiddenAdj;
11732 if (myHiddenAdj > client.hiddenAdj) {
11733 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11734 myHiddenAdj = client.hiddenAdj;
11735 } else {
11736 myHiddenAdj = FOREGROUND_APP_ADJ;
11737 }
11738 }
11739 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011740 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 if (adj > clientAdj) {
11742 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011743 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011744 if (!client.hidden) {
11745 app.hidden = false;
11746 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011747 if (client.keeping) {
11748 app.keeping = true;
11749 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011750 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011751 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11752 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011753 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011754 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011756 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11757 schedGroup = Process.THREAD_GROUP_DEFAULT;
11758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 }
11760 }
11761 // If the provider has external (non-framework) process
11762 // dependencies, ensure that its adjustment is at least
11763 // FOREGROUND_APP_ADJ.
11764 if (cpr.externals != 0) {
11765 if (adj > FOREGROUND_APP_ADJ) {
11766 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011767 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011768 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011769 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011770 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011771 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011772 }
11773 }
11774 }
11775 }
11776
11777 app.curRawAdj = adj;
11778
Joe Onorato8a9b2202010-02-26 18:56:32 -080011779 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11781 if (adj > app.maxAdj) {
11782 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011783 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011784 schedGroup = Process.THREAD_GROUP_DEFAULT;
11785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011787 if (adj < HIDDEN_APP_MIN_ADJ) {
11788 app.keeping = true;
11789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790
11791 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011792 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 return adj;
11795 }
11796
11797 /**
11798 * Ask a given process to GC right now.
11799 */
11800 final void performAppGcLocked(ProcessRecord app) {
11801 try {
11802 app.lastRequestedGc = SystemClock.uptimeMillis();
11803 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011804 if (app.reportLowMemory) {
11805 app.reportLowMemory = false;
11806 app.thread.scheduleLowMemory();
11807 } else {
11808 app.thread.processInBackground();
11809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 }
11811 } catch (Exception e) {
11812 // whatever.
11813 }
11814 }
11815
11816 /**
11817 * Returns true if things are idle enough to perform GCs.
11818 */
Josh Bartel7f208742010-02-25 11:01:44 -060011819 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011820 return mParallelBroadcasts.size() == 0
11821 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011822 && (mSleeping || (mMainStack.mResumedActivity != null &&
11823 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 }
11825
11826 /**
11827 * Perform GCs on all processes that are waiting for it, but only
11828 * if things are idle.
11829 */
11830 final void performAppGcsLocked() {
11831 final int N = mProcessesToGc.size();
11832 if (N <= 0) {
11833 return;
11834 }
Josh Bartel7f208742010-02-25 11:01:44 -060011835 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 while (mProcessesToGc.size() > 0) {
11837 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011838 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011839 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11840 <= SystemClock.uptimeMillis()) {
11841 // To avoid spamming the system, we will GC processes one
11842 // at a time, waiting a few seconds between each.
11843 performAppGcLocked(proc);
11844 scheduleAppGcsLocked();
11845 return;
11846 } else {
11847 // It hasn't been long enough since we last GCed this
11848 // process... put it in the list to wait for its time.
11849 addProcessToGcListLocked(proc);
11850 break;
11851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 }
11853 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011854
11855 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 }
11857 }
11858
11859 /**
11860 * If all looks good, perform GCs on all processes waiting for them.
11861 */
11862 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011863 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011864 performAppGcsLocked();
11865 return;
11866 }
11867 // Still not idle, wait some more.
11868 scheduleAppGcsLocked();
11869 }
11870
11871 /**
11872 * Schedule the execution of all pending app GCs.
11873 */
11874 final void scheduleAppGcsLocked() {
11875 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011876
11877 if (mProcessesToGc.size() > 0) {
11878 // Schedule a GC for the time to the next process.
11879 ProcessRecord proc = mProcessesToGc.get(0);
11880 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11881
11882 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11883 long now = SystemClock.uptimeMillis();
11884 if (when < (now+GC_TIMEOUT)) {
11885 when = now + GC_TIMEOUT;
11886 }
11887 mHandler.sendMessageAtTime(msg, when);
11888 }
11889 }
11890
11891 /**
11892 * Add a process to the array of processes waiting to be GCed. Keeps the
11893 * list in sorted order by the last GC time. The process can't already be
11894 * on the list.
11895 */
11896 final void addProcessToGcListLocked(ProcessRecord proc) {
11897 boolean added = false;
11898 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11899 if (mProcessesToGc.get(i).lastRequestedGc <
11900 proc.lastRequestedGc) {
11901 added = true;
11902 mProcessesToGc.add(i+1, proc);
11903 break;
11904 }
11905 }
11906 if (!added) {
11907 mProcessesToGc.add(0, proc);
11908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 }
11910
11911 /**
11912 * Set up to ask a process to GC itself. This will either do it
11913 * immediately, or put it on the list of processes to gc the next
11914 * time things are idle.
11915 */
11916 final void scheduleAppGcLocked(ProcessRecord app) {
11917 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011918 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 return;
11920 }
11921 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011922 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 scheduleAppGcsLocked();
11924 }
11925 }
11926
Dianne Hackborn287952c2010-09-22 22:34:31 -070011927 final void checkExcessivePowerUsageLocked(boolean doKills) {
11928 updateCpuStatsNow();
11929
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011930 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011931 boolean doWakeKills = doKills;
11932 boolean doCpuKills = doKills;
11933 if (mLastPowerCheckRealtime == 0) {
11934 doWakeKills = false;
11935 }
11936 if (mLastPowerCheckUptime == 0) {
11937 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011938 }
11939 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011940 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011941 }
11942 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011943 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11944 final long curUptime = SystemClock.uptimeMillis();
11945 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11946 mLastPowerCheckRealtime = curRealtime;
11947 mLastPowerCheckUptime = curUptime;
11948 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11949 doWakeKills = false;
11950 }
11951 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11952 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011953 }
11954 int i = mLruProcesses.size();
11955 while (i > 0) {
11956 i--;
11957 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011958 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011959 long wtime;
11960 synchronized (stats) {
11961 wtime = stats.getProcessWakeTime(app.info.uid,
11962 app.pid, curRealtime);
11963 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011964 long wtimeUsed = wtime - app.lastWakeTime;
11965 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11966 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011967 StringBuilder sb = new StringBuilder(128);
11968 sb.append("Wake for ");
11969 app.toShortString(sb);
11970 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011971 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011972 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011973 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011974 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011975 sb.append((wtimeUsed*100)/realtimeSince);
11976 sb.append("%)");
11977 Slog.i(TAG, sb.toString());
11978 sb.setLength(0);
11979 sb.append("CPU for ");
11980 app.toShortString(sb);
11981 sb.append(": over ");
11982 TimeUtils.formatDuration(uptimeSince, sb);
11983 sb.append(" used ");
11984 TimeUtils.formatDuration(cputimeUsed, sb);
11985 sb.append(" (");
11986 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011987 sb.append("%)");
11988 Slog.i(TAG, sb.toString());
11989 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011990 // If a process has held a wake lock for more
11991 // than 50% of the time during this period,
11992 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070011993 if (doWakeKills && realtimeSince > 0
11994 && ((wtimeUsed*100)/realtimeSince) >= 50) {
11995 synchronized (stats) {
11996 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
11997 realtimeSince, wtimeUsed);
11998 }
11999 Slog.w(TAG, "Excessive wake lock in " + app.processName
12000 + " (pid " + app.pid + "): held " + wtimeUsed
12001 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012002 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12003 app.processName, app.setAdj, "excessive wake lock");
12004 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012005 } else if (doCpuKills && uptimeSince > 0
12006 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12007 synchronized (stats) {
12008 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12009 uptimeSince, cputimeUsed);
12010 }
12011 Slog.w(TAG, "Excessive CPU in " + app.processName
12012 + " (pid " + app.pid + "): used " + cputimeUsed
12013 + " during " + uptimeSince);
12014 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12015 app.processName, app.setAdj, "excessive cpu");
12016 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012017 } else {
12018 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012019 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012020 }
12021 }
12022 }
12023 }
12024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 private final boolean updateOomAdjLocked(
12026 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12027 app.hiddenAdj = hiddenAdj;
12028
12029 if (app.thread == null) {
12030 return true;
12031 }
12032
Dianne Hackborn287952c2010-09-22 22:34:31 -070012033 final boolean wasKeeping = app.keeping;
12034
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012035 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012036
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012037 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012038 if (app.curRawAdj != app.setRawAdj) {
12039 if (app.curRawAdj > FOREGROUND_APP_ADJ
12040 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12041 // If this app is transitioning from foreground to
12042 // non-foreground, have it do a gc.
12043 scheduleAppGcLocked(app);
12044 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12045 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12046 // Likewise do a gc when an app is moving in to the
12047 // background (such as a service stopping).
12048 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012049 }
12050
12051 if (wasKeeping && !app.keeping) {
12052 // This app is no longer something we want to keep. Note
12053 // its current wake lock time to later know to kill it if
12054 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012055 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12056 synchronized (stats) {
12057 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12058 app.pid, SystemClock.elapsedRealtime());
12059 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012060 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012061 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 app.setRawAdj = app.curRawAdj;
12064 }
12065 if (adj != app.setAdj) {
12066 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012067 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068 TAG, "Set app " + app.processName +
12069 " oom adj to " + adj);
12070 app.setAdj = adj;
12071 } else {
12072 return false;
12073 }
12074 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012075 if (app.setSchedGroup != app.curSchedGroup) {
12076 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012077 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012078 "Setting process group of " + app.processName
12079 + " to " + app.curSchedGroup);
12080 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012081 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012082 try {
12083 Process.setProcessGroup(app.pid, app.curSchedGroup);
12084 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012085 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012086 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012087 e.printStackTrace();
12088 } finally {
12089 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012090 }
12091 }
12092 if (false) {
12093 if (app.thread != null) {
12094 try {
12095 app.thread.setSchedulingGroup(app.curSchedGroup);
12096 } catch (RemoteException e) {
12097 }
12098 }
12099 }
12100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012101 }
12102
12103 return true;
12104 }
12105
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012106 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012107 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012109 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012110 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012111 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012112 }
12113 }
12114 return resumedActivity;
12115 }
12116
12117 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012118 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012119 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12120 int curAdj = app.curAdj;
12121 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12122 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12123
12124 mAdjSeq++;
12125
12126 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12127 if (res) {
12128 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12129 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12130 if (nowHidden != wasHidden) {
12131 // Changed to/from hidden state, so apps after it in the LRU
12132 // list may also be changed.
12133 updateOomAdjLocked();
12134 }
12135 }
12136 return res;
12137 }
12138
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012139 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012140 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012141 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12143
12144 if (false) {
12145 RuntimeException e = new RuntimeException();
12146 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012147 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012148 }
12149
12150 mAdjSeq++;
12151
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012152 // Let's determine how many processes we have running vs.
12153 // how many slots we have for background processes; we may want
12154 // to put multiple processes in a slot of there are enough of
12155 // them.
12156 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12157 int factor = (mLruProcesses.size()-4)/numSlots;
12158 if (factor < 1) factor = 1;
12159 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012160 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012162 // First try updating the OOM adjustment for each of the
12163 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012164 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012165 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12166 while (i > 0) {
12167 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012168 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012169 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012171 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012172 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012173 step++;
12174 if (step >= factor) {
12175 step = 0;
12176 curHiddenAdj++;
12177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012179 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012180 if (!app.killedBackground) {
12181 numHidden++;
12182 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012183 Slog.i(TAG, "No longer want " + app.processName
12184 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012185 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12186 app.processName, app.setAdj, "too many background");
12187 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012188 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012189 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012190 }
12191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012192 } else {
12193 didOomAdj = false;
12194 }
12195 }
12196
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012197 // If we return false, we will fall back on killing processes to
12198 // have a fixed limit. Do this if a limit has been requested; else
12199 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012200 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12201 }
12202
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012203 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012204 synchronized (this) {
12205 int i;
12206
12207 // First remove any unused application processes whose package
12208 // has been removed.
12209 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12210 final ProcessRecord app = mRemovedProcesses.get(i);
12211 if (app.activities.size() == 0
12212 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012213 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012214 TAG, "Exiting empty application process "
12215 + app.processName + " ("
12216 + (app.thread != null ? app.thread.asBinder() : null)
12217 + ")\n");
12218 if (app.pid > 0 && app.pid != MY_PID) {
12219 Process.killProcess(app.pid);
12220 } else {
12221 try {
12222 app.thread.scheduleExit();
12223 } catch (Exception e) {
12224 // Ignore exceptions.
12225 }
12226 }
12227 cleanUpApplicationRecordLocked(app, false, -1);
12228 mRemovedProcesses.remove(i);
12229
12230 if (app.persistent) {
12231 if (app.persistent) {
12232 addAppLocked(app.info);
12233 }
12234 }
12235 }
12236 }
12237
12238 // Now try updating the OOM adjustment for each of the
12239 // application processes based on their current state.
12240 // If the setOomAdj() API is not supported, then go with our
12241 // back-up plan...
12242 if (!updateOomAdjLocked()) {
12243
12244 // Count how many processes are running services.
12245 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012246 for (i=mLruProcesses.size()-1; i>=0; i--) {
12247 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012248
12249 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012250 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012251 // Don't count processes holding services against our
12252 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012253 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 TAG, "Not trimming app " + app + " with services: "
12255 + app.services);
12256 numServiceProcs++;
12257 }
12258 }
12259
12260 int curMaxProcs = mProcessLimit;
12261 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12262 if (mAlwaysFinishActivities) {
12263 curMaxProcs = 1;
12264 }
12265 curMaxProcs += numServiceProcs;
12266
12267 // Quit as many processes as we can to get down to the desired
12268 // process count. First remove any processes that no longer
12269 // have activites running in them.
12270 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012271 i<mLruProcesses.size()
12272 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012273 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012274 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012275 // Quit an application only if it is not currently
12276 // running any activities.
12277 if (!app.persistent && 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 // todo: For now we assume the application is not buggy
12294 // or evil, and will quit as a result of our request.
12295 // Eventually we need to drive this off of the death
12296 // notification, and kill the process if it takes too long.
12297 cleanUpApplicationRecordLocked(app, false, i);
12298 i--;
12299 }
12300 }
12301
12302 // If we still have too many processes, now from the least
12303 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012304 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012305 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012306 " of " + curMaxProcs + " processes");
12307 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012308 i<mLruProcesses.size()
12309 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012310 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012311 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012312 // Quit the application only if we have a state saved for
12313 // all of its activities.
12314 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012315 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 int NUMA = app.activities.size();
12317 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012318 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012319 TAG, "Looking to quit " + app.processName);
12320 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012321 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012322 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012323 TAG, " " + r.intent.getComponent().flattenToShortString()
12324 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12325 canQuit = (r.haveState || !r.stateNotNeeded)
12326 && !r.visible && r.stopped;
12327 }
12328 if (canQuit) {
12329 // Finish all of the activities, and then the app itself.
12330 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012331 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012333 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012334 }
12335 r.resultTo = null;
12336 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012337 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 + app.processName + " ("
12339 + (app.thread != null ? app.thread.asBinder() : null)
12340 + ")\n");
12341 if (app.pid > 0 && app.pid != MY_PID) {
12342 Process.killProcess(app.pid);
12343 } else {
12344 try {
12345 app.thread.scheduleExit();
12346 } catch (Exception e) {
12347 // Ignore exceptions.
12348 }
12349 }
12350 // todo: For now we assume the application is not buggy
12351 // or evil, and will quit as a result of our request.
12352 // Eventually we need to drive this off of the death
12353 // notification, and kill the process if it takes too long.
12354 cleanUpApplicationRecordLocked(app, false, i);
12355 i--;
12356 //dump();
12357 }
12358 }
12359
12360 }
12361
12362 int curMaxActivities = MAX_ACTIVITIES;
12363 if (mAlwaysFinishActivities) {
12364 curMaxActivities = 1;
12365 }
12366
12367 // Finally, if there are too many activities now running, try to
12368 // finish as many as we can to get back down to the limit.
12369 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012370 i<mMainStack.mLRUActivities.size()
12371 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012372 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012373 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012374 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012375
12376 // We can finish this one if we have its icicle saved and
12377 // it is not persistent.
12378 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012379 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012380 final int origSize = mMainStack.mLRUActivities.size();
12381 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382
12383 // This will remove it from the LRU list, so keep
12384 // our index at the same value. Note that this check to
12385 // see if the size changes is just paranoia -- if
12386 // something unexpected happens, we don't want to end up
12387 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012388 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012389 i--;
12390 }
12391 }
12392 }
12393 }
12394 }
12395
12396 /** This method sends the specified signal to each of the persistent apps */
12397 public void signalPersistentProcesses(int sig) throws RemoteException {
12398 if (sig != Process.SIGNAL_USR1) {
12399 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12400 }
12401
12402 synchronized (this) {
12403 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12404 != PackageManager.PERMISSION_GRANTED) {
12405 throw new SecurityException("Requires permission "
12406 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12407 }
12408
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012409 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12410 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411 if (r.thread != null && r.persistent) {
12412 Process.sendSignal(r.pid, sig);
12413 }
12414 }
12415 }
12416 }
12417
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012418 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012419 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012420
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012421 try {
12422 synchronized (this) {
12423 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12424 // its own permission.
12425 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12426 != PackageManager.PERMISSION_GRANTED) {
12427 throw new SecurityException("Requires permission "
12428 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012429 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012430
12431 if (start && fd == null) {
12432 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012433 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012434
12435 ProcessRecord proc = null;
12436 try {
12437 int pid = Integer.parseInt(process);
12438 synchronized (mPidsSelfLocked) {
12439 proc = mPidsSelfLocked.get(pid);
12440 }
12441 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012442 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012443
12444 if (proc == null) {
12445 HashMap<String, SparseArray<ProcessRecord>> all
12446 = mProcessNames.getMap();
12447 SparseArray<ProcessRecord> procs = all.get(process);
12448 if (procs != null && procs.size() > 0) {
12449 proc = procs.valueAt(0);
12450 }
12451 }
12452
12453 if (proc == null || proc.thread == null) {
12454 throw new IllegalArgumentException("Unknown process: " + process);
12455 }
12456
12457 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12458 if (isSecure) {
12459 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12460 throw new SecurityException("Process not debuggable: " + proc);
12461 }
12462 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012463
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012464 proc.thread.profilerControl(start, path, fd);
12465 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012466 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012467 }
12468 } catch (RemoteException e) {
12469 throw new IllegalStateException("Process disappeared");
12470 } finally {
12471 if (fd != null) {
12472 try {
12473 fd.close();
12474 } catch (IOException e) {
12475 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012476 }
12477 }
12478 }
12479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012480 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12481 public void monitor() {
12482 synchronized (this) { }
12483 }
12484}