blob: 399c19ae7f574ff324588d489d46d9609d42ec96 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070079import android.net.Proxy;
80import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700111import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700118import java.io.BufferedInputStream;
119import java.io.BufferedOutputStream;
120import java.io.DataInputStream;
121import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.File;
123import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200127import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800128import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.PrintWriter;
130import java.lang.IllegalStateException;
131import java.lang.ref.WeakReference;
132import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700133import java.util.Collections;
134import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.util.HashMap;
136import java.util.HashSet;
137import java.util.Iterator;
138import java.util.List;
139import java.util.Locale;
140import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700141import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700142import java.util.concurrent.atomic.AtomicBoolean;
143import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700145public final class ActivityManagerService extends ActivityManagerNative
146 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final String TAG = "ActivityManager";
148 static final boolean DEBUG = false;
149 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
150 static final boolean DEBUG_SWITCH = localLOGV || false;
151 static final boolean DEBUG_TASKS = localLOGV || false;
152 static final boolean DEBUG_PAUSE = localLOGV || false;
153 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
154 static final boolean DEBUG_TRANSITION = localLOGV || false;
155 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700156 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700158 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_VISBILITY = localLOGV || false;
160 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700161 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800162 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700164 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700165 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700166 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700167 static final boolean DEBUG_POWER = localLOGV || false;
168 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean VALIDATE_TOKENS = false;
170 static final boolean SHOW_ACTIVITY_START_TIME = true;
171
172 // Control over CPU and battery monitoring.
173 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
174 static final boolean MONITOR_CPU_USAGE = true;
175 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
176 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
177 static final boolean MONITOR_THREAD_CPU_USAGE = false;
178
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700180 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 private static final String SYSTEM_SECURE = "ro.secure";
183
184 // This is the maximum number of application processes we would like
185 // to have running. Due to the asynchronous nature of things, we can
186 // temporarily go beyond this limit.
187 static final int MAX_PROCESSES = 2;
188
189 // Set to false to leave processes running indefinitely, relying on
190 // the kernel killing them as resources are required.
191 static final boolean ENFORCE_PROCESS_LIMIT = false;
192
193 // This is the maximum number of activities that we would like to have
194 // running at a given time.
195 static final int MAX_ACTIVITIES = 20;
196
197 // Maximum number of recent tasks that we can remember.
198 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700199
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700200 // Amount of time after a call to stopAppSwitches() during which we will
201 // prevent further untrusted switches from happening.
202 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203
204 // How long we wait for a launched process to attach to the activity manager
205 // before we decide it's never going to come up for real.
206 static final int PROC_START_TIMEOUT = 10*1000;
207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 // How long to wait after going idle before forcing apps to GC.
209 static final int GC_TIMEOUT = 5*1000;
210
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700211 // The minimum amount of time between successive GC requests for a process.
212 static final int GC_MIN_INTERVAL = 60*1000;
213
Dianne Hackborn287952c2010-09-22 22:34:31 -0700214 // The rate at which we check for apps using excessive power -- 15 mins.
215 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
216
217 // The minimum sample duration we will allow before deciding we have
218 // enough data on wake locks to start killing things.
219 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
220
221 // The minimum sample duration we will allow before deciding we have
222 // enough data on CPU usage to start killing things.
223 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // How long we allow a receiver to run before giving up on it.
226 static final int BROADCAST_TIMEOUT = 10*1000;
227
228 // How long we wait for a service to finish executing.
229 static final int SERVICE_TIMEOUT = 20*1000;
230
231 // How long a service needs to be running until restarting its process
232 // is no longer considered to be a relaunch of the service.
233 static final int SERVICE_RESTART_DURATION = 5*1000;
234
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700235 // How long a service needs to be running until it will start back at
236 // SERVICE_RESTART_DURATION after being killed.
237 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
238
239 // Multiplying factor to increase restart duration time by, for each time
240 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
241 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
242
243 // The minimum amount of time between restarting services that we allow.
244 // That is, when multiple services are restarting, we won't allow each
245 // to restart less than this amount of time from the last one.
246 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 // Maximum amount of time for there to be no activity on a service before
249 // we consider it non-essential and allow its process to go on the
250 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700251 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // How long we wait until we timeout on key dispatching.
254 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
255
256 // The minimum time we allow between crashes, for us to consider this
257 // application to be bad and stop and its services and reject broadcasts.
258 static final int MIN_CRASH_INTERVAL = 60*1000;
259
260 // How long we wait until we timeout on key dispatching during instrumentation.
261 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
262
263 // OOM adjustments for processes in various states:
264
265 // This is a process without anything currently running in it. Definitely
266 // the first to go! Value set in system/rootdir/init.rc on startup.
267 // This value is initalized in the constructor, careful when refering to
268 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 // This is a process only hosting activities that are not visible,
272 // so it can be killed without any disruption. Value set in
273 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 static int HIDDEN_APP_MIN_ADJ;
276
The Android Open Source Project4df24232009-03-05 14:34:35 -0800277 // This is a process holding the home application -- we want to try
278 // avoiding killing it, even if it would normally be in the background,
279 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800281
Christopher Tate6fa95972009-06-05 18:43:55 -0700282 // This is a process currently hosting a backup operation. Killing it
283 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 // This is a process holding a secondary server -- killing it will not
287 // have much of an impact as far as the user is concerned. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700291 // This is a process with a heavy-weight application. It is in the
292 // background, but we want to try to avoid killing it. Value set in
293 // system/rootdir/init.rc on startup.
294 static final int HEAVY_WEIGHT_APP_ADJ;
295
296 // This is a process only hosting components that are perceptible to the
297 // user, and we really want to avoid killing them, but they are not
298 // immediately visible. An example is background music playback. Value set in
299 // system/rootdir/init.rc on startup.
300 static final int PERCEPTIBLE_APP_ADJ;
301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 // This is a process only hosting activities that are visible to the
303 // user, so we'd prefer they don't disappear. Value set in
304 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800305 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
307 // This is the process running the current foreground app. We'd really
308 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800309 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 // This is a process running a core server, such as telephony. Definitely
312 // don't want to kill it, but doing so is not completely fatal.
313 static final int CORE_SERVER_ADJ = -12;
314
315 // The system process runs at the default adjustment.
316 static final int SYSTEM_ADJ = -16;
317
318 // Memory pages are 4K.
319 static final int PAGE_SIZE = 4*1024;
320
321 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322 static final int EMPTY_APP_MEM;
323 static final int HIDDEN_APP_MEM;
324 static final int HOME_APP_MEM;
325 static final int BACKUP_APP_MEM;
326 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static final int HEAVY_WEIGHT_APP_MEM;
328 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800329 static final int VISIBLE_APP_MEM;
330 static final int FOREGROUND_APP_MEM;
331
332 // The minimum number of hidden apps we want to be able to keep around,
333 // without empty apps being able to push them out of memory.
334 static final int MIN_HIDDEN_APPS = 2;
335
Dianne Hackborn8633e682010-04-22 16:03:41 -0700336 // The maximum number of hidden processes we will keep around before
337 // killing them; this is just a control to not let us go too crazy with
338 // keeping around processes on devices with large amounts of RAM.
339 static final int MAX_HIDDEN_APPS = 15;
340
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700342 // been idle for less than 15 seconds.
343 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800344
345 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700346 // been idle for less than 120 seconds.
347 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800348
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700349 static int getIntProp(String name, boolean allowZero) {
350 String str = SystemProperties.get(name);
351 if (str == null) {
352 throw new IllegalArgumentException("Property not defined: " + name);
353 }
354 int val = Integer.valueOf(str);
355 if (val == 0 && !allowZero) {
356 throw new IllegalArgumentException("Property must not be zero: " + name);
357 }
358 return val;
359 }
360
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 static {
362 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700363 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
364 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
365 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
366 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
367 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
368 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
369 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
370 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
371 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
372 // These days we use the last empty slot for hidden apps as well.
373 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
374 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
375 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
376 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
377 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
378 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
379 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
380 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
381 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
382 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
Dan Egnor42471dd2010-01-07 17:25:22 -0800385 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386
387 static final String[] EMPTY_STRING_ARRAY = new String[0];
388
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700389 public ActivityStack mMainStack;
390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700392 * Description of a request to start a new activity, which has been held
393 * due to app switches being disabled.
394 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700395 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700396 ActivityRecord r;
397 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700398 Uri[] grantedUriPermissions;
399 int grantedMode;
400 boolean onlyIfNeeded;
401 }
402
403 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
404 = new ArrayList<PendingActivityLaunch>();
405
406 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 * List of all active broadcasts that are to be executed immediately
408 * (without waiting for another broadcast to finish). Currently this only
409 * contains broadcasts to registered receivers, to avoid spinning up
410 * a bunch of processes to execute IntentReceiver components.
411 */
412 final ArrayList<BroadcastRecord> mParallelBroadcasts
413 = new ArrayList<BroadcastRecord>();
414
415 /**
416 * List of all active broadcasts that are to be executed one at a time.
417 * The object at the top of the list is the currently activity broadcasts;
418 * those after it are waiting for the top to finish..
419 */
420 final ArrayList<BroadcastRecord> mOrderedBroadcasts
421 = new ArrayList<BroadcastRecord>();
422
423 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800424 * Historical data of past broadcasts, for debugging.
425 */
426 static final int MAX_BROADCAST_HISTORY = 100;
427 final BroadcastRecord[] mBroadcastHistory
428 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
429
430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * Set when we current have a BROADCAST_INTENT_MSG in flight.
432 */
433 boolean mBroadcastsScheduled = false;
434
435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * Activity we have told the window manager to have key focus.
437 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700438 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * List of intents that were used to start the most recent tasks.
441 */
442 final ArrayList<TaskRecord> mRecentTasks
443 = new ArrayList<TaskRecord>();
444
445 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 * All of the applications we currently have running organized by name.
447 * The keys are strings of the application package name (as
448 * returned by the package manager), and the keys are ApplicationRecord
449 * objects.
450 */
451 final ProcessMap<ProcessRecord> mProcessNames
452 = new ProcessMap<ProcessRecord>();
453
454 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700455 * The currently running heavy-weight process, if any.
456 */
457 ProcessRecord mHeavyWeightProcess = null;
458
459 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 * The last time that various processes have crashed.
461 */
462 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
463
464 /**
465 * Set of applications that we consider to be bad, and will reject
466 * incoming broadcasts from (which the user has no control over).
467 * Processes are added to this set when they have crashed twice within
468 * a minimum amount of time; they are removed from it when they are
469 * later restarted (hopefully due to some user action). The value is the
470 * time it was added to the list.
471 */
472 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
473
474 /**
475 * All of the processes we currently have running organized by pid.
476 * The keys are the pid running the application.
477 *
478 * <p>NOTE: This object is protected by its own lock, NOT the global
479 * activity manager lock!
480 */
481 final SparseArray<ProcessRecord> mPidsSelfLocked
482 = new SparseArray<ProcessRecord>();
483
484 /**
485 * All of the processes that have been forced to be foreground. The key
486 * is the pid of the caller who requested it (we hold a death
487 * link on it).
488 */
489 abstract class ForegroundToken implements IBinder.DeathRecipient {
490 int pid;
491 IBinder token;
492 }
493 final SparseArray<ForegroundToken> mForegroundProcesses
494 = new SparseArray<ForegroundToken>();
495
496 /**
497 * List of records for processes that someone had tried to start before the
498 * system was ready. We don't start them at that point, but ensure they
499 * are started by the time booting is complete.
500 */
501 final ArrayList<ProcessRecord> mProcessesOnHold
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of records for processes that we have started and are waiting
506 * for them to call back. This is really only needed when running in
507 * single processes mode, in which case we do not have a unique pid for
508 * each process.
509 */
510 final ArrayList<ProcessRecord> mStartingProcesses
511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of persistent applications that are in the process
515 * of being started.
516 */
517 final ArrayList<ProcessRecord> mPersistentStartingProcesses
518 = new ArrayList<ProcessRecord>();
519
520 /**
521 * Processes that are being forcibly torn down.
522 */
523 final ArrayList<ProcessRecord> mRemovedProcesses
524 = new ArrayList<ProcessRecord>();
525
526 /**
527 * List of running applications, sorted by recent usage.
528 * The first entry in the list is the least recently used.
529 * It contains ApplicationRecord objects. This list does NOT include
530 * any persistent application records (since we never want to exit them).
531 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800532 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 = new ArrayList<ProcessRecord>();
534
535 /**
536 * List of processes that should gc as soon as things are idle.
537 */
538 final ArrayList<ProcessRecord> mProcessesToGc
539 = new ArrayList<ProcessRecord>();
540
541 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800542 * This is the process holding what we currently consider to be
543 * the "home" activity.
544 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700545 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800546
547 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 * Set of PendingResultRecord objects that are currently active.
549 */
550 final HashSet mPendingResultRecords = new HashSet();
551
552 /**
553 * Set of IntentSenderRecord objects that are currently active.
554 */
555 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
556 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
557
558 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800559 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700560 * already logged DropBox entries for. Guarded by itself. If
561 * something (rogue user app) forces this over
562 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
563 */
564 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
565 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
566
567 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700568 * Strict Mode background batched logging state.
569 *
570 * The string buffer is guarded by itself, and its lock is also
571 * used to determine if another batched write is already
572 * in-flight.
573 */
574 private final StringBuilder mStrictModeBuffer = new StringBuilder();
575
576 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700577 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
578 */
579 private boolean mPendingBroadcastTimeoutMessage;
580
581 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 * Intent broadcast that we have tried to start, but are
583 * waiting for its application's process to be created. We only
584 * need one (instead of a list) because we always process broadcasts
585 * one at a time, so no others can be started while waiting for this
586 * one.
587 */
588 BroadcastRecord mPendingBroadcast = null;
589
590 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700591 * The receiver index that is pending, to restart the broadcast if needed.
592 */
593 int mPendingBroadcastRecvIndex;
594
595 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 * Keeps track of all IIntentReceivers that have been registered for
597 * broadcasts. Hash keys are the receiver IBinder, hash value is
598 * a ReceiverList.
599 */
600 final HashMap mRegisteredReceivers = new HashMap();
601
602 /**
603 * Resolver for broadcast intents to registered receivers.
604 * Holds BroadcastFilter (subclass of IntentFilter).
605 */
606 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
607 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
608 @Override
609 protected boolean allowFilterResult(
610 BroadcastFilter filter, List<BroadcastFilter> dest) {
611 IBinder target = filter.receiverList.receiver.asBinder();
612 for (int i=dest.size()-1; i>=0; i--) {
613 if (dest.get(i).receiverList.receiver.asBinder() == target) {
614 return false;
615 }
616 }
617 return true;
618 }
619 };
620
621 /**
622 * State of all active sticky broadcasts. Keys are the action of the
623 * sticky Intent, values are an ArrayList of all broadcasted intents with
624 * that action (which should usually be one).
625 */
626 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
627 new HashMap<String, ArrayList<Intent>>();
628
629 /**
630 * All currently running services.
631 */
632 final HashMap<ComponentName, ServiceRecord> mServices =
633 new HashMap<ComponentName, ServiceRecord>();
634
635 /**
636 * All currently running services indexed by the Intent used to start them.
637 */
638 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
639 new HashMap<Intent.FilterComparison, ServiceRecord>();
640
641 /**
642 * All currently bound service connections. Keys are the IBinder of
643 * the client's IServiceConnection.
644 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700645 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
646 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647
648 /**
649 * List of services that we have been asked to start,
650 * but haven't yet been able to. It is used to hold start requests
651 * while waiting for their corresponding application thread to get
652 * going.
653 */
654 final ArrayList<ServiceRecord> mPendingServices
655 = new ArrayList<ServiceRecord>();
656
657 /**
658 * List of services that are scheduled to restart following a crash.
659 */
660 final ArrayList<ServiceRecord> mRestartingServices
661 = new ArrayList<ServiceRecord>();
662
663 /**
664 * List of services that are in the process of being stopped.
665 */
666 final ArrayList<ServiceRecord> mStoppingServices
667 = new ArrayList<ServiceRecord>();
668
669 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700670 * Backup/restore process management
671 */
672 String mBackupAppName = null;
673 BackupRecord mBackupTarget = null;
674
675 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 * List of PendingThumbnailsRecord objects of clients who are still
677 * waiting to receive all of the thumbnails for a task.
678 */
679 final ArrayList mPendingThumbnails = new ArrayList();
680
681 /**
682 * List of HistoryRecord objects that have been finished and must
683 * still report back to a pending thumbnail receiver.
684 */
685 final ArrayList mCancelledThumbnails = new ArrayList();
686
687 /**
688 * All of the currently running global content providers. Keys are a
689 * string containing the provider name and values are a
690 * ContentProviderRecord object containing the data about it. Note
691 * that a single provider may be published under multiple names, so
692 * there may be multiple entries here for a single one in mProvidersByClass.
693 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700694 final HashMap<String, ContentProviderRecord> mProvidersByName
695 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696
697 /**
698 * All of the currently running global content providers. Keys are a
699 * string containing the provider's implementation class and values are a
700 * ContentProviderRecord object containing the data about it.
701 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700702 final HashMap<String, ContentProviderRecord> mProvidersByClass
703 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 /**
706 * List of content providers who have clients waiting for them. The
707 * application is currently being launched and the provider will be
708 * removed from this list once it is published.
709 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700710 final ArrayList<ContentProviderRecord> mLaunchingProviders
711 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
713 /**
714 * Global set of specific Uri permissions that have been granted.
715 */
716 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
717 = new SparseArray<HashMap<Uri, UriPermission>>();
718
719 /**
720 * Thread-local storage used to carry caller permissions over through
721 * indirect content-provider access.
722 * @see #ActivityManagerService.openContentUri()
723 */
724 private class Identity {
725 public int pid;
726 public int uid;
727
728 Identity(int _pid, int _uid) {
729 pid = _pid;
730 uid = _uid;
731 }
732 }
733 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
734
735 /**
736 * All information we have collected about the runtime performance of
737 * any user id that can impact battery performance.
738 */
739 final BatteryStatsService mBatteryStatsService;
740
741 /**
742 * information about component usage
743 */
744 final UsageStatsService mUsageStatsService;
745
746 /**
747 * Current configuration information. HistoryRecord objects are given
748 * a reference to this object to indicate which configuration they are
749 * currently running in, so this object must be kept immutable.
750 */
751 Configuration mConfiguration = new Configuration();
752
753 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800754 * Current sequencing integer of the configuration, for skipping old
755 * configurations.
756 */
757 int mConfigurationSeq = 0;
758
759 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700760 * Hardware-reported OpenGLES version.
761 */
762 final int GL_ES_VERSION;
763
764 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 * List of initialization arguments to pass to all processes when binding applications to them.
766 * For example, references to the commonly used services.
767 */
768 HashMap<String, IBinder> mAppBindArgs;
769
770 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700771 * Temporary to avoid allocations. Protected by main lock.
772 */
773 final StringBuilder mStringBuilder = new StringBuilder(256);
774
775 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 * Used to control how we initialize the service.
777 */
778 boolean mStartRunning = false;
779 ComponentName mTopComponent;
780 String mTopAction;
781 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700782 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 boolean mSystemReady = false;
784 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700785 boolean mWaitingUpdate = false;
786 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700787 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700788 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789
790 Context mContext;
791
792 int mFactoryTest;
793
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700794 boolean mCheckedForSetup;
795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700797 * The time at which we will allow normal application switches again,
798 * after a call to {@link #stopAppSwitches()}.
799 */
800 long mAppSwitchesAllowedTime;
801
802 /**
803 * This is set to true after the first switch after mAppSwitchesAllowedTime
804 * is set; any switches after that will clear the time.
805 */
806 boolean mDidAppSwitch;
807
808 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700810 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700811 long mLastPowerCheckRealtime;
812
813 /**
814 * Last time (in uptime) at which we checked for power usage.
815 */
816 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700817
818 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 * Set while we are wanting to sleep, to prevent any
820 * activities from being started/resumed.
821 */
822 boolean mSleeping = false;
823
824 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700825 * Set if we are shutting down the system, similar to sleeping.
826 */
827 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828
829 /**
830 * Task identifier that activities are currently being started
831 * in. Incremented each time a new task is created.
832 * todo: Replace this with a TokenSpace class that generates non-repeating
833 * integers that won't wrap.
834 */
835 int mCurTask = 1;
836
837 /**
838 * Current sequence id for oom_adj computation traversal.
839 */
840 int mAdjSeq = 0;
841
842 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700843 * Current sequence id for process LRU updating.
844 */
845 int mLruSeq = 0;
846
847 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
849 * is set, indicating the user wants processes started in such a way
850 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
851 * running in each process (thus no pre-initialized process, etc).
852 */
853 boolean mSimpleProcessManagement = false;
854
855 /**
856 * System monitoring: number of processes that died since the last
857 * N procs were started.
858 */
859 int[] mProcDeaths = new int[20];
860
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700861 /**
862 * This is set if we had to do a delayed dexopt of an app before launching
863 * it, to increasing the ANR timeouts in that case.
864 */
865 boolean mDidDexOpt;
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 String mDebugApp = null;
868 boolean mWaitForDebugger = false;
869 boolean mDebugTransient = false;
870 String mOrigDebugApp = null;
871 boolean mOrigWaitForDebugger = false;
872 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700875 final RemoteCallbackList<IActivityWatcher> mWatchers
876 = new RemoteCallbackList<IActivityWatcher>();
877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 /**
879 * Callback of last caller to {@link #requestPss}.
880 */
881 Runnable mRequestPssCallback;
882
883 /**
884 * Remaining processes for which we are waiting results from the last
885 * call to {@link #requestPss}.
886 */
887 final ArrayList<ProcessRecord> mRequestPssList
888 = new ArrayList<ProcessRecord>();
889
890 /**
891 * Runtime statistics collection thread. This object's lock is used to
892 * protect all related state.
893 */
894 final Thread mProcessStatsThread;
895
896 /**
897 * Used to collect process stats when showing not responding dialog.
898 * Protected by mProcessStatsThread.
899 */
900 final ProcessStats mProcessStats = new ProcessStats(
901 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700902 final AtomicLong mLastCpuTime = new AtomicLong(0);
903 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 long mLastWriteTime = 0;
906
907 /**
908 * Set to true after the system has finished booting.
909 */
910 boolean mBooted = false;
911
912 int mProcessLimit = 0;
913
914 WindowManagerService mWindowManager;
915
916 static ActivityManagerService mSelf;
917 static ActivityThread mSystemThread;
918
919 private final class AppDeathRecipient implements IBinder.DeathRecipient {
920 final ProcessRecord mApp;
921 final int mPid;
922 final IApplicationThread mAppThread;
923
924 AppDeathRecipient(ProcessRecord app, int pid,
925 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800926 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 TAG, "New death recipient " + this
928 + " for thread " + thread.asBinder());
929 mApp = app;
930 mPid = pid;
931 mAppThread = thread;
932 }
933
934 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800935 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 TAG, "Death received in " + this
937 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 synchronized(ActivityManagerService.this) {
939 appDiedLocked(mApp, mPid, mAppThread);
940 }
941 }
942 }
943
944 static final int SHOW_ERROR_MSG = 1;
945 static final int SHOW_NOT_RESPONDING_MSG = 2;
946 static final int SHOW_FACTORY_ERROR_MSG = 3;
947 static final int UPDATE_CONFIGURATION_MSG = 4;
948 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
949 static final int WAIT_FOR_DEBUGGER_MSG = 6;
950 static final int BROADCAST_INTENT_MSG = 7;
951 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 static final int SERVICE_TIMEOUT_MSG = 12;
953 static final int UPDATE_TIME_ZONE = 13;
954 static final int SHOW_UID_ERROR_MSG = 14;
955 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700957 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700958 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800959 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700960 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
961 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700962 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700963 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700964 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700965 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966
967 AlertDialog mUidAlert;
968
969 final Handler mHandler = new Handler() {
970 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800971 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 //}
973
974 public void handleMessage(Message msg) {
975 switch (msg.what) {
976 case SHOW_ERROR_MSG: {
977 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 synchronized (ActivityManagerService.this) {
979 ProcessRecord proc = (ProcessRecord)data.get("app");
980 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800981 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 return;
983 }
984 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700985 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800986 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 d.show();
988 proc.crashDialog = d;
989 } else {
990 // The device is asleep, so just pretend that the user
991 // saw a crash dialog and hit "force quit".
992 res.set(0);
993 }
994 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700995
996 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 } break;
998 case SHOW_NOT_RESPONDING_MSG: {
999 synchronized (ActivityManagerService.this) {
1000 HashMap data = (HashMap) msg.obj;
1001 ProcessRecord proc = (ProcessRecord)data.get("app");
1002 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001003 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 return;
1005 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001006
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001007 Intent intent = new Intent("android.intent.action.ANR");
1008 if (!mProcessesReady) {
1009 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1010 }
1011 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001012 null, null, 0, null, null, null,
1013 false, false, MY_PID, Process.SYSTEM_UID);
1014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001016 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 d.show();
1018 proc.anrDialog = d;
1019 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001020
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001021 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001023 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1024 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1025 synchronized (ActivityManagerService.this) {
1026 ProcessRecord proc = (ProcessRecord) data.get("app");
1027 if (proc == null) {
1028 Slog.e(TAG, "App not found when showing strict mode dialog.");
1029 break;
1030 }
1031 if (proc.crashDialog != null) {
1032 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1033 return;
1034 }
1035 AppErrorResult res = (AppErrorResult) data.get("result");
1036 if (!mSleeping && !mShuttingDown) {
1037 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1038 d.show();
1039 proc.crashDialog = d;
1040 } else {
1041 // The device is asleep, so just pretend that the user
1042 // saw a crash dialog and hit "force quit".
1043 res.set(0);
1044 }
1045 }
1046 ensureBootCompleted();
1047 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 case SHOW_FACTORY_ERROR_MSG: {
1049 Dialog d = new FactoryErrorDialog(
1050 mContext, msg.getData().getCharSequence("msg"));
1051 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001052 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 } break;
1054 case UPDATE_CONFIGURATION_MSG: {
1055 final ContentResolver resolver = mContext.getContentResolver();
1056 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1057 } break;
1058 case GC_BACKGROUND_PROCESSES_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 performAppGcsIfAppropriateLocked();
1061 }
1062 } break;
1063 case WAIT_FOR_DEBUGGER_MSG: {
1064 synchronized (ActivityManagerService.this) {
1065 ProcessRecord app = (ProcessRecord)msg.obj;
1066 if (msg.arg1 != 0) {
1067 if (!app.waitedForDebugger) {
1068 Dialog d = new AppWaitingForDebuggerDialog(
1069 ActivityManagerService.this,
1070 mContext, app);
1071 app.waitDialog = d;
1072 app.waitedForDebugger = true;
1073 d.show();
1074 }
1075 } else {
1076 if (app.waitDialog != null) {
1077 app.waitDialog.dismiss();
1078 app.waitDialog = null;
1079 }
1080 }
1081 }
1082 } break;
1083 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001084 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 TAG, "Received BROADCAST_INTENT_MSG");
1086 processNextBroadcast(true);
1087 } break;
1088 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001089 synchronized (ActivityManagerService.this) {
1090 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001094 if (mDidDexOpt) {
1095 mDidDexOpt = false;
1096 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1097 nmsg.obj = msg.obj;
1098 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1099 return;
1100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 serviceTimeout((ProcessRecord)msg.obj);
1102 } break;
1103 case UPDATE_TIME_ZONE: {
1104 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001105 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1106 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 if (r.thread != null) {
1108 try {
1109 r.thread.updateTimeZone();
1110 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001111 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 }
1113 }
1114 }
1115 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001116 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001117 case CLEAR_DNS_CACHE: {
1118 synchronized (ActivityManagerService.this) {
1119 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1120 ProcessRecord r = mLruProcesses.get(i);
1121 if (r.thread != null) {
1122 try {
1123 r.thread.clearDnsCache();
1124 } catch (RemoteException ex) {
1125 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1126 }
1127 }
1128 }
1129 }
1130 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001131 case UPDATE_HTTP_PROXY: {
1132 ProxyProperties proxy = (ProxyProperties)msg.obj;
1133 String host = "";
1134 String port = "";
1135 String exclList = "";
1136 if (proxy != null) {
1137 host = proxy.getHost();
1138 port = Integer.toString(proxy.getPort());
1139 exclList = proxy.getExclusionList();
1140 }
1141 synchronized (ActivityManagerService.this) {
1142 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1143 ProcessRecord r = mLruProcesses.get(i);
1144 if (r.thread != null) {
1145 try {
1146 r.thread.setHttpProxy(host, port, exclList);
1147 } catch (RemoteException ex) {
1148 Slog.w(TAG, "Failed to update http proxy for: " +
1149 r.info.processName);
1150 }
1151 }
1152 }
1153 }
1154 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 case SHOW_UID_ERROR_MSG: {
1156 // XXX This is a temporary dialog, no need to localize.
1157 AlertDialog d = new BaseErrorDialog(mContext);
1158 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1159 d.setCancelable(false);
1160 d.setTitle("System UIDs Inconsistent");
1161 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001162 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1164 mUidAlert = d;
1165 d.show();
1166 } break;
1167 case IM_FEELING_LUCKY_MSG: {
1168 if (mUidAlert != null) {
1169 mUidAlert.dismiss();
1170 mUidAlert = null;
1171 }
1172 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001174 if (mDidDexOpt) {
1175 mDidDexOpt = false;
1176 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1177 nmsg.obj = msg.obj;
1178 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1179 return;
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 ProcessRecord app = (ProcessRecord)msg.obj;
1182 synchronized (ActivityManagerService.this) {
1183 processStartTimedOutLocked(app);
1184 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001185 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001186 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1187 synchronized (ActivityManagerService.this) {
1188 doPendingActivityLaunchesLocked(true);
1189 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001190 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001191 case KILL_APPLICATION_MSG: {
1192 synchronized (ActivityManagerService.this) {
1193 int uid = msg.arg1;
1194 boolean restart = (msg.arg2 == 1);
1195 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001196 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001197 }
1198 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001199 case FINALIZE_PENDING_INTENT_MSG: {
1200 ((PendingIntentRecord)msg.obj).completeFinalize();
1201 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001202 case POST_HEAVY_NOTIFICATION_MSG: {
1203 INotificationManager inm = NotificationManager.getService();
1204 if (inm == null) {
1205 return;
1206 }
1207
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001208 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001209 ProcessRecord process = root.app;
1210 if (process == null) {
1211 return;
1212 }
1213
1214 try {
1215 Context context = mContext.createPackageContext(process.info.packageName, 0);
1216 String text = mContext.getString(R.string.heavy_weight_notification,
1217 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1218 Notification notification = new Notification();
1219 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1220 notification.when = 0;
1221 notification.flags = Notification.FLAG_ONGOING_EVENT;
1222 notification.tickerText = text;
1223 notification.defaults = 0; // please be quiet
1224 notification.sound = null;
1225 notification.vibrate = null;
1226 notification.setLatestEventInfo(context, text,
1227 mContext.getText(R.string.heavy_weight_notification_detail),
1228 PendingIntent.getActivity(mContext, 0, root.intent,
1229 PendingIntent.FLAG_CANCEL_CURRENT));
1230
1231 try {
1232 int[] outId = new int[1];
1233 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1234 notification, outId);
1235 } catch (RuntimeException e) {
1236 Slog.w(ActivityManagerService.TAG,
1237 "Error showing notification for heavy-weight app", e);
1238 } catch (RemoteException e) {
1239 }
1240 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001241 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001242 }
1243 } break;
1244 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1245 INotificationManager inm = NotificationManager.getService();
1246 if (inm == null) {
1247 return;
1248 }
1249 try {
1250 inm.cancelNotification("android",
1251 R.string.heavy_weight_notification);
1252 } catch (RuntimeException e) {
1253 Slog.w(ActivityManagerService.TAG,
1254 "Error canceling notification for service", e);
1255 } catch (RemoteException e) {
1256 }
1257 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001258 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1259 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001260 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001261 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001262 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1263 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001264 }
1265 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 }
1267 }
1268 };
1269
1270 public static void setSystemProcess() {
1271 try {
1272 ActivityManagerService m = mSelf;
1273
1274 ServiceManager.addService("activity", m);
1275 ServiceManager.addService("meminfo", new MemBinder(m));
1276 if (MONITOR_CPU_USAGE) {
1277 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 ServiceManager.addService("permission", new PermissionController(m));
1280
1281 ApplicationInfo info =
1282 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001283 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001284 mSystemThread.installSystemApplicationInfo(info);
1285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 synchronized (mSelf) {
1287 ProcessRecord app = mSelf.newProcessRecordLocked(
1288 mSystemThread.getApplicationThread(), info,
1289 info.processName);
1290 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001291 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 app.maxAdj = SYSTEM_ADJ;
1293 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1294 synchronized (mSelf.mPidsSelfLocked) {
1295 mSelf.mPidsSelfLocked.put(app.pid, app);
1296 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001297 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 }
1299 } catch (PackageManager.NameNotFoundException e) {
1300 throw new RuntimeException(
1301 "Unable to find android system package", e);
1302 }
1303 }
1304
1305 public void setWindowManager(WindowManagerService wm) {
1306 mWindowManager = wm;
1307 }
1308
1309 public static final Context main(int factoryTest) {
1310 AThread thr = new AThread();
1311 thr.start();
1312
1313 synchronized (thr) {
1314 while (thr.mService == null) {
1315 try {
1316 thr.wait();
1317 } catch (InterruptedException e) {
1318 }
1319 }
1320 }
1321
1322 ActivityManagerService m = thr.mService;
1323 mSelf = m;
1324 ActivityThread at = ActivityThread.systemMain();
1325 mSystemThread = at;
1326 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001327 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 m.mContext = context;
1329 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001330 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331
1332 m.mBatteryStatsService.publish(context);
1333 m.mUsageStatsService.publish(context);
1334
1335 synchronized (thr) {
1336 thr.mReady = true;
1337 thr.notifyAll();
1338 }
1339
1340 m.startRunning(null, null, null, null);
1341
1342 return context;
1343 }
1344
1345 public static ActivityManagerService self() {
1346 return mSelf;
1347 }
1348
1349 static class AThread extends Thread {
1350 ActivityManagerService mService;
1351 boolean mReady = false;
1352
1353 public AThread() {
1354 super("ActivityManager");
1355 }
1356
1357 public void run() {
1358 Looper.prepare();
1359
1360 android.os.Process.setThreadPriority(
1361 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001362 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363
1364 ActivityManagerService m = new ActivityManagerService();
1365
1366 synchronized (this) {
1367 mService = m;
1368 notifyAll();
1369 }
1370
1371 synchronized (this) {
1372 while (!mReady) {
1373 try {
1374 wait();
1375 } catch (InterruptedException e) {
1376 }
1377 }
1378 }
1379
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001380 // For debug builds, log event loop stalls to dropbox for analysis.
1381 if (StrictMode.conditionallyEnableDebugLogging()) {
1382 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1383 }
1384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 Looper.loop();
1386 }
1387 }
1388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 static class MemBinder extends Binder {
1390 ActivityManagerService mActivityManagerService;
1391 MemBinder(ActivityManagerService activityManagerService) {
1392 mActivityManagerService = activityManagerService;
1393 }
1394
1395 @Override
1396 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1397 ActivityManagerService service = mActivityManagerService;
1398 ArrayList<ProcessRecord> procs;
1399 synchronized (mActivityManagerService) {
1400 if (args != null && args.length > 0
1401 && args[0].charAt(0) != '-') {
1402 procs = new ArrayList<ProcessRecord>();
1403 int pid = -1;
1404 try {
1405 pid = Integer.parseInt(args[0]);
1406 } catch (NumberFormatException e) {
1407
1408 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001409 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1410 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 if (proc.pid == pid) {
1412 procs.add(proc);
1413 } else if (proc.processName.equals(args[0])) {
1414 procs.add(proc);
1415 }
1416 }
1417 if (procs.size() <= 0) {
1418 pw.println("No process found for: " + args[0]);
1419 return;
1420 }
1421 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001422 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1426 }
1427 }
1428
1429 static class CpuBinder extends Binder {
1430 ActivityManagerService mActivityManagerService;
1431 CpuBinder(ActivityManagerService activityManagerService) {
1432 mActivityManagerService = activityManagerService;
1433 }
1434
1435 @Override
1436 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1437 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001438 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1439 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1440 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 }
1442 }
1443 }
1444
1445 private ActivityManagerService() {
1446 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1447 if (v != null && Integer.getInteger(v) != 0) {
1448 mSimpleProcessManagement = true;
1449 }
1450 v = System.getenv("ANDROID_DEBUG_APP");
1451 if (v != null) {
1452 mSimpleProcessManagement = true;
1453 }
1454
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 File dataDir = Environment.getDataDirectory();
1458 File systemDir = new File(dataDir, "system");
1459 systemDir.mkdirs();
1460 mBatteryStatsService = new BatteryStatsService(new File(
1461 systemDir, "batterystats.bin").toString());
1462 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001463 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001464 mOnBattery = DEBUG_POWER ? true
1465 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001466 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001468 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001469 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Jack Palevichb90d28c2009-07-22 15:35:24 -07001471 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1472 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1473
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001474 mConfiguration.setToDefaults();
1475 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 mProcessStats.init();
1477
1478 // Add ourself to the Watchdog monitors.
1479 Watchdog.getInstance().addMonitor(this);
1480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 mProcessStatsThread = new Thread("ProcessStats") {
1482 public void run() {
1483 while (true) {
1484 try {
1485 try {
1486 synchronized(this) {
1487 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001488 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 // + ", write delay=" + nextWriteDelay);
1492 if (nextWriteDelay < nextCpuDelay) {
1493 nextCpuDelay = nextWriteDelay;
1494 }
1495 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001496 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 this.wait(nextCpuDelay);
1498 }
1499 }
1500 } catch (InterruptedException e) {
1501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 updateCpuStatsNow();
1503 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001504 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
1506 }
1507 }
1508 };
1509 mProcessStatsThread.start();
1510 }
1511
1512 @Override
1513 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1514 throws RemoteException {
1515 try {
1516 return super.onTransact(code, data, reply, flags);
1517 } catch (RuntimeException e) {
1518 // The activity manager only throws security exceptions, so let's
1519 // log all others.
1520 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 }
1523 throw e;
1524 }
1525 }
1526
1527 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001528 final long now = SystemClock.uptimeMillis();
1529 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1530 return;
1531 }
1532 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1533 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 mProcessStatsThread.notify();
1535 }
1536 }
1537 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 void updateCpuStatsNow() {
1540 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001541 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 final long now = SystemClock.uptimeMillis();
1543 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001546 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1547 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 haveNewCpuStats = true;
1549 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001550 //Slog.i(TAG, mProcessStats.printCurrentState());
1551 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 // + mProcessStats.getTotalCpuPercent() + "%");
1553
Joe Onorato8a9b2202010-02-26 18:56:32 -08001554 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 if ("true".equals(SystemProperties.get("events.cpu"))) {
1556 int user = mProcessStats.getLastUserTime();
1557 int system = mProcessStats.getLastSystemTime();
1558 int iowait = mProcessStats.getLastIoWaitTime();
1559 int irq = mProcessStats.getLastIrqTime();
1560 int softIrq = mProcessStats.getLastSoftIrqTime();
1561 int idle = mProcessStats.getLastIdleTime();
1562
1563 int total = user + system + iowait + irq + softIrq + idle;
1564 if (total == 0) total = 1;
1565
Doug Zongker2bec3d42009-12-04 12:52:44 -08001566 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 ((user+system+iowait+irq+softIrq) * 100) / total,
1568 (user * 100) / total,
1569 (system * 100) / total,
1570 (iowait * 100) / total,
1571 (irq * 100) / total,
1572 (softIrq * 100) / total);
1573 }
1574 }
1575
Amith Yamasanie43530a2009-08-21 13:11:37 -07001576 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001577 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001578 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 synchronized(mPidsSelfLocked) {
1580 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001581 if (mOnBattery) {
1582 int perc = bstats.startAddingCpuLocked();
1583 int totalUTime = 0;
1584 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001585 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001587 ProcessStats.Stats st = mProcessStats.getStats(i);
1588 if (!st.working) {
1589 continue;
1590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001592 int otherUTime = (st.rel_utime*perc)/100;
1593 int otherSTime = (st.rel_stime*perc)/100;
1594 totalUTime += otherUTime;
1595 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 if (pr != null) {
1597 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1599 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001600 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001601 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001602 } else {
1603 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001604 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001606 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1607 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001608 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 }
1611 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001612 bstats.finishAddingCpuLocked(perc, totalUTime,
1613 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
1615 }
1616 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1619 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001620 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 }
1622 }
1623 }
1624 }
1625
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001626 @Override
1627 public void batteryNeedsCpuUpdate() {
1628 updateCpuStatsNow();
1629 }
1630
1631 @Override
1632 public void batteryPowerChanged(boolean onBattery) {
1633 // When plugging in, update the CPU stats first before changing
1634 // the plug state.
1635 updateCpuStatsNow();
1636 synchronized (this) {
1637 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001638 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001639 }
1640 }
1641 }
1642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 /**
1644 * Initialize the application bind args. These are passed to each
1645 * process when the bindApplication() IPC is sent to the process. They're
1646 * lazily setup to make sure the services are running when they're asked for.
1647 */
1648 private HashMap<String, IBinder> getCommonServicesLocked() {
1649 if (mAppBindArgs == null) {
1650 mAppBindArgs = new HashMap<String, IBinder>();
1651
1652 // Setup the application init args
1653 mAppBindArgs.put("package", ServiceManager.getService("package"));
1654 mAppBindArgs.put("window", ServiceManager.getService("window"));
1655 mAppBindArgs.put(Context.ALARM_SERVICE,
1656 ServiceManager.getService(Context.ALARM_SERVICE));
1657 }
1658 return mAppBindArgs;
1659 }
1660
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001661 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 if (mFocusedActivity != r) {
1663 mFocusedActivity = r;
1664 mWindowManager.setFocusedApp(r, true);
1665 }
1666 }
1667
Dianne Hackborn906497c2010-05-10 15:57:38 -07001668 private final void updateLruProcessInternalLocked(ProcessRecord app,
1669 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001671 int lrui = mLruProcesses.indexOf(app);
1672 if (lrui >= 0) mLruProcesses.remove(lrui);
1673
1674 int i = mLruProcesses.size()-1;
1675 int skipTop = 0;
1676
Dianne Hackborn906497c2010-05-10 15:57:38 -07001677 app.lruSeq = mLruSeq;
1678
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001679 // compute the new weight for this process.
1680 if (updateActivityTime) {
1681 app.lastActivityTime = SystemClock.uptimeMillis();
1682 }
1683 if (app.activities.size() > 0) {
1684 // If this process has activities, we more strongly want to keep
1685 // it around.
1686 app.lruWeight = app.lastActivityTime;
1687 } else if (app.pubProviders.size() > 0) {
1688 // If this process contains content providers, we want to keep
1689 // it a little more strongly.
1690 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1691 // Also don't let it kick out the first few "real" hidden processes.
1692 skipTop = MIN_HIDDEN_APPS;
1693 } else {
1694 // If this process doesn't have activities, we less strongly
1695 // want to keep it around, and generally want to avoid getting
1696 // in front of any very recently used activities.
1697 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1698 // Also don't let it kick out the first few "real" hidden processes.
1699 skipTop = MIN_HIDDEN_APPS;
1700 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001701
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001702 while (i >= 0) {
1703 ProcessRecord p = mLruProcesses.get(i);
1704 // If this app shouldn't be in front of the first N background
1705 // apps, then skip over that many that are currently hidden.
1706 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1707 skipTop--;
1708 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001709 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001710 mLruProcesses.add(i+1, app);
1711 break;
1712 }
1713 i--;
1714 }
1715 if (i < 0) {
1716 mLruProcesses.add(0, app);
1717 }
1718
Dianne Hackborn906497c2010-05-10 15:57:38 -07001719 // If the app is currently using a content provider or service,
1720 // bump those processes as well.
1721 if (app.connections.size() > 0) {
1722 for (ConnectionRecord cr : app.connections) {
1723 if (cr.binding != null && cr.binding.service != null
1724 && cr.binding.service.app != null
1725 && cr.binding.service.app.lruSeq != mLruSeq) {
1726 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1727 updateActivityTime, i+1);
1728 }
1729 }
1730 }
1731 if (app.conProviders.size() > 0) {
1732 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1733 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1734 updateLruProcessInternalLocked(cpr.app, oomAdj,
1735 updateActivityTime, i+1);
1736 }
1737 }
1738 }
1739
Joe Onorato8a9b2202010-02-26 18:56:32 -08001740 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 if (oomAdj) {
1742 updateOomAdjLocked();
1743 }
1744 }
1745
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001746 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001747 boolean oomAdj, boolean updateActivityTime) {
1748 mLruSeq++;
1749 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1750 }
1751
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001752 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 String processName, int uid) {
1754 if (uid == Process.SYSTEM_UID) {
1755 // The system gets to run in any process. If there are multiple
1756 // processes with the same uid, just pick the first (this
1757 // should never happen).
1758 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1759 processName);
1760 return procs != null ? procs.valueAt(0) : null;
1761 }
1762 ProcessRecord proc = mProcessNames.get(processName, uid);
1763 return proc;
1764 }
1765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001766 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001767 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001768 try {
1769 if (pm.performDexOpt(packageName)) {
1770 mDidDexOpt = true;
1771 }
1772 } catch (RemoteException e) {
1773 }
1774 }
1775
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001776 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 int transit = mWindowManager.getPendingAppTransition();
1778 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1779 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1780 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1781 }
1782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001783 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001785 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1787 // We don't have to do anything more if:
1788 // (1) There is an existing application record; and
1789 // (2) The caller doesn't think it is dead, OR there is no thread
1790 // object attached to it so we know it couldn't have crashed; and
1791 // (3) There is a pid assigned to it, so it is either starting or
1792 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001793 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 + " app=" + app + " knownToBeDead=" + knownToBeDead
1795 + " thread=" + (app != null ? app.thread : null)
1796 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001797 if (app != null && app.pid > 0) {
1798 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001799 // We already have the app running, or are waiting for it to
1800 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001802 return app;
1803 } else {
1804 // An application record is attached to a previous process,
1805 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001806 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001807 handleAppDiedLocked(app, true);
1808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 String hostingNameStr = hostingName != null
1812 ? hostingName.flattenToShortString() : null;
1813
1814 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1815 // If we are in the background, then check to see if this process
1816 // is bad. If so, we will just silently fail.
1817 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001818 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1819 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 return null;
1821 }
1822 } else {
1823 // When the user is explicitly starting a process, then clear its
1824 // crash count so that we won't make it bad until they see at
1825 // least one crash dialog again, and make the process good again
1826 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001827 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1828 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 mProcessCrashTimes.remove(info.processName, info.uid);
1830 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001831 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 info.processName);
1833 mBadProcesses.remove(info.processName, info.uid);
1834 if (app != null) {
1835 app.bad = false;
1836 }
1837 }
1838 }
1839
1840 if (app == null) {
1841 app = newProcessRecordLocked(null, info, processName);
1842 mProcessNames.put(processName, info.uid, app);
1843 } else {
1844 // If this is a new package in the process, add the package to the list
1845 app.addPackage(info.packageName);
1846 }
1847
1848 // If the system is not ready yet, then hold off on starting this
1849 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001850 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001851 && !isAllowedWhileBooting(info)
1852 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 if (!mProcessesOnHold.contains(app)) {
1854 mProcessesOnHold.add(app);
1855 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001856 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 return app;
1858 }
1859
1860 startProcessLocked(app, hostingType, hostingNameStr);
1861 return (app.pid != 0) ? app : null;
1862 }
1863
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001864 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1865 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1866 }
1867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 private final void startProcessLocked(ProcessRecord app,
1869 String hostingType, String hostingNameStr) {
1870 if (app.pid > 0 && app.pid != MY_PID) {
1871 synchronized (mPidsSelfLocked) {
1872 mPidsSelfLocked.remove(app.pid);
1873 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1874 }
1875 app.pid = 0;
1876 }
1877
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001878 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1879 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 mProcessesOnHold.remove(app);
1881
1882 updateCpuStats();
1883
1884 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1885 mProcDeaths[0] = 0;
1886
1887 try {
1888 int uid = app.info.uid;
1889 int[] gids = null;
1890 try {
1891 gids = mContext.getPackageManager().getPackageGids(
1892 app.info.packageName);
1893 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
1896 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1897 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1898 && mTopComponent != null
1899 && app.processName.equals(mTopComponent.getPackageName())) {
1900 uid = 0;
1901 }
1902 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1903 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1904 uid = 0;
1905 }
1906 }
1907 int debugFlags = 0;
1908 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1909 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1910 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001911 // Run the app in safe mode if its manifest requests so or the
1912 // system is booted in safe mode.
1913 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1914 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001915 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1918 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1919 }
1920 if ("1".equals(SystemProperties.get("debug.assert"))) {
1921 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1922 }
1923 int pid = Process.start("android.app.ActivityThread",
1924 mSimpleProcessManagement ? app.processName : null, uid, uid,
1925 gids, debugFlags, null);
1926 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1927 synchronized (bs) {
1928 if (bs.isOnBattery()) {
1929 app.batteryStats.incStartsLocked();
1930 }
1931 }
1932
Doug Zongker2bec3d42009-12-04 12:52:44 -08001933 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 app.processName, hostingType,
1935 hostingNameStr != null ? hostingNameStr : "");
1936
1937 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001938 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001941 StringBuilder buf = mStringBuilder;
1942 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 buf.append("Start proc ");
1944 buf.append(app.processName);
1945 buf.append(" for ");
1946 buf.append(hostingType);
1947 if (hostingNameStr != null) {
1948 buf.append(" ");
1949 buf.append(hostingNameStr);
1950 }
1951 buf.append(": pid=");
1952 buf.append(pid);
1953 buf.append(" uid=");
1954 buf.append(uid);
1955 buf.append(" gids={");
1956 if (gids != null) {
1957 for (int gi=0; gi<gids.length; gi++) {
1958 if (gi != 0) buf.append(", ");
1959 buf.append(gids[gi]);
1960
1961 }
1962 }
1963 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001964 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 if (pid == 0 || pid == MY_PID) {
1966 // Processes are being emulated with threads.
1967 app.pid = MY_PID;
1968 app.removed = false;
1969 mStartingProcesses.add(app);
1970 } else if (pid > 0) {
1971 app.pid = pid;
1972 app.removed = false;
1973 synchronized (mPidsSelfLocked) {
1974 this.mPidsSelfLocked.put(pid, app);
1975 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1976 msg.obj = app;
1977 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1978 }
1979 } else {
1980 app.pid = 0;
1981 RuntimeException e = new RuntimeException(
1982 "Failure starting process " + app.processName
1983 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001984 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986 } catch (RuntimeException e) {
1987 // XXX do better error recovery.
1988 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001989 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 }
1991 }
1992
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 if (resumed) {
1995 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1996 } else {
1997 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1998 }
1999 }
2000
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002002 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2003 && mTopAction == null) {
2004 // We are running in factory test mode, but unable to find
2005 // the factory test app, so just sit around displaying the
2006 // error message and don't try to start anything.
2007 return false;
2008 }
2009 Intent intent = new Intent(
2010 mTopAction,
2011 mTopData != null ? Uri.parse(mTopData) : null);
2012 intent.setComponent(mTopComponent);
2013 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2014 intent.addCategory(Intent.CATEGORY_HOME);
2015 }
2016 ActivityInfo aInfo =
2017 intent.resolveActivityInfo(mContext.getPackageManager(),
2018 STOCK_PM_FLAGS);
2019 if (aInfo != null) {
2020 intent.setComponent(new ComponentName(
2021 aInfo.applicationInfo.packageName, aInfo.name));
2022 // Don't do this if the home app is currently being
2023 // instrumented.
2024 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2025 aInfo.applicationInfo.uid);
2026 if (app == null || app.instrumentationClass == null) {
2027 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002029 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002030 }
2031 }
2032
2033
2034 return true;
2035 }
2036
2037 /**
2038 * Starts the "new version setup screen" if appropriate.
2039 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002041 // Only do this once per boot.
2042 if (mCheckedForSetup) {
2043 return;
2044 }
2045
2046 // We will show this screen if the current one is a different
2047 // version than the last one shown, and we are not running in
2048 // low-level factory test mode.
2049 final ContentResolver resolver = mContext.getContentResolver();
2050 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2051 Settings.Secure.getInt(resolver,
2052 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2053 mCheckedForSetup = true;
2054
2055 // See if we should be showing the platform update setup UI.
2056 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2057 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2058 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2059
2060 // We don't allow third party apps to replace this.
2061 ResolveInfo ri = null;
2062 for (int i=0; ris != null && i<ris.size(); i++) {
2063 if ((ris.get(i).activityInfo.applicationInfo.flags
2064 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2065 ri = ris.get(i);
2066 break;
2067 }
2068 }
2069
2070 if (ri != null) {
2071 String vers = ri.activityInfo.metaData != null
2072 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2073 : null;
2074 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2075 vers = ri.activityInfo.applicationInfo.metaData.getString(
2076 Intent.METADATA_SETUP_VERSION);
2077 }
2078 String lastVers = Settings.Secure.getString(
2079 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2080 if (vers != null && !vers.equals(lastVers)) {
2081 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2082 intent.setComponent(new ComponentName(
2083 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002084 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002085 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002086 }
2087 }
2088 }
2089 }
2090
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002091 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002092 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002093
2094 final int identHash = System.identityHashCode(r);
2095 updateUsageStats(r, true);
2096
2097 int i = mWatchers.beginBroadcast();
2098 while (i > 0) {
2099 i--;
2100 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2101 if (w != null) {
2102 try {
2103 w.activityResuming(identHash);
2104 } catch (RemoteException e) {
2105 }
2106 }
2107 }
2108 mWatchers.finishBroadcast();
2109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002111 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002112 final int N = mPendingActivityLaunches.size();
2113 if (N <= 0) {
2114 return;
2115 }
2116 for (int i=0; i<N; i++) {
2117 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002118 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002119 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2120 doResume && i == (N-1));
2121 }
2122 mPendingActivityLaunches.clear();
2123 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002124
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002125 public final int startActivity(IApplicationThread caller,
2126 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2127 int grantedMode, IBinder resultTo,
2128 String resultWho, int requestCode, boolean onlyIfNeeded,
2129 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002130 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002131 grantedUriPermissions, grantedMode, resultTo, resultWho,
2132 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002133 }
2134
2135 public final WaitResult startActivityAndWait(IApplicationThread caller,
2136 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2137 int grantedMode, IBinder resultTo,
2138 String resultWho, int requestCode, boolean onlyIfNeeded,
2139 boolean debug) {
2140 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002141 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002142 grantedUriPermissions, grantedMode, resultTo, resultWho,
2143 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002144 return res;
2145 }
2146
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002147 public final int startActivityWithConfig(IApplicationThread caller,
2148 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2149 int grantedMode, IBinder resultTo,
2150 String resultWho, int requestCode, boolean onlyIfNeeded,
2151 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002152 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002153 grantedUriPermissions, grantedMode, resultTo, resultWho,
2154 requestCode, onlyIfNeeded, debug, null, config);
2155 }
2156
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002157 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002158 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002159 IBinder resultTo, String resultWho, int requestCode,
2160 int flagsMask, int flagsValues) {
2161 // Refuse possible leaked file descriptors
2162 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2163 throw new IllegalArgumentException("File descriptors passed in Intent");
2164 }
2165
2166 IIntentSender sender = intent.getTarget();
2167 if (!(sender instanceof PendingIntentRecord)) {
2168 throw new IllegalArgumentException("Bad PendingIntent object");
2169 }
2170
2171 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002172
2173 synchronized (this) {
2174 // If this is coming from the currently resumed activity, it is
2175 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002176 if (mMainStack.mResumedActivity != null
2177 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002178 Binder.getCallingUid()) {
2179 mAppSwitchesAllowedTime = 0;
2180 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002181 }
2182
2183 return pir.sendInner(0, fillInIntent, resolvedType,
2184 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2185 }
2186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 public boolean startNextMatchingActivity(IBinder callingActivity,
2188 Intent intent) {
2189 // Refuse possible leaked file descriptors
2190 if (intent != null && intent.hasFileDescriptors() == true) {
2191 throw new IllegalArgumentException("File descriptors passed in Intent");
2192 }
2193
2194 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 if (index < 0) {
2197 return false;
2198 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002199 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 if (r.app == null || r.app.thread == null) {
2201 // The caller is not running... d'oh!
2202 return false;
2203 }
2204 intent = new Intent(intent);
2205 // The caller is not allowed to change the data.
2206 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2207 // And we are resetting to find the next component...
2208 intent.setComponent(null);
2209
2210 ActivityInfo aInfo = null;
2211 try {
2212 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002213 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002215 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216
2217 // Look for the original activity in the list...
2218 final int N = resolves != null ? resolves.size() : 0;
2219 for (int i=0; i<N; i++) {
2220 ResolveInfo rInfo = resolves.get(i);
2221 if (rInfo.activityInfo.packageName.equals(r.packageName)
2222 && rInfo.activityInfo.name.equals(r.info.name)) {
2223 // We found the current one... the next matching is
2224 // after it.
2225 i++;
2226 if (i<N) {
2227 aInfo = resolves.get(i).activityInfo;
2228 }
2229 break;
2230 }
2231 }
2232 } catch (RemoteException e) {
2233 }
2234
2235 if (aInfo == null) {
2236 // Nobody who is next!
2237 return false;
2238 }
2239
2240 intent.setComponent(new ComponentName(
2241 aInfo.applicationInfo.packageName, aInfo.name));
2242 intent.setFlags(intent.getFlags()&~(
2243 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2244 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2245 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2246 Intent.FLAG_ACTIVITY_NEW_TASK));
2247
2248 // Okay now we need to start the new activity, replacing the
2249 // currently running activity. This is a little tricky because
2250 // we want to start the new one as if the current one is finished,
2251 // but not finish the current one first so that there is no flicker.
2252 // And thus...
2253 final boolean wasFinishing = r.finishing;
2254 r.finishing = true;
2255
2256 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002257 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 final String resultWho = r.resultWho;
2259 final int requestCode = r.requestCode;
2260 r.resultTo = null;
2261 if (resultTo != null) {
2262 resultTo.removeResultsLocked(r, resultWho, requestCode);
2263 }
2264
2265 final long origId = Binder.clearCallingIdentity();
2266 // XXX we are not dealing with propagating grantedUriPermissions...
2267 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002268 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002270 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 Binder.restoreCallingIdentity(origId);
2272
2273 r.finishing = wasFinishing;
2274 if (res != START_SUCCESS) {
2275 return false;
2276 }
2277 return true;
2278 }
2279 }
2280
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002281 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 Intent intent, String resolvedType, IBinder resultTo,
2283 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002284
2285 // This is so super not safe, that only the system (or okay root)
2286 // can do it.
2287 final int callingUid = Binder.getCallingUid();
2288 if (callingUid != 0 && callingUid != Process.myUid()) {
2289 throw new SecurityException(
2290 "startActivityInPackage only available to the system");
2291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002293 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2294 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2295 }
2296
2297 public final int startActivities(IApplicationThread caller,
2298 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2299 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2300 }
2301
2302 public final int startActivitiesInPackage(int uid,
2303 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2304
2305 // This is so super not safe, that only the system (or okay root)
2306 // can do it.
2307 final int callingUid = Binder.getCallingUid();
2308 if (callingUid != 0 && callingUid != Process.myUid()) {
2309 throw new SecurityException(
2310 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 }
2312
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002313 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 }
2315
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002316 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002318 // Quick case: check if the top-most recent task is the same.
2319 if (N > 0 && mRecentTasks.get(0) == task) {
2320 return;
2321 }
2322 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 for (int i=0; i<N; i++) {
2324 TaskRecord tr = mRecentTasks.get(i);
2325 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2326 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2327 mRecentTasks.remove(i);
2328 i--;
2329 N--;
2330 if (task.intent == null) {
2331 // If the new recent task we are adding is not fully
2332 // specified, then replace it with the existing recent task.
2333 task = tr;
2334 }
2335 }
2336 }
2337 if (N >= MAX_RECENT_TASKS) {
2338 mRecentTasks.remove(N-1);
2339 }
2340 mRecentTasks.add(0, task);
2341 }
2342
2343 public void setRequestedOrientation(IBinder token,
2344 int requestedOrientation) {
2345 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 if (index < 0) {
2348 return;
2349 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002350 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 final long origId = Binder.clearCallingIdentity();
2352 mWindowManager.setAppOrientation(r, requestedOrientation);
2353 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002354 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 r.mayFreezeScreenLocked(r.app) ? r : null);
2356 if (config != null) {
2357 r.frozenBeforeDestroy = true;
2358 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002359 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
2361 }
2362 Binder.restoreCallingIdentity(origId);
2363 }
2364 }
2365
2366 public int getRequestedOrientation(IBinder token) {
2367 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 if (index < 0) {
2370 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2371 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002372 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 return mWindowManager.getAppOrientation(r);
2374 }
2375 }
2376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 /**
2378 * This is the internal entry point for handling Activity.finish().
2379 *
2380 * @param token The Binder token referencing the Activity we want to finish.
2381 * @param resultCode Result code, if any, from this Activity.
2382 * @param resultData Result data (Intent), if any, from this Activity.
2383 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002384 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 */
2386 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2387 // Refuse possible leaked file descriptors
2388 if (resultData != null && resultData.hasFileDescriptors() == true) {
2389 throw new IllegalArgumentException("File descriptors passed in Intent");
2390 }
2391
2392 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002393 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002395 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 if (next != null) {
2397 // ask watcher if this is allowed
2398 boolean resumeOK = true;
2399 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002400 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002402 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 }
2404
2405 if (!resumeOK) {
2406 return false;
2407 }
2408 }
2409 }
2410 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002411 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 resultData, "app-request");
2413 Binder.restoreCallingIdentity(origId);
2414 return res;
2415 }
2416 }
2417
Dianne Hackborn860755f2010-06-03 18:47:52 -07002418 public final void finishHeavyWeightApp() {
2419 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2420 != PackageManager.PERMISSION_GRANTED) {
2421 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2422 + Binder.getCallingPid()
2423 + ", uid=" + Binder.getCallingUid()
2424 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2425 Slog.w(TAG, msg);
2426 throw new SecurityException(msg);
2427 }
2428
2429 synchronized(this) {
2430 if (mHeavyWeightProcess == null) {
2431 return;
2432 }
2433
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002434 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002435 mHeavyWeightProcess.activities);
2436 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002437 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002440 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002441 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002442 null, "finish-heavy");
2443 }
2444 }
2445 }
2446
2447 mHeavyWeightProcess = null;
2448 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2449 }
2450 }
2451
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002452 public void crashApplication(int uid, int initialPid, String packageName,
2453 String message) {
2454 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2455 != PackageManager.PERMISSION_GRANTED) {
2456 String msg = "Permission Denial: crashApplication() from pid="
2457 + Binder.getCallingPid()
2458 + ", uid=" + Binder.getCallingUid()
2459 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2460 Slog.w(TAG, msg);
2461 throw new SecurityException(msg);
2462 }
2463
2464 synchronized(this) {
2465 ProcessRecord proc = null;
2466
2467 // Figure out which process to kill. We don't trust that initialPid
2468 // still has any relation to current pids, so must scan through the
2469 // list.
2470 synchronized (mPidsSelfLocked) {
2471 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2472 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2473 if (p.info.uid != uid) {
2474 continue;
2475 }
2476 if (p.pid == initialPid) {
2477 proc = p;
2478 break;
2479 }
2480 for (String str : p.pkgList) {
2481 if (str.equals(packageName)) {
2482 proc = p;
2483 }
2484 }
2485 }
2486 }
2487
2488 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002489 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002490 + " initialPid=" + initialPid
2491 + " packageName=" + packageName);
2492 return;
2493 }
2494
2495 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002496 if (proc.pid == Process.myPid()) {
2497 Log.w(TAG, "crashApplication: trying to crash self!");
2498 return;
2499 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002500 long ident = Binder.clearCallingIdentity();
2501 try {
2502 proc.thread.scheduleCrash(message);
2503 } catch (RemoteException e) {
2504 }
2505 Binder.restoreCallingIdentity(ident);
2506 }
2507 }
2508 }
2509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 public final void finishSubActivity(IBinder token, String resultWho,
2511 int requestCode) {
2512 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 if (index < 0) {
2515 return;
2516 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002517 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518
2519 final long origId = Binder.clearCallingIdentity();
2520
2521 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2523 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 if (r.resultTo == self && r.requestCode == requestCode) {
2525 if ((r.resultWho == null && resultWho == null) ||
2526 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 Activity.RESULT_CANCELED, null, "request-sub");
2529 }
2530 }
2531 }
2532
2533 Binder.restoreCallingIdentity(origId);
2534 }
2535 }
2536
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002537 public boolean willActivityBeVisible(IBinder token) {
2538 synchronized(this) {
2539 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2541 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002542 if (r == token) {
2543 return true;
2544 }
2545 if (r.fullscreen && !r.finishing) {
2546 return false;
2547 }
2548 }
2549 return true;
2550 }
2551 }
2552
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 public void overridePendingTransition(IBinder token, String packageName,
2554 int enterAnim, int exitAnim) {
2555 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002556 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002557 if (index < 0) {
2558 return;
2559 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002561
2562 final long origId = Binder.clearCallingIdentity();
2563
2564 if (self.state == ActivityState.RESUMED
2565 || self.state == ActivityState.PAUSING) {
2566 mWindowManager.overridePendingAppTransition(packageName,
2567 enterAnim, exitAnim);
2568 }
2569
2570 Binder.restoreCallingIdentity(origId);
2571 }
2572 }
2573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 * Main function for removing an existing process from the activity manager
2576 * as a result of that process going away. Clears out all connections
2577 * to the process.
2578 */
2579 private final void handleAppDiedLocked(ProcessRecord app,
2580 boolean restarting) {
2581 cleanUpApplicationRecordLocked(app, restarting, -1);
2582 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002583 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 }
2585
2586 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002587 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2588 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2589 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002591 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2592 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
2594
2595 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002596 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597
2598 boolean atTop = true;
2599 boolean hasVisibleActivities = false;
2600
2601 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002602 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002603 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 TAG, "Removing app " + app + " from history with " + i + " entries");
2605 while (i > 0) {
2606 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002607 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002608 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2610 if (r.app == app) {
2611 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 TAG, "Removing this entry! frozen=" + r.haveState
2614 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002615 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002616 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617
2618 r.inHistory = false;
2619 mWindowManager.removeAppToken(r);
2620 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002623 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624
2625 } else {
2626 // We have the current state for this activity, so
2627 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002628 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 TAG, "Keeping entry, setting app to null");
2630 if (r.visible) {
2631 hasVisibleActivities = true;
2632 }
2633 r.app = null;
2634 r.nowVisible = false;
2635 if (!r.haveState) {
2636 r.icicle = null;
2637 }
2638 }
2639
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002640 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 r.state = ActivityState.STOPPED;
2642 }
2643 atTop = false;
2644 }
2645
2646 app.activities.clear();
2647
2648 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002649 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 + " running instrumentation " + app.instrumentationClass);
2651 Bundle info = new Bundle();
2652 info.putString("shortMsg", "Process crashed.");
2653 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2654 }
2655
2656 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002657 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 // If there was nothing to resume, and we are not already
2659 // restarting this process, but there is a visible activity that
2660 // is hosted by the process... then make sure all visible
2661 // activities are running, taking care of restarting this
2662 // process.
2663 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002664 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666 }
2667 }
2668 }
2669
2670 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2671 IBinder threadBinder = thread.asBinder();
2672
2673 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002674 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2675 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2677 return i;
2678 }
2679 }
2680 return -1;
2681 }
2682
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002683 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 IApplicationThread thread) {
2685 if (thread == null) {
2686 return null;
2687 }
2688
2689 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002690 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
2692
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002693 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 IApplicationThread thread) {
2695
2696 mProcDeaths[0]++;
2697
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002698 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2699 synchronized (stats) {
2700 stats.noteProcessDiedLocked(app.info.uid, pid);
2701 }
2702
Magnus Edlund7bb25812010-02-24 15:45:06 +01002703 // Clean up already done if the process has been re-started.
2704 if (app.pid == pid && app.thread != null &&
2705 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002706 if (!app.killedBackground) {
2707 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2708 + ") has died.");
2709 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002710 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002711 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 TAG, "Dying app: " + app + ", pid: " + pid
2713 + ", thread: " + thread.asBinder());
2714 boolean doLowMem = app.instrumentationClass == null;
2715 handleAppDiedLocked(app, false);
2716
2717 if (doLowMem) {
2718 // If there are no longer any background processes running,
2719 // and the app that died was not running instrumentation,
2720 // then tell everyone we are now low on memory.
2721 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002722 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2723 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2725 haveBg = true;
2726 break;
2727 }
2728 }
2729
2730 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002731 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002732 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002733 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002734 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2735 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002736 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002737 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2738 // The low memory report is overriding any current
2739 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002740 // heavy/important/visible/foreground processes first.
2741 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002742 rec.lastRequestedGc = 0;
2743 } else {
2744 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002746 rec.reportLowMemory = true;
2747 rec.lastLowMemory = now;
2748 mProcessesToGc.remove(rec);
2749 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 }
2751 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002752 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 }
2754 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002755 } else if (app.pid != pid) {
2756 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002757 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002758 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002759 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002760 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002761 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 + thread.asBinder());
2763 }
2764 }
2765
Dan Egnor42471dd2010-01-07 17:25:22 -08002766 /**
2767 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002768 * @param clearTraces causes the dump file to be erased prior to the new
2769 * traces being written, if true; when false, the new traces will be
2770 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002771 * @param firstPids of dalvik VM processes to dump stack traces for first
2772 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002773 * @return file containing stack traces, or null if no dump file is configured
2774 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002775 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2776 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002777 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2778 if (tracesPath == null || tracesPath.length() == 0) {
2779 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002780 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002781
2782 File tracesFile = new File(tracesPath);
2783 try {
2784 File tracesDir = tracesFile.getParentFile();
2785 if (!tracesDir.exists()) tracesFile.mkdirs();
2786 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2787
Christopher Tate6ee412d2010-05-28 12:01:56 -07002788 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002789 tracesFile.createNewFile();
2790 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2791 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002792 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002793 return null;
2794 }
2795
2796 // Use a FileObserver to detect when traces finish writing.
2797 // The order of traces is considered important to maintain for legibility.
2798 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2799 public synchronized void onEvent(int event, String path) { notify(); }
2800 };
2801
2802 try {
2803 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002804
2805 // First collect all of the stacks of the most important pids.
2806 try {
2807 int num = firstPids.size();
2808 for (int i = 0; i < num; i++) {
2809 synchronized (observer) {
2810 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2811 observer.wait(200); // Wait for write-close, give up after 200msec
2812 }
2813 }
2814 } catch (InterruptedException e) {
2815 Log.wtf(TAG, e);
2816 }
2817
2818 // Next measure CPU usage.
2819 if (processStats != null) {
2820 processStats.init();
2821 System.gc();
2822 processStats.update();
2823 try {
2824 synchronized (processStats) {
2825 processStats.wait(500); // measure over 1/2 second.
2826 }
2827 } catch (InterruptedException e) {
2828 }
2829 processStats.update();
2830
2831 // We'll take the stack crawls of just the top apps using CPU.
2832 final int N = processStats.countWorkingStats();
2833 int numProcs = 0;
2834 for (int i=0; i<N && numProcs<5; i++) {
2835 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2836 if (lastPids.indexOfKey(stats.pid) >= 0) {
2837 numProcs++;
2838 try {
2839 synchronized (observer) {
2840 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2841 observer.wait(200); // Wait for write-close, give up after 200msec
2842 }
2843 } catch (InterruptedException e) {
2844 Log.wtf(TAG, e);
2845 }
2846
2847 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002848 }
2849 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002850
2851 return tracesFile;
2852
Dan Egnor42471dd2010-01-07 17:25:22 -08002853 } finally {
2854 observer.stopWatching();
2855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
2857
Jeff Brown4d94a762010-09-23 11:33:28 -07002858 private final class AppNotResponding implements Runnable {
2859 private final ProcessRecord mApp;
2860 private final String mAnnotation;
2861
2862 public AppNotResponding(ProcessRecord app, String annotation) {
2863 mApp = app;
2864 mAnnotation = annotation;
2865 }
2866
2867 @Override
2868 public void run() {
2869 appNotResponding(mApp, null, null, mAnnotation);
2870 }
2871 }
2872
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002873 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2874 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002875 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2876 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2877
Dianne Hackborn287952c2010-09-22 22:34:31 -07002878 if (mController != null) {
2879 try {
2880 // 0 == continue, -1 = kill process immediately
2881 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2882 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2883 } catch (RemoteException e) {
2884 mController = null;
2885 }
2886 }
2887
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002888 long anrTime = SystemClock.uptimeMillis();
2889 if (MONITOR_CPU_USAGE) {
2890 updateCpuStatsNow();
2891 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002892
2893 synchronized (this) {
2894 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2895 if (mShuttingDown) {
2896 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2897 return;
2898 } else if (app.notResponding) {
2899 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2900 return;
2901 } else if (app.crashing) {
2902 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2903 return;
2904 }
2905
2906 // In case we come through here for the same app before completing
2907 // this one, mark as anring now so we will bail out.
2908 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002909
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002910 // Log the ANR to the event log.
2911 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2912 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002913
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002914 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002915 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002916
2917 int parentPid = app.pid;
2918 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002919 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002920
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002921 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002922
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002923 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2924 ProcessRecord r = mLruProcesses.get(i);
2925 if (r != null && r.thread != null) {
2926 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002927 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2928 if (r.persistent) {
2929 firstPids.add(pid);
2930 } else {
2931 lastPids.put(pid, Boolean.TRUE);
2932 }
2933 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 }
2936 }
2937
Dan Egnor42471dd2010-01-07 17:25:22 -08002938 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002939 StringBuilder info = mStringBuilder;
2940 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002941 info.append("ANR in ").append(app.processName);
2942 if (activity != null && activity.shortComponentName != null) {
2943 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002944 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002945 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002947 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002949 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002950 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952
Dianne Hackborn287952c2010-09-22 22:34:31 -07002953 final ProcessStats processStats = new ProcessStats(true);
2954
2955 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2956
Dan Egnor42471dd2010-01-07 17:25:22 -08002957 String cpuInfo = null;
2958 if (MONITOR_CPU_USAGE) {
2959 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002960 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002961 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002962 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002963 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002964 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 }
2966
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002967 info.append(processStats.printCurrentState(anrTime));
2968
Joe Onorato8a9b2202010-02-26 18:56:32 -08002969 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002970 if (tracesFile == null) {
2971 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2972 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2973 }
2974
2975 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2976
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002977 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002979 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2980 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002982 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2983 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 }
2985 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002986 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 }
2989
Dan Egnor42471dd2010-01-07 17:25:22 -08002990 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2991 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2992 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002993
2994 synchronized (this) {
2995 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2996 Process.killProcess(app.pid);
2997 return;
2998 }
2999
3000 // Set the app's notResponding state, and look up the errorReportReceiver
3001 makeAppNotRespondingLocked(app,
3002 activity != null ? activity.shortComponentName : null,
3003 annotation != null ? "ANR " + annotation : "ANR",
3004 info.toString());
3005
3006 // Bring up the infamous App Not Responding dialog
3007 Message msg = Message.obtain();
3008 HashMap map = new HashMap();
3009 msg.what = SHOW_NOT_RESPONDING_MSG;
3010 msg.obj = map;
3011 map.put("app", app);
3012 if (activity != null) {
3013 map.put("activity", activity);
3014 }
3015
3016 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 }
3019
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003020 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3021 if (!mLaunchWarningShown) {
3022 mLaunchWarningShown = true;
3023 mHandler.post(new Runnable() {
3024 @Override
3025 public void run() {
3026 synchronized (ActivityManagerService.this) {
3027 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3028 d.show();
3029 mHandler.postDelayed(new Runnable() {
3030 @Override
3031 public void run() {
3032 synchronized (ActivityManagerService.this) {
3033 d.dismiss();
3034 mLaunchWarningShown = false;
3035 }
3036 }
3037 }, 4000);
3038 }
3039 }
3040 });
3041 }
3042 }
3043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 public boolean clearApplicationUserData(final String packageName,
3045 final IPackageDataObserver observer) {
3046 int uid = Binder.getCallingUid();
3047 int pid = Binder.getCallingPid();
3048 long callingId = Binder.clearCallingIdentity();
3049 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003050 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 int pkgUid = -1;
3052 synchronized(this) {
3053 try {
3054 pkgUid = pm.getPackageUid(packageName);
3055 } catch (RemoteException e) {
3056 }
3057 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003058 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 return false;
3060 }
3061 if (uid == pkgUid || checkComponentPermission(
3062 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003063 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003065 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 } else {
3067 throw new SecurityException(pid+" does not have permission:"+
3068 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3069 "for process:"+packageName);
3070 }
3071 }
3072
3073 try {
3074 //clear application user data
3075 pm.clearApplicationUserData(packageName, observer);
3076 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3077 Uri.fromParts("package", packageName, null));
3078 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003079 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3080 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 } catch (RemoteException e) {
3082 }
3083 } finally {
3084 Binder.restoreCallingIdentity(callingId);
3085 }
3086 return true;
3087 }
3088
Dianne Hackborn03abb812010-01-04 18:43:19 -08003089 public void killBackgroundProcesses(final String packageName) {
3090 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3091 != PackageManager.PERMISSION_GRANTED &&
3092 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3093 != PackageManager.PERMISSION_GRANTED) {
3094 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 + Binder.getCallingPid()
3096 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003097 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003098 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 throw new SecurityException(msg);
3100 }
3101
3102 long callingId = Binder.clearCallingIdentity();
3103 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003104 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 int pkgUid = -1;
3106 synchronized(this) {
3107 try {
3108 pkgUid = pm.getPackageUid(packageName);
3109 } catch (RemoteException e) {
3110 }
3111 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003112 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 return;
3114 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003115 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003116 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003117 }
3118 } finally {
3119 Binder.restoreCallingIdentity(callingId);
3120 }
3121 }
3122
3123 public void forceStopPackage(final String packageName) {
3124 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3125 != PackageManager.PERMISSION_GRANTED) {
3126 String msg = "Permission Denial: forceStopPackage() from pid="
3127 + Binder.getCallingPid()
3128 + ", uid=" + Binder.getCallingUid()
3129 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003130 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003131 throw new SecurityException(msg);
3132 }
3133
3134 long callingId = Binder.clearCallingIdentity();
3135 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003136 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003137 int pkgUid = -1;
3138 synchronized(this) {
3139 try {
3140 pkgUid = pm.getPackageUid(packageName);
3141 } catch (RemoteException e) {
3142 }
3143 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003144 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003145 return;
3146 }
3147 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 }
3149 } finally {
3150 Binder.restoreCallingIdentity(callingId);
3151 }
3152 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003153
3154 /*
3155 * The pkg name and uid have to be specified.
3156 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3157 */
3158 public void killApplicationWithUid(String pkg, int uid) {
3159 if (pkg == null) {
3160 return;
3161 }
3162 // Make sure the uid is valid.
3163 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003164 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003165 return;
3166 }
3167 int callerUid = Binder.getCallingUid();
3168 // Only the system server can kill an application
3169 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003170 // Post an aysnc message to kill the application
3171 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3172 msg.arg1 = uid;
3173 msg.arg2 = 0;
3174 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003175 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003176 } else {
3177 throw new SecurityException(callerUid + " cannot kill pkg: " +
3178 pkg);
3179 }
3180 }
3181
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003182 public void closeSystemDialogs(String reason) {
3183 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003184 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003185 if (reason != null) {
3186 intent.putExtra("reason", reason);
3187 }
3188
3189 final int uid = Binder.getCallingUid();
3190 final long origId = Binder.clearCallingIdentity();
3191 synchronized (this) {
3192 int i = mWatchers.beginBroadcast();
3193 while (i > 0) {
3194 i--;
3195 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3196 if (w != null) {
3197 try {
3198 w.closingSystemDialogs(reason);
3199 } catch (RemoteException e) {
3200 }
3201 }
3202 }
3203 mWatchers.finishBroadcast();
3204
Dianne Hackbornffa42482009-09-23 22:20:11 -07003205 mWindowManager.closeSystemDialogs(reason);
3206
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003207 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3208 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003209 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003210 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003211 Activity.RESULT_CANCELED, null, "close-sys");
3212 }
3213 }
3214
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003215 broadcastIntentLocked(null, null, intent, null,
3216 null, 0, null, null, null, false, false, -1, uid);
3217 }
3218 Binder.restoreCallingIdentity(origId);
3219 }
3220
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003221 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003222 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003223 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3224 for (int i=pids.length-1; i>=0; i--) {
3225 infos[i] = new Debug.MemoryInfo();
3226 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003227 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003228 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003229 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003230
3231 public void killApplicationProcess(String processName, int uid) {
3232 if (processName == null) {
3233 return;
3234 }
3235
3236 int callerUid = Binder.getCallingUid();
3237 // Only the system server can kill an application
3238 if (callerUid == Process.SYSTEM_UID) {
3239 synchronized (this) {
3240 ProcessRecord app = getProcessRecordLocked(processName, uid);
3241 if (app != null) {
3242 try {
3243 app.thread.scheduleSuicide();
3244 } catch (RemoteException e) {
3245 // If the other end already died, then our work here is done.
3246 }
3247 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003248 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003249 + processName + " / " + uid);
3250 }
3251 }
3252 } else {
3253 throw new SecurityException(callerUid + " cannot kill app process: " +
3254 processName);
3255 }
3256 }
3257
Dianne Hackborn03abb812010-01-04 18:43:19 -08003258 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003259 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3261 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003262 if (!mProcessesReady) {
3263 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 intent.putExtra(Intent.EXTRA_UID, uid);
3266 broadcastIntentLocked(null, null, intent,
3267 null, null, 0, null, null, null,
3268 false, false, MY_PID, Process.SYSTEM_UID);
3269 }
3270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003271 private final boolean killPackageProcessesLocked(String packageName, int uid,
3272 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003273 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274
Dianne Hackborn03abb812010-01-04 18:43:19 -08003275 // Remove all processes this package may have touched: all with the
3276 // same UID (except for the system or root user), and all whose name
3277 // matches the package name.
3278 final String procNamePrefix = packageName + ":";
3279 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3280 final int NA = apps.size();
3281 for (int ia=0; ia<NA; ia++) {
3282 ProcessRecord app = apps.valueAt(ia);
3283 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003284 if (doit) {
3285 procs.add(app);
3286 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003287 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3288 || app.processName.equals(packageName)
3289 || app.processName.startsWith(procNamePrefix)) {
3290 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003291 if (!doit) {
3292 return true;
3293 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003294 app.removed = true;
3295 procs.add(app);
3296 }
3297 }
3298 }
3299 }
3300
3301 int N = procs.size();
3302 for (int i=0; i<N; i++) {
3303 removeProcessLocked(procs.get(i), callerWillRestart);
3304 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003305 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003306 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003307
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003308 private final boolean forceStopPackageLocked(String name, int uid,
3309 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 int i, N;
3311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 if (uid < 0) {
3313 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003314 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 } catch (RemoteException e) {
3316 }
3317 }
3318
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003319 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003320 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003321
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003322 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3323 while (badApps.hasNext()) {
3324 SparseArray<Long> ba = badApps.next();
3325 if (ba.get(uid) != null) {
3326 badApps.remove();
3327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 }
3329 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003330
3331 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3332 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003334 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3335 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003337 if (!doit) {
3338 return true;
3339 }
3340 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003341 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 if (r.app != null) {
3343 r.app.removed = true;
3344 }
3345 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003346 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348 }
3349
3350 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3351 for (ServiceRecord service : mServices.values()) {
3352 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003353 if (!doit) {
3354 return true;
3355 }
3356 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003357 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 if (service.app != null) {
3359 service.app.removed = true;
3360 }
3361 service.app = null;
3362 services.add(service);
3363 }
3364 }
3365
3366 N = services.size();
3367 for (i=0; i<N; i++) {
3368 bringDownServiceLocked(services.get(i), true);
3369 }
3370
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003371 if (doit) {
3372 if (purgeCache) {
3373 AttributeCache ac = AttributeCache.instance();
3374 if (ac != null) {
3375 ac.removePackage(name);
3376 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003377 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003378 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003379 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003380
3381 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 }
3383
3384 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3385 final String name = app.processName;
3386 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003387 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 TAG, "Force removing process " + app + " (" + name
3389 + "/" + uid + ")");
3390
3391 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003392 if (mHeavyWeightProcess == app) {
3393 mHeavyWeightProcess = null;
3394 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 boolean needRestart = false;
3397 if (app.pid > 0 && app.pid != MY_PID) {
3398 int pid = app.pid;
3399 synchronized (mPidsSelfLocked) {
3400 mPidsSelfLocked.remove(pid);
3401 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3402 }
3403 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003404 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 Process.killProcess(pid);
3406
3407 if (app.persistent) {
3408 if (!callerWillRestart) {
3409 addAppLocked(app.info);
3410 } else {
3411 needRestart = true;
3412 }
3413 }
3414 } else {
3415 mRemovedProcesses.add(app);
3416 }
3417
3418 return needRestart;
3419 }
3420
3421 private final void processStartTimedOutLocked(ProcessRecord app) {
3422 final int pid = app.pid;
3423 boolean gone = false;
3424 synchronized (mPidsSelfLocked) {
3425 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3426 if (knownApp != null && knownApp.thread == null) {
3427 mPidsSelfLocked.remove(pid);
3428 gone = true;
3429 }
3430 }
3431
3432 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003434 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003435 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003437 if (mHeavyWeightProcess == app) {
3438 mHeavyWeightProcess = null;
3439 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3440 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003441 // Take care of any launching providers waiting for this process.
3442 checkAppInLaunchingProvidersLocked(app, true);
3443 // Take care of any services that are waiting for the process.
3444 for (int i=0; i<mPendingServices.size(); i++) {
3445 ServiceRecord sr = mPendingServices.get(i);
3446 if (app.info.uid == sr.appInfo.uid
3447 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003448 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003449 mPendingServices.remove(i);
3450 i--;
3451 bringDownServiceLocked(sr, true);
3452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003454 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003455 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003456 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003457 try {
3458 IBackupManager bm = IBackupManager.Stub.asInterface(
3459 ServiceManager.getService(Context.BACKUP_SERVICE));
3460 bm.agentDisconnected(app.info.packageName);
3461 } catch (RemoteException e) {
3462 // Can't happen; the backup manager is local
3463 }
3464 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003465 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003466 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003467 mPendingBroadcast.state = BroadcastRecord.IDLE;
3468 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003469 mPendingBroadcast = null;
3470 scheduleBroadcastsLocked();
3471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 }
3475 }
3476
3477 private final boolean attachApplicationLocked(IApplicationThread thread,
3478 int pid) {
3479
3480 // Find the application record that is being attached... either via
3481 // the pid if we are running in multiple processes, or just pull the
3482 // next app record if we are emulating process with anonymous threads.
3483 ProcessRecord app;
3484 if (pid != MY_PID && pid >= 0) {
3485 synchronized (mPidsSelfLocked) {
3486 app = mPidsSelfLocked.get(pid);
3487 }
3488 } else if (mStartingProcesses.size() > 0) {
3489 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003490 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 } else {
3492 app = null;
3493 }
3494
3495 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003498 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 if (pid > 0 && pid != MY_PID) {
3500 Process.killProcess(pid);
3501 } else {
3502 try {
3503 thread.scheduleExit();
3504 } catch (Exception e) {
3505 // Ignore exceptions.
3506 }
3507 }
3508 return false;
3509 }
3510
3511 // If this application record is still attached to a previous
3512 // process, clean it up now.
3513 if (app.thread != null) {
3514 handleAppDiedLocked(app, true);
3515 }
3516
3517 // Tell the process all about itself.
3518
Joe Onorato8a9b2202010-02-26 18:56:32 -08003519 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 TAG, "Binding process pid " + pid + " to record " + app);
3521
3522 String processName = app.processName;
3523 try {
3524 thread.asBinder().linkToDeath(new AppDeathRecipient(
3525 app, pid, thread), 0);
3526 } catch (RemoteException e) {
3527 app.resetPackageList();
3528 startProcessLocked(app, "link fail", processName);
3529 return false;
3530 }
3531
Doug Zongker2bec3d42009-12-04 12:52:44 -08003532 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533
3534 app.thread = thread;
3535 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003536 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3537 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 app.forcingToForeground = null;
3539 app.foregroundServices = false;
3540 app.debugging = false;
3541
3542 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3543
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003544 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003545 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003547 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003548 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003549 }
3550
Joe Onorato8a9b2202010-02-26 18:56:32 -08003551 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 TAG, "New app record " + app
3553 + " thread=" + thread.asBinder() + " pid=" + pid);
3554 try {
3555 int testMode = IApplicationThread.DEBUG_OFF;
3556 if (mDebugApp != null && mDebugApp.equals(processName)) {
3557 testMode = mWaitForDebugger
3558 ? IApplicationThread.DEBUG_WAIT
3559 : IApplicationThread.DEBUG_ON;
3560 app.debugging = true;
3561 if (mDebugTransient) {
3562 mDebugApp = mOrigDebugApp;
3563 mWaitForDebugger = mOrigWaitForDebugger;
3564 }
3565 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003566
Christopher Tate181fafa2009-05-14 11:12:14 -07003567 // If the app is being launched for restore or full backup, set it up specially
3568 boolean isRestrictedBackupMode = false;
3569 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3570 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3571 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3572 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003573
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003574 ensurePackageDexOpt(app.instrumentationInfo != null
3575 ? app.instrumentationInfo.packageName
3576 : app.info.packageName);
3577 if (app.instrumentationClass != null) {
3578 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003579 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003580 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003581 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003582 thread.bindApplication(processName, app.instrumentationInfo != null
3583 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 app.instrumentationClass, app.instrumentationProfileFile,
3585 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003586 isRestrictedBackupMode || !normalMode,
3587 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003588 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003589 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 } catch (Exception e) {
3591 // todo: Yikes! What should we do? For now we will try to
3592 // start another process, but that could easily get us in
3593 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003594 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595
3596 app.resetPackageList();
3597 startProcessLocked(app, "bind fail", processName);
3598 return false;
3599 }
3600
3601 // Remove this record from the list of starting applications.
3602 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003603 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3604 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 mProcessesOnHold.remove(app);
3606
3607 boolean badApp = false;
3608 boolean didSomething = false;
3609
3610 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003611 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003612 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3614 && processName.equals(hr.processName)) {
3615 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003616 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 didSomething = true;
3618 }
3619 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003620 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 + hr.intent.getComponent().flattenToShortString(), e);
3622 badApp = true;
3623 }
3624 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003625 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 }
3627 }
3628
3629 // Find any services that should be running in this process...
3630 if (!badApp && mPendingServices.size() > 0) {
3631 ServiceRecord sr = null;
3632 try {
3633 for (int i=0; i<mPendingServices.size(); i++) {
3634 sr = mPendingServices.get(i);
3635 if (app.info.uid != sr.appInfo.uid
3636 || !processName.equals(sr.processName)) {
3637 continue;
3638 }
3639
3640 mPendingServices.remove(i);
3641 i--;
3642 realStartServiceLocked(sr, app);
3643 didSomething = true;
3644 }
3645 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003646 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 + sr.shortName, e);
3648 badApp = true;
3649 }
3650 }
3651
3652 // Check if the next broadcast receiver is in this process...
3653 BroadcastRecord br = mPendingBroadcast;
3654 if (!badApp && br != null && br.curApp == app) {
3655 try {
3656 mPendingBroadcast = null;
3657 processCurBroadcastLocked(br, app);
3658 didSomething = true;
3659 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003660 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 + br.curComponent.flattenToShortString(), e);
3662 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003663 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3665 br.resultExtras, br.resultAbort, true);
3666 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003667 // We need to reset the state if we fails to start the receiver.
3668 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 }
3670 }
3671
Christopher Tate181fafa2009-05-14 11:12:14 -07003672 // Check whether the next backup agent is in this process...
3673 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003674 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003675 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003676 try {
3677 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3678 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003679 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003680 e.printStackTrace();
3681 }
3682 }
3683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 if (badApp) {
3685 // todo: Also need to kill application to deal with all
3686 // kinds of exceptions.
3687 handleAppDiedLocked(app, false);
3688 return false;
3689 }
3690
3691 if (!didSomething) {
3692 updateOomAdjLocked();
3693 }
3694
3695 return true;
3696 }
3697
3698 public final void attachApplication(IApplicationThread thread) {
3699 synchronized (this) {
3700 int callingPid = Binder.getCallingPid();
3701 final long origId = Binder.clearCallingIdentity();
3702 attachApplicationLocked(thread, callingPid);
3703 Binder.restoreCallingIdentity(origId);
3704 }
3705 }
3706
Dianne Hackborne88846e2009-09-30 21:34:25 -07003707 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003709 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 Binder.restoreCallingIdentity(origId);
3711 }
3712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003714 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003715 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 mWindowManager.enableScreenAfterBoot();
3717 }
3718
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003719 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003720 IntentFilter pkgFilter = new IntentFilter();
3721 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3722 pkgFilter.addDataScheme("package");
3723 mContext.registerReceiver(new BroadcastReceiver() {
3724 @Override
3725 public void onReceive(Context context, Intent intent) {
3726 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3727 if (pkgs != null) {
3728 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003729 synchronized (ActivityManagerService.this) {
3730 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3731 setResultCode(Activity.RESULT_OK);
3732 return;
3733 }
3734 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003735 }
3736 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003737 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003738 }, pkgFilter);
3739
3740 synchronized (this) {
3741 // Ensure that any processes we had put on hold are now started
3742 // up.
3743 final int NP = mProcessesOnHold.size();
3744 if (NP > 0) {
3745 ArrayList<ProcessRecord> procs =
3746 new ArrayList<ProcessRecord>(mProcessesOnHold);
3747 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003748 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3749 + procs.get(ip));
3750 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003751 }
3752 }
3753
3754 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003755 // Start looking for apps that are abusing wake locks.
3756 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003757 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003758 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003759 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003760 broadcastIntentLocked(null, null,
3761 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3762 null, null, 0, null, null,
3763 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3764 false, false, MY_PID, Process.SYSTEM_UID);
3765 }
3766 }
3767 }
3768
3769 final void ensureBootCompleted() {
3770 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003771 boolean enableScreen;
3772 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003773 booting = mBooting;
3774 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003775 enableScreen = !mBooted;
3776 mBooted = true;
3777 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003778
3779 if (booting) {
3780 finishBooting();
3781 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003782
3783 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003784 enableScreenAfterBoot();
3785 }
3786 }
3787
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003788 public final void activityPaused(IBinder token) {
3789 final long origId = Binder.clearCallingIdentity();
3790 mMainStack.activityPaused(token, false);
3791 Binder.restoreCallingIdentity(origId);
3792 }
3793
3794 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3795 CharSequence description) {
3796 if (localLOGV) Slog.v(
3797 TAG, "Activity stopped: token=" + token);
3798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 // Refuse possible leaked file descriptors
3800 if (icicle != null && icicle.hasFileDescriptors()) {
3801 throw new IllegalArgumentException("File descriptors passed in Bundle");
3802 }
3803
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003804 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805
3806 final long origId = Binder.clearCallingIdentity();
3807
3808 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003809 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003811 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003812 r.icicle = icicle;
3813 r.haveState = true;
3814 if (thumbnail != null) {
3815 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003816 if (r.task != null) {
3817 r.task.lastThumbnail = r.thumbnail;
3818 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003821 if (r.task != null) {
3822 r.task.lastDescription = r.description;
3823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 r.stopped = true;
3825 r.state = ActivityState.STOPPED;
3826 if (!r.finishing) {
3827 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003828 r.stack.destroyActivityLocked(r, true);
3829 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 }
3831 }
3832 }
3833 }
3834
3835 if (r != null) {
3836 sendPendingThumbnail(r, null, null, null, false);
3837 }
3838
3839 trimApplications();
3840
3841 Binder.restoreCallingIdentity(origId);
3842 }
3843
3844 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003845 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003846 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 }
3848
3849 public String getCallingPackage(IBinder token) {
3850 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003851 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003852 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003853 }
3854 }
3855
3856 public ComponentName getCallingActivity(IBinder token) {
3857 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003858 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 return r != null ? r.intent.getComponent() : null;
3860 }
3861 }
3862
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003863 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003864 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003866 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 if (r != null) {
3868 return r.resultTo;
3869 }
3870 }
3871 return null;
3872 }
3873
3874 public ComponentName getActivityClassForToken(IBinder token) {
3875 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003876 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003878 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 return r.intent.getComponent();
3880 }
3881 return null;
3882 }
3883 }
3884
3885 public String getPackageForToken(IBinder token) {
3886 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003887 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003889 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 return r.packageName;
3891 }
3892 return null;
3893 }
3894 }
3895
3896 public IIntentSender getIntentSender(int type,
3897 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003898 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003900 if (intents != null) {
3901 if (intents.length < 1) {
3902 throw new IllegalArgumentException("Intents array length must be >= 1");
3903 }
3904 for (int i=0; i<intents.length; i++) {
3905 Intent intent = intents[i];
3906 if (intent == null) {
3907 throw new IllegalArgumentException("Null intent at index " + i);
3908 }
3909 if (intent.hasFileDescriptors()) {
3910 throw new IllegalArgumentException("File descriptors passed in Intent");
3911 }
3912 if (type == INTENT_SENDER_BROADCAST &&
3913 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3914 throw new IllegalArgumentException(
3915 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3916 }
3917 intents[i] = new Intent(intent);
3918 }
3919 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003920 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003921 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003922 }
3923 }
3924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 synchronized(this) {
3926 int callingUid = Binder.getCallingUid();
3927 try {
3928 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3929 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003930 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 .getPackageUid(packageName);
3932 if (uid != Binder.getCallingUid()) {
3933 String msg = "Permission Denial: getIntentSender() from pid="
3934 + Binder.getCallingPid()
3935 + ", uid=" + Binder.getCallingUid()
3936 + ", (need uid=" + uid + ")"
3937 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003938 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 throw new SecurityException(msg);
3940 }
3941 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003942
3943 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003944 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946 } catch (RemoteException e) {
3947 throw new SecurityException(e);
3948 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003949 }
3950 }
3951
3952 IIntentSender getIntentSenderLocked(int type,
3953 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003954 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003955 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003956 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003957 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003958 if (index < 0) {
3959 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003961 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003962 if (activity.finishing) {
3963 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003965 }
3966
3967 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3968 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3969 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3970 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3971 |PendingIntent.FLAG_UPDATE_CURRENT);
3972
3973 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3974 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003975 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003976 WeakReference<PendingIntentRecord> ref;
3977 ref = mIntentSenderRecords.get(key);
3978 PendingIntentRecord rec = ref != null ? ref.get() : null;
3979 if (rec != null) {
3980 if (!cancelCurrent) {
3981 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003982 if (rec.key.requestIntent != null) {
3983 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3984 }
3985 if (intents != null) {
3986 intents[intents.length-1] = rec.key.requestIntent;
3987 rec.key.allIntents = intents;
3988 rec.key.allResolvedTypes = resolvedTypes;
3989 } else {
3990 rec.key.allIntents = null;
3991 rec.key.allResolvedTypes = null;
3992 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 return rec;
3995 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003996 rec.canceled = true;
3997 mIntentSenderRecords.remove(key);
3998 }
3999 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 return rec;
4001 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004002 rec = new PendingIntentRecord(this, key, callingUid);
4003 mIntentSenderRecords.put(key, rec.ref);
4004 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4005 if (activity.pendingResults == null) {
4006 activity.pendingResults
4007 = new HashSet<WeakReference<PendingIntentRecord>>();
4008 }
4009 activity.pendingResults.add(rec.ref);
4010 }
4011 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 }
4013
4014 public void cancelIntentSender(IIntentSender sender) {
4015 if (!(sender instanceof PendingIntentRecord)) {
4016 return;
4017 }
4018 synchronized(this) {
4019 PendingIntentRecord rec = (PendingIntentRecord)sender;
4020 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004021 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 .getPackageUid(rec.key.packageName);
4023 if (uid != Binder.getCallingUid()) {
4024 String msg = "Permission Denial: cancelIntentSender() from pid="
4025 + Binder.getCallingPid()
4026 + ", uid=" + Binder.getCallingUid()
4027 + " is not allowed to cancel packges "
4028 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004029 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 throw new SecurityException(msg);
4031 }
4032 } catch (RemoteException e) {
4033 throw new SecurityException(e);
4034 }
4035 cancelIntentSenderLocked(rec, true);
4036 }
4037 }
4038
4039 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4040 rec.canceled = true;
4041 mIntentSenderRecords.remove(rec.key);
4042 if (cleanActivity && rec.key.activity != null) {
4043 rec.key.activity.pendingResults.remove(rec.ref);
4044 }
4045 }
4046
4047 public String getPackageForIntentSender(IIntentSender pendingResult) {
4048 if (!(pendingResult instanceof PendingIntentRecord)) {
4049 return null;
4050 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004051 try {
4052 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4053 return res.key.packageName;
4054 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 }
4056 return null;
4057 }
4058
4059 public void setProcessLimit(int max) {
4060 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4061 "setProcessLimit()");
4062 mProcessLimit = max;
4063 }
4064
4065 public int getProcessLimit() {
4066 return mProcessLimit;
4067 }
4068
4069 void foregroundTokenDied(ForegroundToken token) {
4070 synchronized (ActivityManagerService.this) {
4071 synchronized (mPidsSelfLocked) {
4072 ForegroundToken cur
4073 = mForegroundProcesses.get(token.pid);
4074 if (cur != token) {
4075 return;
4076 }
4077 mForegroundProcesses.remove(token.pid);
4078 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4079 if (pr == null) {
4080 return;
4081 }
4082 pr.forcingToForeground = null;
4083 pr.foregroundServices = false;
4084 }
4085 updateOomAdjLocked();
4086 }
4087 }
4088
4089 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4090 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4091 "setProcessForeground()");
4092 synchronized(this) {
4093 boolean changed = false;
4094
4095 synchronized (mPidsSelfLocked) {
4096 ProcessRecord pr = mPidsSelfLocked.get(pid);
4097 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004098 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 return;
4100 }
4101 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4102 if (oldToken != null) {
4103 oldToken.token.unlinkToDeath(oldToken, 0);
4104 mForegroundProcesses.remove(pid);
4105 pr.forcingToForeground = null;
4106 changed = true;
4107 }
4108 if (isForeground && token != null) {
4109 ForegroundToken newToken = new ForegroundToken() {
4110 public void binderDied() {
4111 foregroundTokenDied(this);
4112 }
4113 };
4114 newToken.pid = pid;
4115 newToken.token = token;
4116 try {
4117 token.linkToDeath(newToken, 0);
4118 mForegroundProcesses.put(pid, newToken);
4119 pr.forcingToForeground = token;
4120 changed = true;
4121 } catch (RemoteException e) {
4122 // If the process died while doing this, we will later
4123 // do the cleanup with the process death link.
4124 }
4125 }
4126 }
4127
4128 if (changed) {
4129 updateOomAdjLocked();
4130 }
4131 }
4132 }
4133
4134 // =========================================================
4135 // PERMISSIONS
4136 // =========================================================
4137
4138 static class PermissionController extends IPermissionController.Stub {
4139 ActivityManagerService mActivityManagerService;
4140 PermissionController(ActivityManagerService activityManagerService) {
4141 mActivityManagerService = activityManagerService;
4142 }
4143
4144 public boolean checkPermission(String permission, int pid, int uid) {
4145 return mActivityManagerService.checkPermission(permission, pid,
4146 uid) == PackageManager.PERMISSION_GRANTED;
4147 }
4148 }
4149
4150 /**
4151 * This can be called with or without the global lock held.
4152 */
4153 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004154 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 // We might be performing an operation on behalf of an indirect binder
4156 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4157 // client identity accordingly before proceeding.
4158 Identity tlsIdentity = sCallerIdentity.get();
4159 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004160 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4162 uid = tlsIdentity.uid;
4163 pid = tlsIdentity.pid;
4164 }
4165
4166 // Root, system server and our own process get to do everything.
4167 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4168 !Process.supportsProcesses()) {
4169 return PackageManager.PERMISSION_GRANTED;
4170 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004171 // If there is a uid that owns whatever is being accessed, it has
4172 // blanket access to it regardless of the permissions it requires.
4173 if (owningUid >= 0 && uid == owningUid) {
4174 return PackageManager.PERMISSION_GRANTED;
4175 }
4176 // If the target is not exported, then nobody else can get to it.
4177 if (!exported) {
4178 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 return PackageManager.PERMISSION_DENIED;
4180 }
4181 if (permission == null) {
4182 return PackageManager.PERMISSION_GRANTED;
4183 }
4184 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004185 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 .checkUidPermission(permission, uid);
4187 } catch (RemoteException e) {
4188 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004189 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 }
4191 return PackageManager.PERMISSION_DENIED;
4192 }
4193
4194 /**
4195 * As the only public entry point for permissions checking, this method
4196 * can enforce the semantic that requesting a check on a null global
4197 * permission is automatically denied. (Internally a null permission
4198 * string is used when calling {@link #checkComponentPermission} in cases
4199 * when only uid-based security is needed.)
4200 *
4201 * This can be called with or without the global lock held.
4202 */
4203 public int checkPermission(String permission, int pid, int uid) {
4204 if (permission == null) {
4205 return PackageManager.PERMISSION_DENIED;
4206 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004207 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 }
4209
4210 /**
4211 * Binder IPC calls go through the public entry point.
4212 * This can be called with or without the global lock held.
4213 */
4214 int checkCallingPermission(String permission) {
4215 return checkPermission(permission,
4216 Binder.getCallingPid(),
4217 Binder.getCallingUid());
4218 }
4219
4220 /**
4221 * This can be called with or without the global lock held.
4222 */
4223 void enforceCallingPermission(String permission, String func) {
4224 if (checkCallingPermission(permission)
4225 == PackageManager.PERMISSION_GRANTED) {
4226 return;
4227 }
4228
4229 String msg = "Permission Denial: " + func + " from pid="
4230 + Binder.getCallingPid()
4231 + ", uid=" + Binder.getCallingUid()
4232 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004233 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 throw new SecurityException(msg);
4235 }
4236
4237 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004238 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4239 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4240 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4241 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4242 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004244 // Is the component private from the target uid?
4245 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4246
4247 // Acceptable if the there is no read permission needed from the
4248 // target or the target is holding the read permission.
4249 if (!readPerm) {
4250 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004252 == PackageManager.PERMISSION_GRANTED)) {
4253 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 }
4255 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004256
4257 // Acceptable if the there is no write permission needed from the
4258 // target or the target is holding the read permission.
4259 if (!writePerm) {
4260 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004262 == PackageManager.PERMISSION_GRANTED)) {
4263 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 }
4265 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004266
4267 // Acceptable if there is a path permission matching the URI that
4268 // the target holds the permission on.
4269 PathPermission[] pps = pi.pathPermissions;
4270 if (pps != null && (!readPerm || !writePerm)) {
4271 final String path = uri.getPath();
4272 int i = pps.length;
4273 while (i > 0 && (!readPerm || !writePerm)) {
4274 i--;
4275 PathPermission pp = pps[i];
4276 if (!readPerm) {
4277 final String pprperm = pp.getReadPermission();
4278 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4279 + pprperm + " for " + pp.getPath()
4280 + ": match=" + pp.match(path)
4281 + " check=" + pm.checkUidPermission(pprperm, uid));
4282 if (pprperm != null && pp.match(path) &&
4283 (pm.checkUidPermission(pprperm, uid)
4284 == PackageManager.PERMISSION_GRANTED)) {
4285 readPerm = true;
4286 }
4287 }
4288 if (!writePerm) {
4289 final String ppwperm = pp.getWritePermission();
4290 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4291 + ppwperm + " for " + pp.getPath()
4292 + ": match=" + pp.match(path)
4293 + " check=" + pm.checkUidPermission(ppwperm, uid));
4294 if (ppwperm != null && pp.match(path) &&
4295 (pm.checkUidPermission(ppwperm, uid)
4296 == PackageManager.PERMISSION_GRANTED)) {
4297 writePerm = true;
4298 }
4299 }
4300 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 } catch (RemoteException e) {
4303 return false;
4304 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004305
4306 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4310 int modeFlags) {
4311 // Root gets to do everything.
4312 if (uid == 0 || !Process.supportsProcesses()) {
4313 return true;
4314 }
4315 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4316 if (perms == null) return false;
4317 UriPermission perm = perms.get(uri);
4318 if (perm == null) return false;
4319 return (modeFlags&perm.modeFlags) == modeFlags;
4320 }
4321
4322 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4323 // Another redirected-binder-call permissions check as in
4324 // {@link checkComponentPermission}.
4325 Identity tlsIdentity = sCallerIdentity.get();
4326 if (tlsIdentity != null) {
4327 uid = tlsIdentity.uid;
4328 pid = tlsIdentity.pid;
4329 }
4330
4331 // Our own process gets to do everything.
4332 if (pid == MY_PID) {
4333 return PackageManager.PERMISSION_GRANTED;
4334 }
4335 synchronized(this) {
4336 return checkUriPermissionLocked(uri, uid, modeFlags)
4337 ? PackageManager.PERMISSION_GRANTED
4338 : PackageManager.PERMISSION_DENIED;
4339 }
4340 }
4341
Dianne Hackborn39792d22010-08-19 18:01:52 -07004342 /**
4343 * Check if the targetPkg can be granted permission to access uri by
4344 * the callingUid using the given modeFlags. Throws a security exception
4345 * if callingUid is not allowed to do this. Returns the uid of the target
4346 * if the URI permission grant should be performed; returns -1 if it is not
4347 * needed (for example targetPkg already has permission to access the URI).
4348 */
4349 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4350 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4352 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4353 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004354 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 }
4356
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004357 if (targetPkg != null) {
4358 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4359 "Checking grant " + targetPkg + " permission to " + uri);
4360 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004361
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004362 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363
4364 // If this is not a content: uri, we can't do anything with it.
4365 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004366 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004367 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004368 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 }
4370
4371 String name = uri.getAuthority();
4372 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004373 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 if (cpr != null) {
4375 pi = cpr.info;
4376 } else {
4377 try {
4378 pi = pm.resolveContentProvider(name,
4379 PackageManager.GET_URI_PERMISSION_PATTERNS);
4380 } catch (RemoteException ex) {
4381 }
4382 }
4383 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004384 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004385 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 }
4387
4388 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004389 if (targetPkg != null) {
4390 try {
4391 targetUid = pm.getPackageUid(targetPkg);
4392 if (targetUid < 0) {
4393 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4394 "Can't grant URI permission no uid for: " + targetPkg);
4395 return -1;
4396 }
4397 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004398 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004400 } else {
4401 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 }
4403
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004404 if (targetUid >= 0) {
4405 // First... does the target actually need this permission?
4406 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4407 // No need to grant the target this permission.
4408 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4409 "Target " + targetPkg + " already has full permission to " + uri);
4410 return -1;
4411 }
4412 } else {
4413 // First... there is no target package, so can anyone access it?
4414 boolean allowed = pi.exported;
4415 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4416 if (pi.readPermission != null) {
4417 allowed = false;
4418 }
4419 }
4420 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4421 if (pi.writePermission != null) {
4422 allowed = false;
4423 }
4424 }
4425 if (allowed) {
4426 return -1;
4427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 }
4429
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004430 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 if (!pi.grantUriPermissions) {
4432 throw new SecurityException("Provider " + pi.packageName
4433 + "/" + pi.name
4434 + " does not allow granting of Uri permissions (uri "
4435 + uri + ")");
4436 }
4437 if (pi.uriPermissionPatterns != null) {
4438 final int N = pi.uriPermissionPatterns.length;
4439 boolean allowed = false;
4440 for (int i=0; i<N; i++) {
4441 if (pi.uriPermissionPatterns[i] != null
4442 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4443 allowed = true;
4444 break;
4445 }
4446 }
4447 if (!allowed) {
4448 throw new SecurityException("Provider " + pi.packageName
4449 + "/" + pi.name
4450 + " does not allow granting of permission to path of Uri "
4451 + uri);
4452 }
4453 }
4454
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004455 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004457 if (callingUid != Process.myUid()) {
4458 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4459 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4460 throw new SecurityException("Uid " + callingUid
4461 + " does not have permission to uri " + uri);
4462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 }
4464 }
4465
Dianne Hackborn39792d22010-08-19 18:01:52 -07004466 return targetUid;
4467 }
4468
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004469 public int checkGrantUriPermission(int callingUid, String targetPkg,
4470 Uri uri, int modeFlags) {
4471 synchronized(this) {
4472 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4473 }
4474 }
4475
Dianne Hackborn39792d22010-08-19 18:01:52 -07004476 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4477 Uri uri, int modeFlags, UriPermissionOwner owner) {
4478 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4479 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4480 if (modeFlags == 0) {
4481 return;
4482 }
4483
4484 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 // to the uri, and the target doesn't. Let's now give this to
4486 // the target.
4487
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004489 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 HashMap<Uri, UriPermission> targetUris
4492 = mGrantedUriPermissions.get(targetUid);
4493 if (targetUris == null) {
4494 targetUris = new HashMap<Uri, UriPermission>();
4495 mGrantedUriPermissions.put(targetUid, targetUris);
4496 }
4497
4498 UriPermission perm = targetUris.get(uri);
4499 if (perm == null) {
4500 perm = new UriPermission(targetUid, uri);
4501 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004505 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004507 } else {
4508 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4509 perm.readOwners.add(owner);
4510 owner.addReadPermission(perm);
4511 }
4512 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4513 perm.writeOwners.add(owner);
4514 owner.addWritePermission(perm);
4515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 }
4517 }
4518
Dianne Hackborn39792d22010-08-19 18:01:52 -07004519 void grantUriPermissionLocked(int callingUid,
4520 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004521 if (targetPkg == null) {
4522 throw new NullPointerException("targetPkg");
4523 }
4524
Dianne Hackborn39792d22010-08-19 18:01:52 -07004525 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4526 if (targetUid < 0) {
4527 return;
4528 }
4529
4530 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4531 }
4532
4533 /**
4534 * Like checkGrantUriPermissionLocked, but takes an Intent.
4535 */
4536 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4537 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004538 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004539 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004540 + " from " + intent + "; flags=0x"
4541 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4542
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004543 if (targetPkg == null) {
4544 throw new NullPointerException("targetPkg");
4545 }
4546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004548 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 }
4550 Uri data = intent.getData();
4551 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004552 return -1;
4553 }
4554 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4555 intent.getFlags());
4556 }
4557
4558 /**
4559 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4560 */
4561 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4562 String targetPkg, Intent intent, UriPermissionOwner owner) {
4563 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4564 intent.getFlags(), owner);
4565 }
4566
4567 void grantUriPermissionFromIntentLocked(int callingUid,
4568 String targetPkg, Intent intent, UriPermissionOwner owner) {
4569 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4570 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 return;
4572 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004573
4574 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 }
4576
4577 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4578 Uri uri, int modeFlags) {
4579 synchronized(this) {
4580 final ProcessRecord r = getRecordForAppLocked(caller);
4581 if (r == null) {
4582 throw new SecurityException("Unable to find app for caller "
4583 + caller
4584 + " when granting permission to uri " + uri);
4585 }
4586 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004587 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 }
4589 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004590 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 }
4592
4593 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4594 null);
4595 }
4596 }
4597
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004598 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4600 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4601 HashMap<Uri, UriPermission> perms
4602 = mGrantedUriPermissions.get(perm.uid);
4603 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004604 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004605 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 perms.remove(perm.uri);
4607 if (perms.size() == 0) {
4608 mGrantedUriPermissions.remove(perm.uid);
4609 }
4610 }
4611 }
4612 }
4613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4615 int modeFlags) {
4616 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4617 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4618 if (modeFlags == 0) {
4619 return;
4620 }
4621
Joe Onorato8a9b2202010-02-26 18:56:32 -08004622 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004623 "Revoking all granted permissions to " + uri);
4624
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004625 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626
4627 final String authority = uri.getAuthority();
4628 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004629 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 if (cpr != null) {
4631 pi = cpr.info;
4632 } else {
4633 try {
4634 pi = pm.resolveContentProvider(authority,
4635 PackageManager.GET_URI_PERMISSION_PATTERNS);
4636 } catch (RemoteException ex) {
4637 }
4638 }
4639 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004640 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 return;
4642 }
4643
4644 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004645 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 // Right now, if you are not the original owner of the permission,
4647 // you are not allowed to revoke it.
4648 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4649 throw new SecurityException("Uid " + callingUid
4650 + " does not have permission to uri " + uri);
4651 //}
4652 }
4653
4654 // Go through all of the permissions and remove any that match.
4655 final List<String> SEGMENTS = uri.getPathSegments();
4656 if (SEGMENTS != null) {
4657 final int NS = SEGMENTS.size();
4658 int N = mGrantedUriPermissions.size();
4659 for (int i=0; i<N; i++) {
4660 HashMap<Uri, UriPermission> perms
4661 = mGrantedUriPermissions.valueAt(i);
4662 Iterator<UriPermission> it = perms.values().iterator();
4663 toploop:
4664 while (it.hasNext()) {
4665 UriPermission perm = it.next();
4666 Uri targetUri = perm.uri;
4667 if (!authority.equals(targetUri.getAuthority())) {
4668 continue;
4669 }
4670 List<String> targetSegments = targetUri.getPathSegments();
4671 if (targetSegments == null) {
4672 continue;
4673 }
4674 if (targetSegments.size() < NS) {
4675 continue;
4676 }
4677 for (int j=0; j<NS; j++) {
4678 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4679 continue toploop;
4680 }
4681 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004682 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004683 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 perm.clearModes(modeFlags);
4685 if (perm.modeFlags == 0) {
4686 it.remove();
4687 }
4688 }
4689 if (perms.size() == 0) {
4690 mGrantedUriPermissions.remove(
4691 mGrantedUriPermissions.keyAt(i));
4692 N--;
4693 i--;
4694 }
4695 }
4696 }
4697 }
4698
4699 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4700 int modeFlags) {
4701 synchronized(this) {
4702 final ProcessRecord r = getRecordForAppLocked(caller);
4703 if (r == null) {
4704 throw new SecurityException("Unable to find app for caller "
4705 + caller
4706 + " when revoking permission to uri " + uri);
4707 }
4708 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004709 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 return;
4711 }
4712
4713 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4714 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4715 if (modeFlags == 0) {
4716 return;
4717 }
4718
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004719 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720
4721 final String authority = uri.getAuthority();
4722 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004723 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 if (cpr != null) {
4725 pi = cpr.info;
4726 } else {
4727 try {
4728 pi = pm.resolveContentProvider(authority,
4729 PackageManager.GET_URI_PERMISSION_PATTERNS);
4730 } catch (RemoteException ex) {
4731 }
4732 }
4733 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004734 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 return;
4736 }
4737
4738 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4739 }
4740 }
4741
Dianne Hackborn7e269642010-08-25 19:50:20 -07004742 @Override
4743 public IBinder newUriPermissionOwner(String name) {
4744 synchronized(this) {
4745 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4746 return owner.getExternalTokenLocked();
4747 }
4748 }
4749
4750 @Override
4751 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4752 Uri uri, int modeFlags) {
4753 synchronized(this) {
4754 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4755 if (owner == null) {
4756 throw new IllegalArgumentException("Unknown owner: " + token);
4757 }
4758 if (fromUid != Binder.getCallingUid()) {
4759 if (Binder.getCallingUid() != Process.myUid()) {
4760 // Only system code can grant URI permissions on behalf
4761 // of other users.
4762 throw new SecurityException("nice try");
4763 }
4764 }
4765 if (targetPkg == null) {
4766 throw new IllegalArgumentException("null target");
4767 }
4768 if (uri == null) {
4769 throw new IllegalArgumentException("null uri");
4770 }
4771
4772 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4773 }
4774 }
4775
4776 @Override
4777 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4778 synchronized(this) {
4779 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4780 if (owner == null) {
4781 throw new IllegalArgumentException("Unknown owner: " + token);
4782 }
4783
4784 if (uri == null) {
4785 owner.removeUriPermissionsLocked(mode);
4786 } else {
4787 owner.removeUriPermissionLocked(uri, mode);
4788 }
4789 }
4790 }
4791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4793 synchronized (this) {
4794 ProcessRecord app =
4795 who != null ? getRecordForAppLocked(who) : null;
4796 if (app == null) return;
4797
4798 Message msg = Message.obtain();
4799 msg.what = WAIT_FOR_DEBUGGER_MSG;
4800 msg.obj = app;
4801 msg.arg1 = waiting ? 1 : 0;
4802 mHandler.sendMessage(msg);
4803 }
4804 }
4805
4806 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4807 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004808 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004810 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 }
4812
4813 // =========================================================
4814 // TASK MANAGEMENT
4815 // =========================================================
4816
4817 public List getTasks(int maxNum, int flags,
4818 IThumbnailReceiver receiver) {
4819 ArrayList list = new ArrayList();
4820
4821 PendingThumbnailsRecord pending = null;
4822 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004823 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824
4825 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004826 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4828 + ", receiver=" + receiver);
4829
4830 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4831 != PackageManager.PERMISSION_GRANTED) {
4832 if (receiver != null) {
4833 // If the caller wants to wait for pending thumbnails,
4834 // it ain't gonna get them.
4835 try {
4836 receiver.finished();
4837 } catch (RemoteException ex) {
4838 }
4839 }
4840 String msg = "Permission Denial: getTasks() from pid="
4841 + Binder.getCallingPid()
4842 + ", uid=" + Binder.getCallingUid()
4843 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 throw new SecurityException(msg);
4846 }
4847
Dianne Hackbornd2835932010-12-13 16:28:46 -08004848 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4849 && checkCallingPermission(
4850 android.Manifest.permission.READ_FRAME_BUFFER)
4851 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004852
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004853 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004854 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004855 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004856 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 CharSequence topDescription = null;
4858 TaskRecord curTask = null;
4859 int numActivities = 0;
4860 int numRunning = 0;
4861 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004862 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004864 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865
4866 // Initialize state for next task if needed.
4867 if (top == null ||
4868 (top.state == ActivityState.INITIALIZING
4869 && top.task == r.task)) {
4870 top = r;
4871 topDescription = r.description;
4872 curTask = r.task;
4873 numActivities = numRunning = 0;
4874 }
4875
4876 // Add 'r' into the current task.
4877 numActivities++;
4878 if (r.app != null && r.app.thread != null) {
4879 numRunning++;
4880 }
4881 if (topDescription == null) {
4882 topDescription = r.description;
4883 }
4884
Joe Onorato8a9b2202010-02-26 18:56:32 -08004885 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 TAG, r.intent.getComponent().flattenToShortString()
4887 + ": task=" + r.task);
4888
4889 // If the next one is a different task, generate a new
4890 // TaskInfo entry for what we have.
4891 if (next == null || next.task != curTask) {
4892 ActivityManager.RunningTaskInfo ci
4893 = new ActivityManager.RunningTaskInfo();
4894 ci.id = curTask.taskId;
4895 ci.baseActivity = r.intent.getComponent();
4896 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004897 if (canReadFb) {
4898 if (top.thumbnail != null) {
4899 ci.thumbnail = top.thumbnail;
4900 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004901 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004902 }
4903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 ci.description = topDescription;
4905 ci.numActivities = numActivities;
4906 ci.numRunning = numRunning;
4907 //System.out.println(
4908 // "#" + maxNum + ": " + " descr=" + ci.description);
4909 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004910 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 TAG, "State=" + top.state + "Idle=" + top.idle
4912 + " app=" + top.app
4913 + " thr=" + (top.app != null ? top.app.thread : null));
4914 if (top.state == ActivityState.RESUMED
4915 || top.state == ActivityState.PAUSING) {
4916 if (top.idle && top.app != null
4917 && top.app.thread != null) {
4918 topRecord = top;
4919 topThumbnail = top.app.thread;
4920 } else {
4921 top.thumbnailNeeded = true;
4922 }
4923 }
4924 if (pending == null) {
4925 pending = new PendingThumbnailsRecord(receiver);
4926 }
4927 pending.pendingRecords.add(top);
4928 }
4929 list.add(ci);
4930 maxNum--;
4931 top = null;
4932 }
4933 }
4934
4935 if (pending != null) {
4936 mPendingThumbnails.add(pending);
4937 }
4938 }
4939
Joe Onorato8a9b2202010-02-26 18:56:32 -08004940 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941
4942 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004943 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 try {
4945 topThumbnail.requestThumbnail(topRecord);
4946 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004947 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 sendPendingThumbnail(null, topRecord, null, null, true);
4949 }
4950 }
4951
4952 if (pending == null && receiver != null) {
4953 // In this case all thumbnails were available and the client
4954 // is being asked to be told when the remaining ones come in...
4955 // which is unusually, since the top-most currently running
4956 // activity should never have a canned thumbnail! Oh well.
4957 try {
4958 receiver.finished();
4959 } catch (RemoteException ex) {
4960 }
4961 }
4962
4963 return list;
4964 }
4965
4966 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4967 int flags) {
4968 synchronized (this) {
4969 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4970 "getRecentTasks()");
4971
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004972 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004973
Dianne Hackbornd2835932010-12-13 16:28:46 -08004974 ActivityRecord resumed = mMainStack.mResumedActivity;
4975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 final int N = mRecentTasks.size();
4977 ArrayList<ActivityManager.RecentTaskInfo> res
4978 = new ArrayList<ActivityManager.RecentTaskInfo>(
4979 maxNum < N ? maxNum : N);
4980 for (int i=0; i<N && maxNum > 0; i++) {
4981 TaskRecord tr = mRecentTasks.get(i);
4982 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4983 || (tr.intent == null)
4984 || ((tr.intent.getFlags()
4985 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4986 ActivityManager.RecentTaskInfo rti
4987 = new ActivityManager.RecentTaskInfo();
4988 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004989 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 rti.baseIntent = new Intent(
4991 tr.intent != null ? tr.intent : tr.affinityIntent);
4992 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08004993 rti.description = tr.lastDescription;
4994
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004995 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4996 // Check whether this activity is currently available.
4997 try {
4998 if (rti.origActivity != null) {
4999 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5000 continue;
5001 }
5002 } else if (rti.baseIntent != null) {
5003 if (pm.queryIntentActivities(rti.baseIntent,
5004 null, 0) == null) {
5005 continue;
5006 }
5007 }
5008 } catch (RemoteException e) {
5009 // Will never happen.
5010 }
5011 }
5012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 res.add(rti);
5014 maxNum--;
5015 }
5016 }
5017 return res;
5018 }
5019 }
5020
Dianne Hackbornd94df452011-02-16 18:53:31 -08005021 public Bitmap getTaskThumbnail(int id) {
5022 synchronized (this) {
5023 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5024 "getTaskThumbnail()");
5025 ActivityRecord resumed = mMainStack.mResumedActivity;
5026 final int N = mRecentTasks.size();
5027 for (int i=0; i<N; i++) {
5028 TaskRecord tr = mRecentTasks.get(i);
5029 if (tr.taskId == id) {
5030 if (resumed != null && resumed.task == tr) {
5031 return resumed.stack.screenshotActivities(resumed);
5032 } else {
5033 return tr.lastThumbnail;
5034 }
5035 }
5036 }
5037 }
5038 return null;
5039 }
5040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5042 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005043 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 TaskRecord jt = startTask;
5045
5046 // First look backwards
5047 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005048 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 if (r.task != jt) {
5050 jt = r.task;
5051 if (affinity.equals(jt.affinity)) {
5052 return j;
5053 }
5054 }
5055 }
5056
5057 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005058 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 jt = startTask;
5060 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005061 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 if (r.task != jt) {
5063 if (affinity.equals(jt.affinity)) {
5064 return j;
5065 }
5066 jt = r.task;
5067 }
5068 }
5069
5070 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005071 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 return N-1;
5073 }
5074
5075 return -1;
5076 }
5077
5078 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005079 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005081 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5083 "moveTaskToFront()");
5084
5085 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005086 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5087 Binder.getCallingUid(), "Task to front")) {
5088 return;
5089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 final long origId = Binder.clearCallingIdentity();
5091 try {
5092 int N = mRecentTasks.size();
5093 for (int i=0; i<N; i++) {
5094 TaskRecord tr = mRecentTasks.get(i);
5095 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005096 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5097 mMainStack.mUserLeaving = true;
5098 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005099 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5100 // Caller wants the home activity moved with it. To accomplish this,
5101 // we'll just move the home task to the top first.
5102 mMainStack.moveHomeToFrontLocked();
5103 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005104 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 return;
5106 }
5107 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005108 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5109 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005111 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5112 mMainStack.mUserLeaving = true;
5113 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005114 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5115 // Caller wants the home activity moved with it. To accomplish this,
5116 // we'll just move the home task to the top first.
5117 mMainStack.moveHomeToFrontLocked();
5118 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005119 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 return;
5121 }
5122 }
5123 } finally {
5124 Binder.restoreCallingIdentity(origId);
5125 }
5126 }
5127 }
5128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 public void moveTaskToBack(int task) {
5130 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5131 "moveTaskToBack()");
5132
5133 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005134 if (mMainStack.mResumedActivity != null
5135 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005136 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5137 Binder.getCallingUid(), "Task to back")) {
5138 return;
5139 }
5140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005142 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 Binder.restoreCallingIdentity(origId);
5144 }
5145 }
5146
5147 /**
5148 * Moves an activity, and all of the other activities within the same task, to the bottom
5149 * of the history stack. The activity's order within the task is unchanged.
5150 *
5151 * @param token A reference to the activity we wish to move
5152 * @param nonRoot If false then this only works if the activity is the root
5153 * of a task; if true it will work for any activity in a task.
5154 * @return Returns true if the move completed, false if not.
5155 */
5156 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5157 synchronized(this) {
5158 final long origId = Binder.clearCallingIdentity();
5159 int taskId = getTaskForActivityLocked(token, !nonRoot);
5160 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005161 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 }
5163 Binder.restoreCallingIdentity(origId);
5164 }
5165 return false;
5166 }
5167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 public void moveTaskBackwards(int task) {
5169 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5170 "moveTaskBackwards()");
5171
5172 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005173 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5174 Binder.getCallingUid(), "Task backwards")) {
5175 return;
5176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 final long origId = Binder.clearCallingIdentity();
5178 moveTaskBackwardsLocked(task);
5179 Binder.restoreCallingIdentity(origId);
5180 }
5181 }
5182
5183 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005184 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 }
5186
5187 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5188 synchronized(this) {
5189 return getTaskForActivityLocked(token, onlyRoot);
5190 }
5191 }
5192
5193 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005194 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 TaskRecord lastTask = null;
5196 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005197 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 if (r == token) {
5199 if (!onlyRoot || lastTask != r.task) {
5200 return r.task.taskId;
5201 }
5202 return -1;
5203 }
5204 lastTask = r.task;
5205 }
5206
5207 return -1;
5208 }
5209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 public void finishOtherInstances(IBinder token, ComponentName className) {
5211 synchronized(this) {
5212 final long origId = Binder.clearCallingIdentity();
5213
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005214 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005215 TaskRecord lastTask = null;
5216 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005217 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 if (r.realActivity.equals(className)
5219 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005220 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 null, "others")) {
5222 i--;
5223 N--;
5224 }
5225 }
5226 lastTask = r.task;
5227 }
5228
5229 Binder.restoreCallingIdentity(origId);
5230 }
5231 }
5232
5233 // =========================================================
5234 // THUMBNAILS
5235 // =========================================================
5236
5237 public void reportThumbnail(IBinder token,
5238 Bitmap thumbnail, CharSequence description) {
5239 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5240 final long origId = Binder.clearCallingIdentity();
5241 sendPendingThumbnail(null, token, thumbnail, description, true);
5242 Binder.restoreCallingIdentity(origId);
5243 }
5244
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005245 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 Bitmap thumbnail, CharSequence description, boolean always) {
5247 TaskRecord task = null;
5248 ArrayList receivers = null;
5249
5250 //System.out.println("Send pending thumbnail: " + r);
5251
5252 synchronized(this) {
5253 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005254 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 if (index < 0) {
5256 return;
5257 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005258 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 }
5260 if (thumbnail == null) {
5261 thumbnail = r.thumbnail;
5262 description = r.description;
5263 }
5264 if (thumbnail == null && !always) {
5265 // If there is no thumbnail, and this entry is not actually
5266 // going away, then abort for now and pick up the next
5267 // thumbnail we get.
5268 return;
5269 }
5270 task = r.task;
5271
5272 int N = mPendingThumbnails.size();
5273 int i=0;
5274 while (i<N) {
5275 PendingThumbnailsRecord pr =
5276 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5277 //System.out.println("Looking in " + pr.pendingRecords);
5278 if (pr.pendingRecords.remove(r)) {
5279 if (receivers == null) {
5280 receivers = new ArrayList();
5281 }
5282 receivers.add(pr);
5283 if (pr.pendingRecords.size() == 0) {
5284 pr.finished = true;
5285 mPendingThumbnails.remove(i);
5286 N--;
5287 continue;
5288 }
5289 }
5290 i++;
5291 }
5292 }
5293
5294 if (receivers != null) {
5295 final int N = receivers.size();
5296 for (int i=0; i<N; i++) {
5297 try {
5298 PendingThumbnailsRecord pr =
5299 (PendingThumbnailsRecord)receivers.get(i);
5300 pr.receiver.newThumbnail(
5301 task != null ? task.taskId : -1, thumbnail, description);
5302 if (pr.finished) {
5303 pr.receiver.finished();
5304 }
5305 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005306 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 }
5308 }
5309 }
5310 }
5311
5312 // =========================================================
5313 // CONTENT PROVIDERS
5314 // =========================================================
5315
5316 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5317 List providers = null;
5318 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005319 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005321 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 } catch (RemoteException ex) {
5323 }
5324 if (providers != null) {
5325 final int N = providers.size();
5326 for (int i=0; i<N; i++) {
5327 ProviderInfo cpi =
5328 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005329 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 if (cpr == null) {
5331 cpr = new ContentProviderRecord(cpi, app.info);
5332 mProvidersByClass.put(cpi.name, cpr);
5333 }
5334 app.pubProviders.put(cpi.name, cpr);
5335 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005336 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 }
5338 }
5339 return providers;
5340 }
5341
5342 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005343 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5345 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5346 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005347 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005348 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 return null;
5350 }
5351 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005352 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 == PackageManager.PERMISSION_GRANTED) {
5354 return null;
5355 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005356
5357 PathPermission[] pps = cpi.pathPermissions;
5358 if (pps != null) {
5359 int i = pps.length;
5360 while (i > 0) {
5361 i--;
5362 PathPermission pp = pps[i];
5363 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005364 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005365 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005366 return null;
5367 }
5368 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005369 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005370 == PackageManager.PERMISSION_GRANTED) {
5371 return null;
5372 }
5373 }
5374 }
5375
Dianne Hackbornb424b632010-08-18 15:59:05 -07005376 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5377 if (perms != null) {
5378 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5379 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5380 return null;
5381 }
5382 }
5383 }
5384
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005385 String msg;
5386 if (!cpi.exported) {
5387 msg = "Permission Denial: opening provider " + cpi.name
5388 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5389 + ", uid=" + callingUid + ") that is not exported from uid "
5390 + cpi.applicationInfo.uid;
5391 } else {
5392 msg = "Permission Denial: opening provider " + cpi.name
5393 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5394 + ", uid=" + callingUid + ") requires "
5395 + cpi.readPermission + " or " + cpi.writePermission;
5396 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005397 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 return msg;
5399 }
5400
5401 private final ContentProviderHolder getContentProviderImpl(
5402 IApplicationThread caller, String name) {
5403 ContentProviderRecord cpr;
5404 ProviderInfo cpi = null;
5405
5406 synchronized(this) {
5407 ProcessRecord r = null;
5408 if (caller != null) {
5409 r = getRecordForAppLocked(caller);
5410 if (r == null) {
5411 throw new SecurityException(
5412 "Unable to find app for caller " + caller
5413 + " (pid=" + Binder.getCallingPid()
5414 + ") when getting content provider " + name);
5415 }
5416 }
5417
5418 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005419 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 if (cpr != null) {
5421 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005422 String msg;
5423 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5424 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 }
5426
5427 if (r != null && cpr.canRunHere(r)) {
5428 // This provider has been published or is in the process
5429 // of being published... but it is also allowed to run
5430 // in the caller's process, so don't make a connection
5431 // and just let the caller instantiate its own instance.
5432 if (cpr.provider != null) {
5433 // don't give caller the provider object, it needs
5434 // to make its own.
5435 cpr = new ContentProviderRecord(cpr);
5436 }
5437 return cpr;
5438 }
5439
5440 final long origId = Binder.clearCallingIdentity();
5441
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005442 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 // return it right away.
5444 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005445 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005446 "Adding provider requested by "
5447 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005448 + cpr.info.processName);
5449 Integer cnt = r.conProviders.get(cpr);
5450 if (cnt == null) {
5451 r.conProviders.put(cpr, new Integer(1));
5452 } else {
5453 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005456 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5457 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005458 // make sure to count it as being accessed and thus
5459 // back up on the LRU list. This is good because
5460 // content providers are often expensive to start.
5461 updateLruProcessLocked(cpr.app, false, true);
5462 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005463 } else {
5464 cpr.externals++;
5465 }
5466
5467 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 updateOomAdjLocked(cpr.app);
5469 }
5470
5471 Binder.restoreCallingIdentity(origId);
5472
5473 } else {
5474 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005475 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005476 resolveContentProvider(name,
5477 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 } catch (RemoteException ex) {
5479 }
5480 if (cpi == null) {
5481 return null;
5482 }
5483
Dianne Hackbornb424b632010-08-18 15:59:05 -07005484 String msg;
5485 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5486 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 }
5488
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005489 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005490 && !cpi.processName.equals("system")) {
5491 // If this content provider does not run in the system
5492 // process, and the system is not yet ready to run other
5493 // processes, then fail fast instead of hanging.
5494 throw new IllegalArgumentException(
5495 "Attempt to launch content provider before system ready");
5496 }
5497
Dianne Hackborn860755f2010-06-03 18:47:52 -07005498 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 final boolean firstClass = cpr == null;
5500 if (firstClass) {
5501 try {
5502 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005503 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 getApplicationInfo(
5505 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005506 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005508 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 + cpi.name);
5510 return null;
5511 }
5512 cpr = new ContentProviderRecord(cpi, ai);
5513 } catch (RemoteException ex) {
5514 // pm is in same process, this will never happen.
5515 }
5516 }
5517
5518 if (r != null && cpr.canRunHere(r)) {
5519 // If this is a multiprocess provider, then just return its
5520 // info and allow the caller to instantiate it. Only do
5521 // this if the provider is the same user as the caller's
5522 // process, or can run as root (so can be in any process).
5523 return cpr;
5524 }
5525
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005526 if (DEBUG_PROVIDER) {
5527 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005528 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005529 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 }
5531
5532 // This is single process, and our app is now connecting to it.
5533 // See if we are already in the process of launching this
5534 // provider.
5535 final int N = mLaunchingProviders.size();
5536 int i;
5537 for (i=0; i<N; i++) {
5538 if (mLaunchingProviders.get(i) == cpr) {
5539 break;
5540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 }
5542
5543 // If the provider is not already being launched, then get it
5544 // started.
5545 if (i >= N) {
5546 final long origId = Binder.clearCallingIdentity();
5547 ProcessRecord proc = startProcessLocked(cpi.processName,
5548 cpr.appInfo, false, 0, "content provider",
5549 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005550 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005552 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 + cpi.applicationInfo.packageName + "/"
5554 + cpi.applicationInfo.uid + " for provider "
5555 + name + ": process is bad");
5556 return null;
5557 }
5558 cpr.launchingApp = proc;
5559 mLaunchingProviders.add(cpr);
5560 Binder.restoreCallingIdentity(origId);
5561 }
5562
5563 // Make sure the provider is published (the same provider class
5564 // may be published under multiple names).
5565 if (firstClass) {
5566 mProvidersByClass.put(cpi.name, cpr);
5567 }
5568 mProvidersByName.put(name, cpr);
5569
5570 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005571 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005572 "Adding provider requested by "
5573 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005574 + cpr.info.processName);
5575 Integer cnt = r.conProviders.get(cpr);
5576 if (cnt == null) {
5577 r.conProviders.put(cpr, new Integer(1));
5578 } else {
5579 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 cpr.clients.add(r);
5582 } else {
5583 cpr.externals++;
5584 }
5585 }
5586 }
5587
5588 // Wait for the provider to be published...
5589 synchronized (cpr) {
5590 while (cpr.provider == null) {
5591 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005592 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 + cpi.applicationInfo.packageName + "/"
5594 + cpi.applicationInfo.uid + " for provider "
5595 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005596 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 cpi.applicationInfo.packageName,
5598 cpi.applicationInfo.uid, name);
5599 return null;
5600 }
5601 try {
5602 cpr.wait();
5603 } catch (InterruptedException ex) {
5604 }
5605 }
5606 }
5607 return cpr;
5608 }
5609
5610 public final ContentProviderHolder getContentProvider(
5611 IApplicationThread caller, String name) {
5612 if (caller == null) {
5613 String msg = "null IApplicationThread when getting content provider "
5614 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005615 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 throw new SecurityException(msg);
5617 }
5618
5619 return getContentProviderImpl(caller, name);
5620 }
5621
5622 private ContentProviderHolder getContentProviderExternal(String name) {
5623 return getContentProviderImpl(null, name);
5624 }
5625
5626 /**
5627 * Drop a content provider from a ProcessRecord's bookkeeping
5628 * @param cpr
5629 */
5630 public void removeContentProvider(IApplicationThread caller, String name) {
5631 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005632 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005634 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005635 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005636 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 return;
5638 }
5639 final ProcessRecord r = getRecordForAppLocked(caller);
5640 if (r == null) {
5641 throw new SecurityException(
5642 "Unable to find app for caller " + caller +
5643 " when removing content provider " + name);
5644 }
5645 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005646 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005647 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005648 + r.info.processName + " from process "
5649 + localCpr.appInfo.processName);
5650 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005652 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005653 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 return;
5655 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005656 Integer cnt = r.conProviders.get(localCpr);
5657 if (cnt == null || cnt.intValue() <= 1) {
5658 localCpr.clients.remove(r);
5659 r.conProviders.remove(localCpr);
5660 } else {
5661 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 }
5664 updateOomAdjLocked();
5665 }
5666 }
5667
5668 private void removeContentProviderExternal(String name) {
5669 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005670 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 if(cpr == null) {
5672 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005673 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 return;
5675 }
5676
5677 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005678 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 localCpr.externals--;
5680 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005681 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683 updateOomAdjLocked();
5684 }
5685 }
5686
5687 public final void publishContentProviders(IApplicationThread caller,
5688 List<ContentProviderHolder> providers) {
5689 if (providers == null) {
5690 return;
5691 }
5692
5693 synchronized(this) {
5694 final ProcessRecord r = getRecordForAppLocked(caller);
5695 if (r == null) {
5696 throw new SecurityException(
5697 "Unable to find app for caller " + caller
5698 + " (pid=" + Binder.getCallingPid()
5699 + ") when publishing content providers");
5700 }
5701
5702 final long origId = Binder.clearCallingIdentity();
5703
5704 final int N = providers.size();
5705 for (int i=0; i<N; i++) {
5706 ContentProviderHolder src = providers.get(i);
5707 if (src == null || src.info == null || src.provider == null) {
5708 continue;
5709 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005710 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 if (dst != null) {
5712 mProvidersByClass.put(dst.info.name, dst);
5713 String names[] = dst.info.authority.split(";");
5714 for (int j = 0; j < names.length; j++) {
5715 mProvidersByName.put(names[j], dst);
5716 }
5717
5718 int NL = mLaunchingProviders.size();
5719 int j;
5720 for (j=0; j<NL; j++) {
5721 if (mLaunchingProviders.get(j) == dst) {
5722 mLaunchingProviders.remove(j);
5723 j--;
5724 NL--;
5725 }
5726 }
5727 synchronized (dst) {
5728 dst.provider = src.provider;
5729 dst.app = r;
5730 dst.notifyAll();
5731 }
5732 updateOomAdjLocked(r);
5733 }
5734 }
5735
5736 Binder.restoreCallingIdentity(origId);
5737 }
5738 }
5739
5740 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005741 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005742 synchronized (mSelf) {
5743 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5744 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005745 if (providers != null) {
5746 for (int i=providers.size()-1; i>=0; i--) {
5747 ProviderInfo pi = (ProviderInfo)providers.get(i);
5748 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5749 Slog.w(TAG, "Not installing system proc provider " + pi.name
5750 + ": not system .apk");
5751 providers.remove(i);
5752 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005753 }
5754 }
5755 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005756 if (providers != null) {
5757 mSystemThread.installSystemProviders(providers);
5758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005759 }
5760
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005761 /**
5762 * Allows app to retrieve the MIME type of a URI without having permission
5763 * to access its content provider.
5764 *
5765 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5766 *
5767 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5768 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5769 */
5770 public String getProviderMimeType(Uri uri) {
5771 final String name = uri.getAuthority();
5772 final long ident = Binder.clearCallingIdentity();
5773 ContentProviderHolder holder = null;
5774
5775 try {
5776 holder = getContentProviderExternal(name);
5777 if (holder != null) {
5778 return holder.provider.getType(uri);
5779 }
5780 } catch (RemoteException e) {
5781 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5782 return null;
5783 } finally {
5784 if (holder != null) {
5785 removeContentProviderExternal(name);
5786 }
5787 Binder.restoreCallingIdentity(ident);
5788 }
5789
5790 return null;
5791 }
5792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005793 // =========================================================
5794 // GLOBAL MANAGEMENT
5795 // =========================================================
5796
5797 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5798 ApplicationInfo info, String customProcess) {
5799 String proc = customProcess != null ? customProcess : info.processName;
5800 BatteryStatsImpl.Uid.Proc ps = null;
5801 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5802 synchronized (stats) {
5803 ps = stats.getProcessStatsLocked(info.uid, proc);
5804 }
5805 return new ProcessRecord(ps, thread, info, proc);
5806 }
5807
5808 final ProcessRecord addAppLocked(ApplicationInfo info) {
5809 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5810
5811 if (app == null) {
5812 app = newProcessRecordLocked(null, info, null);
5813 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005814 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 }
5816
5817 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5818 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5819 app.persistent = true;
5820 app.maxAdj = CORE_SERVER_ADJ;
5821 }
5822 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5823 mPersistentStartingProcesses.add(app);
5824 startProcessLocked(app, "added application", app.processName);
5825 }
5826
5827 return app;
5828 }
5829
5830 public void unhandledBack() {
5831 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5832 "unhandledBack()");
5833
5834 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005835 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005836 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 TAG, "Performing unhandledBack(): stack size = " + count);
5838 if (count > 1) {
5839 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005840 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5842 Binder.restoreCallingIdentity(origId);
5843 }
5844 }
5845 }
5846
5847 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5848 String name = uri.getAuthority();
5849 ContentProviderHolder cph = getContentProviderExternal(name);
5850 ParcelFileDescriptor pfd = null;
5851 if (cph != null) {
5852 // We record the binder invoker's uid in thread-local storage before
5853 // going to the content provider to open the file. Later, in the code
5854 // that handles all permissions checks, we look for this uid and use
5855 // that rather than the Activity Manager's own uid. The effect is that
5856 // we do the check against the caller's permissions even though it looks
5857 // to the content provider like the Activity Manager itself is making
5858 // the request.
5859 sCallerIdentity.set(new Identity(
5860 Binder.getCallingPid(), Binder.getCallingUid()));
5861 try {
5862 pfd = cph.provider.openFile(uri, "r");
5863 } catch (FileNotFoundException e) {
5864 // do nothing; pfd will be returned null
5865 } finally {
5866 // Ensure that whatever happens, we clean up the identity state
5867 sCallerIdentity.remove();
5868 }
5869
5870 // We've got the fd now, so we're done with the provider.
5871 removeContentProviderExternal(name);
5872 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005873 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 }
5875 return pfd;
5876 }
5877
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005878 // Actually is sleeping or shutting down or whatever else in the future
5879 // is an inactive state.
5880 public boolean isSleeping() {
5881 return mSleeping || mShuttingDown;
5882 }
5883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 public void goingToSleep() {
5885 synchronized(this) {
5886 mSleeping = true;
5887 mWindowManager.setEventDispatching(false);
5888
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005889 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005890
5891 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005892 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005893 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5894 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005895 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 }
5897 }
5898
Dianne Hackborn55280a92009-05-07 15:53:46 -07005899 public boolean shutdown(int timeout) {
5900 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5901 != PackageManager.PERMISSION_GRANTED) {
5902 throw new SecurityException("Requires permission "
5903 + android.Manifest.permission.SHUTDOWN);
5904 }
5905
5906 boolean timedout = false;
5907
5908 synchronized(this) {
5909 mShuttingDown = true;
5910 mWindowManager.setEventDispatching(false);
5911
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005912 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005913 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005914 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005915 while (mMainStack.mResumedActivity != null
5916 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005917 long delay = endTime - System.currentTimeMillis();
5918 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005919 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005920 timedout = true;
5921 break;
5922 }
5923 try {
5924 this.wait();
5925 } catch (InterruptedException e) {
5926 }
5927 }
5928 }
5929 }
5930
5931 mUsageStatsService.shutdown();
5932 mBatteryStatsService.shutdown();
5933
5934 return timedout;
5935 }
5936
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005937 public final void activitySlept(IBinder token) {
5938 if (localLOGV) Slog.v(
5939 TAG, "Activity slept: token=" + token);
5940
5941 ActivityRecord r = null;
5942
5943 final long origId = Binder.clearCallingIdentity();
5944
5945 synchronized (this) {
5946 int index = mMainStack.indexOfTokenLocked(token);
5947 if (index >= 0) {
5948 r = (ActivityRecord)mMainStack.mHistory.get(index);
5949 mMainStack.activitySleptLocked(r);
5950 }
5951 }
5952
5953 Binder.restoreCallingIdentity(origId);
5954 }
5955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 public void wakingUp() {
5957 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 mWindowManager.setEventDispatching(true);
5959 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005960 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005961 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 }
5963 }
5964
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005965 public void stopAppSwitches() {
5966 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5967 != PackageManager.PERMISSION_GRANTED) {
5968 throw new SecurityException("Requires permission "
5969 + android.Manifest.permission.STOP_APP_SWITCHES);
5970 }
5971
5972 synchronized(this) {
5973 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5974 + APP_SWITCH_DELAY_TIME;
5975 mDidAppSwitch = false;
5976 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5977 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5978 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5979 }
5980 }
5981
5982 public void resumeAppSwitches() {
5983 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5984 != PackageManager.PERMISSION_GRANTED) {
5985 throw new SecurityException("Requires permission "
5986 + android.Manifest.permission.STOP_APP_SWITCHES);
5987 }
5988
5989 synchronized(this) {
5990 // Note that we don't execute any pending app switches... we will
5991 // let those wait until either the timeout, or the next start
5992 // activity request.
5993 mAppSwitchesAllowedTime = 0;
5994 }
5995 }
5996
5997 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5998 String name) {
5999 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6000 return true;
6001 }
6002
6003 final int perm = checkComponentPermission(
6004 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006005 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006006 if (perm == PackageManager.PERMISSION_GRANTED) {
6007 return true;
6008 }
6009
Joe Onorato8a9b2202010-02-26 18:56:32 -08006010 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006011 return false;
6012 }
6013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 public void setDebugApp(String packageName, boolean waitForDebugger,
6015 boolean persistent) {
6016 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6017 "setDebugApp()");
6018
6019 // Note that this is not really thread safe if there are multiple
6020 // callers into it at the same time, but that's not a situation we
6021 // care about.
6022 if (persistent) {
6023 final ContentResolver resolver = mContext.getContentResolver();
6024 Settings.System.putString(
6025 resolver, Settings.System.DEBUG_APP,
6026 packageName);
6027 Settings.System.putInt(
6028 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6029 waitForDebugger ? 1 : 0);
6030 }
6031
6032 synchronized (this) {
6033 if (!persistent) {
6034 mOrigDebugApp = mDebugApp;
6035 mOrigWaitForDebugger = mWaitForDebugger;
6036 }
6037 mDebugApp = packageName;
6038 mWaitForDebugger = waitForDebugger;
6039 mDebugTransient = !persistent;
6040 if (packageName != null) {
6041 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006042 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 Binder.restoreCallingIdentity(origId);
6044 }
6045 }
6046 }
6047
6048 public void setAlwaysFinish(boolean enabled) {
6049 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6050 "setAlwaysFinish()");
6051
6052 Settings.System.putInt(
6053 mContext.getContentResolver(),
6054 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6055
6056 synchronized (this) {
6057 mAlwaysFinishActivities = enabled;
6058 }
6059 }
6060
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006061 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006062 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006063 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006065 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 }
6067 }
6068
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006069 public boolean isUserAMonkey() {
6070 // For now the fact that there is a controller implies
6071 // we have a monkey.
6072 synchronized (this) {
6073 return mController != null;
6074 }
6075 }
6076
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006077 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006078 synchronized (this) {
6079 mWatchers.register(watcher);
6080 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006081 }
6082
6083 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006084 synchronized (this) {
6085 mWatchers.unregister(watcher);
6086 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006087 }
6088
Daniel Sandler69a48172010-06-23 16:29:36 -04006089 public void setImmersive(IBinder token, boolean immersive) {
6090 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006091 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006092 if (index < 0) {
6093 throw new IllegalArgumentException();
6094 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006095 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006096 r.immersive = immersive;
6097 }
6098 }
6099
6100 public boolean isImmersive(IBinder token) {
6101 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006102 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006103 if (index < 0) {
6104 throw new IllegalArgumentException();
6105 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006106 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006107 return r.immersive;
6108 }
6109 }
6110
6111 public boolean isTopActivityImmersive() {
6112 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006113 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006114 return (r != null) ? r.immersive : false;
6115 }
6116 }
6117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006118 public final void enterSafeMode() {
6119 synchronized(this) {
6120 // It only makes sense to do this before the system is ready
6121 // and started launching other packages.
6122 if (!mSystemReady) {
6123 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006124 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 } catch (RemoteException e) {
6126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 }
6128 }
6129 }
6130
Jeff Brownb09abc12011-01-13 21:08:27 -08006131 public final void showSafeModeOverlay() {
6132 View v = LayoutInflater.from(mContext).inflate(
6133 com.android.internal.R.layout.safe_mode, null);
6134 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6135 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6136 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6137 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6138 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6139 lp.format = v.getBackground().getOpacity();
6140 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6141 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6142 ((WindowManager)mContext.getSystemService(
6143 Context.WINDOW_SERVICE)).addView(v, lp);
6144 }
6145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006146 public void noteWakeupAlarm(IIntentSender sender) {
6147 if (!(sender instanceof PendingIntentRecord)) {
6148 return;
6149 }
6150 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6151 synchronized (stats) {
6152 if (mBatteryStatsService.isOnBattery()) {
6153 mBatteryStatsService.enforceCallingPermission();
6154 PendingIntentRecord rec = (PendingIntentRecord)sender;
6155 int MY_UID = Binder.getCallingUid();
6156 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6157 BatteryStatsImpl.Uid.Pkg pkg =
6158 stats.getPackageStatsLocked(uid, rec.key.packageName);
6159 pkg.incWakeupsLocked();
6160 }
6161 }
6162 }
6163
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006164 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006165 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006166 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006168 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006169 // XXX Note: don't acquire main activity lock here, because the window
6170 // manager calls in with its locks held.
6171
6172 boolean killed = false;
6173 synchronized (mPidsSelfLocked) {
6174 int[] types = new int[pids.length];
6175 int worstType = 0;
6176 for (int i=0; i<pids.length; i++) {
6177 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6178 if (proc != null) {
6179 int type = proc.setAdj;
6180 types[i] = type;
6181 if (type > worstType) {
6182 worstType = type;
6183 }
6184 }
6185 }
6186
6187 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6188 // then constrain it so we will kill all hidden procs.
6189 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6190 worstType = HIDDEN_APP_MIN_ADJ;
6191 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006192 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 for (int i=0; i<pids.length; i++) {
6194 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6195 if (proc == null) {
6196 continue;
6197 }
6198 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006199 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006200 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006201 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6202 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006204 proc.killedBackground = true;
6205 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
6207 }
6208 }
6209 return killed;
6210 }
6211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 public final void startRunning(String pkg, String cls, String action,
6213 String data) {
6214 synchronized(this) {
6215 if (mStartRunning) {
6216 return;
6217 }
6218 mStartRunning = true;
6219 mTopComponent = pkg != null && cls != null
6220 ? new ComponentName(pkg, cls) : null;
6221 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6222 mTopData = data;
6223 if (!mSystemReady) {
6224 return;
6225 }
6226 }
6227
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006228 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006229 }
6230
6231 private void retrieveSettings() {
6232 final ContentResolver resolver = mContext.getContentResolver();
6233 String debugApp = Settings.System.getString(
6234 resolver, Settings.System.DEBUG_APP);
6235 boolean waitForDebugger = Settings.System.getInt(
6236 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6237 boolean alwaysFinishActivities = Settings.System.getInt(
6238 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6239
6240 Configuration configuration = new Configuration();
6241 Settings.System.getConfiguration(resolver, configuration);
6242
6243 synchronized (this) {
6244 mDebugApp = mOrigDebugApp = debugApp;
6245 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6246 mAlwaysFinishActivities = alwaysFinishActivities;
6247 // This happens before any activities are started, so we can
6248 // change mConfiguration in-place.
6249 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006250 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006251 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006252 }
6253 }
6254
6255 public boolean testIsSystemReady() {
6256 // no need to synchronize(this) just to read & return the value
6257 return mSystemReady;
6258 }
6259
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006260 private static File getCalledPreBootReceiversFile() {
6261 File dataDir = Environment.getDataDirectory();
6262 File systemDir = new File(dataDir, "system");
6263 File fname = new File(systemDir, "called_pre_boots.dat");
6264 return fname;
6265 }
6266
6267 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6268 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6269 File file = getCalledPreBootReceiversFile();
6270 FileInputStream fis = null;
6271 try {
6272 fis = new FileInputStream(file);
6273 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6274 int vers = dis.readInt();
6275 String codename = dis.readUTF();
6276 if (vers == android.os.Build.VERSION.SDK_INT
6277 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6278 int num = dis.readInt();
6279 while (num > 0) {
6280 num--;
6281 String pkg = dis.readUTF();
6282 String cls = dis.readUTF();
6283 lastDoneReceivers.add(new ComponentName(pkg, cls));
6284 }
6285 }
6286 } catch (FileNotFoundException e) {
6287 } catch (IOException e) {
6288 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6289 } finally {
6290 if (fis != null) {
6291 try {
6292 fis.close();
6293 } catch (IOException e) {
6294 }
6295 }
6296 }
6297 return lastDoneReceivers;
6298 }
6299
6300 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6301 File file = getCalledPreBootReceiversFile();
6302 FileOutputStream fos = null;
6303 DataOutputStream dos = null;
6304 try {
6305 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6306 fos = new FileOutputStream(file);
6307 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6308 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6309 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6310 dos.writeInt(list.size());
6311 for (int i=0; i<list.size(); i++) {
6312 dos.writeUTF(list.get(i).getPackageName());
6313 dos.writeUTF(list.get(i).getClassName());
6314 }
6315 } catch (IOException e) {
6316 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6317 file.delete();
6318 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006319 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006320 if (dos != null) {
6321 try {
6322 dos.close();
6323 } catch (IOException e) {
6324 // TODO Auto-generated catch block
6325 e.printStackTrace();
6326 }
6327 }
6328 }
6329 }
6330
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006331 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 // In the simulator, startRunning will never have been called, which
6333 // normally sets a few crucial variables. Do it here instead.
6334 if (!Process.supportsProcesses()) {
6335 mStartRunning = true;
6336 mTopAction = Intent.ACTION_MAIN;
6337 }
6338
6339 synchronized(this) {
6340 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006341 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 return;
6343 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006344
6345 // Check to see if there are any update receivers to run.
6346 if (!mDidUpdate) {
6347 if (mWaitingUpdate) {
6348 return;
6349 }
6350 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6351 List<ResolveInfo> ris = null;
6352 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006353 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006354 intent, null, 0);
6355 } catch (RemoteException e) {
6356 }
6357 if (ris != null) {
6358 for (int i=ris.size()-1; i>=0; i--) {
6359 if ((ris.get(i).activityInfo.applicationInfo.flags
6360 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6361 ris.remove(i);
6362 }
6363 }
6364 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006365
6366 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6367
6368 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006369 for (int i=0; i<ris.size(); i++) {
6370 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006371 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6372 if (lastDoneReceivers.contains(comp)) {
6373 ris.remove(i);
6374 i--;
6375 }
6376 }
6377
6378 for (int i=0; i<ris.size(); i++) {
6379 ActivityInfo ai = ris.get(i).activityInfo;
6380 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6381 doneReceivers.add(comp);
6382 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006383 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006384 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006385 finisher = new IIntentReceiver.Stub() {
6386 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006387 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006388 boolean sticky) {
6389 // The raw IIntentReceiver interface is called
6390 // with the AM lock held, so redispatch to
6391 // execute our code without the lock.
6392 mHandler.post(new Runnable() {
6393 public void run() {
6394 synchronized (ActivityManagerService.this) {
6395 mDidUpdate = true;
6396 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006397 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006398 systemReady(goingCallback);
6399 }
6400 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006401 }
6402 };
6403 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006404 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006405 broadcastIntentLocked(null, null, intent, null, finisher,
6406 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006407 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006408 mWaitingUpdate = true;
6409 }
6410 }
6411 }
6412 if (mWaitingUpdate) {
6413 return;
6414 }
6415 mDidUpdate = true;
6416 }
6417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006418 mSystemReady = true;
6419 if (!mStartRunning) {
6420 return;
6421 }
6422 }
6423
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006424 ArrayList<ProcessRecord> procsToKill = null;
6425 synchronized(mPidsSelfLocked) {
6426 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6427 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6428 if (!isAllowedWhileBooting(proc.info)){
6429 if (procsToKill == null) {
6430 procsToKill = new ArrayList<ProcessRecord>();
6431 }
6432 procsToKill.add(proc);
6433 }
6434 }
6435 }
6436
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006437 synchronized(this) {
6438 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006439 for (int i=procsToKill.size()-1; i>=0; i--) {
6440 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006441 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006442 removeProcessLocked(proc, true);
6443 }
6444 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006445
6446 // Now that we have cleaned up any update processes, we
6447 // are ready to start launching real processes and know that
6448 // we won't trample on them any more.
6449 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006450 }
6451
Joe Onorato8a9b2202010-02-26 18:56:32 -08006452 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006453 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006454 SystemClock.uptimeMillis());
6455
6456 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006457 // Make sure we have no pre-ready processes sitting around.
6458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6460 ResolveInfo ri = mContext.getPackageManager()
6461 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006462 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 CharSequence errorMsg = null;
6464 if (ri != null) {
6465 ActivityInfo ai = ri.activityInfo;
6466 ApplicationInfo app = ai.applicationInfo;
6467 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6468 mTopAction = Intent.ACTION_FACTORY_TEST;
6469 mTopData = null;
6470 mTopComponent = new ComponentName(app.packageName,
6471 ai.name);
6472 } else {
6473 errorMsg = mContext.getResources().getText(
6474 com.android.internal.R.string.factorytest_not_system);
6475 }
6476 } else {
6477 errorMsg = mContext.getResources().getText(
6478 com.android.internal.R.string.factorytest_no_action);
6479 }
6480 if (errorMsg != null) {
6481 mTopAction = null;
6482 mTopData = null;
6483 mTopComponent = null;
6484 Message msg = Message.obtain();
6485 msg.what = SHOW_FACTORY_ERROR_MSG;
6486 msg.getData().putCharSequence("msg", errorMsg);
6487 mHandler.sendMessage(msg);
6488 }
6489 }
6490 }
6491
6492 retrieveSettings();
6493
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006494 if (goingCallback != null) goingCallback.run();
6495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 synchronized (this) {
6497 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6498 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006499 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006500 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 if (apps != null) {
6502 int N = apps.size();
6503 int i;
6504 for (i=0; i<N; i++) {
6505 ApplicationInfo info
6506 = (ApplicationInfo)apps.get(i);
6507 if (info != null &&
6508 !info.packageName.equals("android")) {
6509 addAppLocked(info);
6510 }
6511 }
6512 }
6513 } catch (RemoteException ex) {
6514 // pm is in same process, this will never happen.
6515 }
6516 }
6517
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006518 // Start up initial activity.
6519 mBooting = true;
6520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006522 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 Message msg = Message.obtain();
6524 msg.what = SHOW_UID_ERROR_MSG;
6525 mHandler.sendMessage(msg);
6526 }
6527 } catch (RemoteException e) {
6528 }
6529
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006530 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 }
6532 }
6533
Dan Egnorb7f03672009-12-09 16:22:32 -08006534 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006535 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006537 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006538 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 startAppProblemLocked(app);
6540 app.stopFreezingAllLocked();
6541 return handleAppCrashLocked(app);
6542 }
6543
Dan Egnorb7f03672009-12-09 16:22:32 -08006544 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006545 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006547 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006548 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6549 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006550 startAppProblemLocked(app);
6551 app.stopFreezingAllLocked();
6552 }
6553
6554 /**
6555 * Generate a process error record, suitable for attachment to a ProcessRecord.
6556 *
6557 * @param app The ProcessRecord in which the error occurred.
6558 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6559 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006560 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 * @param shortMsg Short message describing the crash.
6562 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006563 * @param stackTrace Full crash stack trace, may be null.
6564 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 * @return Returns a fully-formed AppErrorStateInfo record.
6566 */
6567 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006568 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 report.condition = condition;
6572 report.processName = app.processName;
6573 report.pid = app.pid;
6574 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006575 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 report.shortMsg = shortMsg;
6577 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006578 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006579
6580 return report;
6581 }
6582
Dan Egnor42471dd2010-01-07 17:25:22 -08006583 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 synchronized (this) {
6585 app.crashing = false;
6586 app.crashingReport = null;
6587 app.notResponding = false;
6588 app.notRespondingReport = null;
6589 if (app.anrDialog == fromDialog) {
6590 app.anrDialog = null;
6591 }
6592 if (app.waitDialog == fromDialog) {
6593 app.waitDialog = null;
6594 }
6595 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006596 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006597 Slog.i(ActivityManagerService.TAG, "Killing "
6598 + app.processName + " (pid=" + app.pid + "): user's request");
6599 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6600 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006601 Process.killProcess(app.pid);
6602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006603 }
6604 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006605
Dan Egnorb7f03672009-12-09 16:22:32 -08006606 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006607 long now = SystemClock.uptimeMillis();
6608
6609 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6610 app.info.uid);
6611 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6612 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006613 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006615 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006616 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006617 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6618 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006620 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006622 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006623 }
6624 }
6625 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006626 // Don't let services in this process be restarted and potentially
6627 // annoy the user repeatedly. Unless it is persistent, since those
6628 // processes run critical code.
6629 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 // We don't want to start this process again until the user
6631 // explicitly does so... but for persistent process, we really
6632 // need to keep it running. If a persistent process is actually
6633 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006634 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 app.info.processName);
6636 mBadProcesses.put(app.info.processName, app.info.uid, now);
6637 app.bad = true;
6638 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6639 app.removed = true;
6640 removeProcessLocked(app, false);
6641 return false;
6642 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006643 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006644 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006645 if (r.app == app) {
6646 // If the top running activity is from this crashing
6647 // process, then terminate it to avoid getting in a loop.
6648 Slog.w(TAG, " Force finishing activity "
6649 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006650 int index = mMainStack.indexOfTokenLocked(r);
6651 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006652 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006653 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006654 // stopped, to avoid a situation where one will get
6655 // re-start our crashing activity once it gets resumed again.
6656 index--;
6657 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006658 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006659 if (r.state == ActivityState.RESUMED
6660 || r.state == ActivityState.PAUSING
6661 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006662 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006663 Slog.w(TAG, " Force finishing activity "
6664 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006665 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006666 Activity.RESULT_CANCELED, null, "crashed");
6667 }
6668 }
6669 }
6670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006671 }
6672
6673 // Bump up the crash count of any services currently running in the proc.
6674 if (app.services.size() != 0) {
6675 // Any services running in the application need to be placed
6676 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006677 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006678 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006679 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006680 sr.crashCount++;
6681 }
6682 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006683
6684 // If the crashing process is what we consider to be the "home process" and it has been
6685 // replaced by a third-party app, clear the package preferred activities from packages
6686 // with a home activity running in the process to prevent a repeatedly crashing app
6687 // from blocking the user to manually clear the list.
6688 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6689 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6690 Iterator it = mHomeProcess.activities.iterator();
6691 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006692 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006693 if (r.isHomeActivity) {
6694 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6695 try {
6696 ActivityThread.getPackageManager()
6697 .clearPackagePreferredActivities(r.packageName);
6698 } catch (RemoteException c) {
6699 // pm is in same process, this will never happen.
6700 }
6701 }
6702 }
6703 }
6704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6706 return true;
6707 }
6708
6709 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006710 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6711 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 skipCurrentReceiverLocked(app);
6713 }
6714
6715 void skipCurrentReceiverLocked(ProcessRecord app) {
6716 boolean reschedule = false;
6717 BroadcastRecord r = app.curReceiver;
6718 if (r != null) {
6719 // The current broadcast is waiting for this app's receiver
6720 // to be finished. Looks like that's not going to happen, so
6721 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006722 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006723 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6724 r.resultExtras, r.resultAbort, true);
6725 reschedule = true;
6726 }
6727 r = mPendingBroadcast;
6728 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006729 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006731 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6733 r.resultExtras, r.resultAbort, true);
6734 reschedule = true;
6735 }
6736 if (reschedule) {
6737 scheduleBroadcastsLocked();
6738 }
6739 }
6740
Dan Egnor60d87622009-12-16 16:32:58 -08006741 /**
6742 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6743 * The application process will exit immediately after this call returns.
6744 * @param app object of the crashing app, null for the system server
6745 * @param crashInfo describing the exception
6746 */
6747 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6748 ProcessRecord r = findAppProcess(app);
6749
6750 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6751 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006752 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006753 crashInfo.exceptionClassName,
6754 crashInfo.exceptionMessage,
6755 crashInfo.throwFileName,
6756 crashInfo.throwLineNumber);
6757
Dan Egnor42471dd2010-01-07 17:25:22 -08006758 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006759
6760 crashApplication(r, crashInfo);
6761 }
6762
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006763 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006764 IBinder app,
6765 int violationMask,
6766 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006767 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006768
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006769 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006770 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006771 boolean logIt = true;
6772 synchronized (mAlreadyLoggedViolatedStacks) {
6773 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6774 logIt = false;
6775 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006776 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006777 // the relative pain numbers, without logging all
6778 // the stack traces repeatedly. We'd want to do
6779 // likewise in the client code, which also does
6780 // dup suppression, before the Binder call.
6781 } else {
6782 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6783 mAlreadyLoggedViolatedStacks.clear();
6784 }
6785 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6786 }
6787 }
6788 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006789 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006790 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006791 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006792
6793 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6794 AppErrorResult result = new AppErrorResult();
6795 synchronized (this) {
6796 final long origId = Binder.clearCallingIdentity();
6797
6798 Message msg = Message.obtain();
6799 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6800 HashMap<String, Object> data = new HashMap<String, Object>();
6801 data.put("result", result);
6802 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006803 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006804 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006805 msg.obj = data;
6806 mHandler.sendMessage(msg);
6807
6808 Binder.restoreCallingIdentity(origId);
6809 }
6810 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006811 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006812 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006813 }
6814
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006815 // Depending on the policy in effect, there could be a bunch of
6816 // these in quick succession so we try to batch these together to
6817 // minimize disk writes, number of dropbox entries, and maximize
6818 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006819 private void logStrictModeViolationToDropBox(
6820 ProcessRecord process,
6821 StrictMode.ViolationInfo info) {
6822 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006823 return;
6824 }
6825 final boolean isSystemApp = process == null ||
6826 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6827 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6828 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6829 final DropBoxManager dbox = (DropBoxManager)
6830 mContext.getSystemService(Context.DROPBOX_SERVICE);
6831
6832 // Exit early if the dropbox isn't configured to accept this report type.
6833 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6834
6835 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006836 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006837 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6838 synchronized (sb) {
6839 bufferWasEmpty = sb.length() == 0;
6840 appendDropBoxProcessHeaders(process, sb);
6841 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6842 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006843 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6844 if (info.violationNumThisLoop != 0) {
6845 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6846 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006847 if (info.numAnimationsRunning != 0) {
6848 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6849 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006850 if (info.broadcastIntentAction != null) {
6851 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6852 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006853 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006854 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006855 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006856 if (info.numInstances != -1) {
6857 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6858 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006859 if (info.tags != null) {
6860 for (String tag : info.tags) {
6861 sb.append("Span-Tag: ").append(tag).append("\n");
6862 }
6863 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006864 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006865 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6866 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006867 }
6868 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006869
6870 // Only buffer up to ~64k. Various logging bits truncate
6871 // things at 128k.
6872 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006873 }
6874
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006875 // Flush immediately if the buffer's grown too large, or this
6876 // is a non-system app. Non-system apps are isolated with a
6877 // different tag & policy and not batched.
6878 //
6879 // Batching is useful during internal testing with
6880 // StrictMode settings turned up high. Without batching,
6881 // thousands of separate files could be created on boot.
6882 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006883 new Thread("Error dump: " + dropboxTag) {
6884 @Override
6885 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006886 String report;
6887 synchronized (sb) {
6888 report = sb.toString();
6889 sb.delete(0, sb.length());
6890 sb.trimToSize();
6891 }
6892 if (report.length() != 0) {
6893 dbox.addText(dropboxTag, report);
6894 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006895 }
6896 }.start();
6897 return;
6898 }
6899
6900 // System app batching:
6901 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006902 // An existing dropbox-writing thread is outstanding, so
6903 // we don't need to start it up. The existing thread will
6904 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006905 return;
6906 }
6907
6908 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6909 // (After this point, we shouldn't access AMS internal data structures.)
6910 new Thread("Error dump: " + dropboxTag) {
6911 @Override
6912 public void run() {
6913 // 5 second sleep to let stacks arrive and be batched together
6914 try {
6915 Thread.sleep(5000); // 5 seconds
6916 } catch (InterruptedException e) {}
6917
6918 String errorReport;
6919 synchronized (mStrictModeBuffer) {
6920 errorReport = mStrictModeBuffer.toString();
6921 if (errorReport.length() == 0) {
6922 return;
6923 }
6924 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6925 mStrictModeBuffer.trimToSize();
6926 }
6927 dbox.addText(dropboxTag, errorReport);
6928 }
6929 }.start();
6930 }
6931
Dan Egnor60d87622009-12-16 16:32:58 -08006932 /**
6933 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6934 * @param app object of the crashing app, null for the system server
6935 * @param tag reported by the caller
6936 * @param crashInfo describing the context of the error
6937 * @return true if the process should exit immediately (WTF is fatal)
6938 */
6939 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006940 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006941 ProcessRecord r = findAppProcess(app);
6942
6943 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6944 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006945 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006946 tag, crashInfo.exceptionMessage);
6947
Dan Egnor42471dd2010-01-07 17:25:22 -08006948 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006949
Doug Zongker43866e02010-01-07 12:09:54 -08006950 if (Settings.Secure.getInt(mContext.getContentResolver(),
6951 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006952 crashApplication(r, crashInfo);
6953 return true;
6954 } else {
6955 return false;
6956 }
6957 }
6958
6959 /**
6960 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6961 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6962 */
6963 private ProcessRecord findAppProcess(IBinder app) {
6964 if (app == null) {
6965 return null;
6966 }
6967
6968 synchronized (this) {
6969 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6970 final int NA = apps.size();
6971 for (int ia=0; ia<NA; ia++) {
6972 ProcessRecord p = apps.valueAt(ia);
6973 if (p.thread != null && p.thread.asBinder() == app) {
6974 return p;
6975 }
6976 }
6977 }
6978
Joe Onorato8a9b2202010-02-26 18:56:32 -08006979 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006980 return null;
6981 }
6982 }
6983
6984 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006985 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6986 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006987 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006988 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6989 // Note: ProcessRecord 'process' is guarded by the service
6990 // instance. (notably process.pkgList, which could otherwise change
6991 // concurrently during execution of this method)
6992 synchronized (this) {
6993 if (process == null || process.pid == MY_PID) {
6994 sb.append("Process: system_server\n");
6995 } else {
6996 sb.append("Process: ").append(process.processName).append("\n");
6997 }
6998 if (process == null) {
6999 return;
7000 }
Dan Egnora455d192010-03-12 08:52:28 -08007001 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007002 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007003 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7004 for (String pkg : process.pkgList) {
7005 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007006 try {
Dan Egnora455d192010-03-12 08:52:28 -08007007 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7008 if (pi != null) {
7009 sb.append(" v").append(pi.versionCode);
7010 if (pi.versionName != null) {
7011 sb.append(" (").append(pi.versionName).append(")");
7012 }
7013 }
7014 } catch (RemoteException e) {
7015 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007016 }
Dan Egnora455d192010-03-12 08:52:28 -08007017 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007018 }
Dan Egnora455d192010-03-12 08:52:28 -08007019 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007020 }
7021
7022 private static String processClass(ProcessRecord process) {
7023 if (process == null || process.pid == MY_PID) {
7024 return "system_server";
7025 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7026 return "system_app";
7027 } else {
7028 return "data_app";
7029 }
7030 }
7031
7032 /**
7033 * Write a description of an error (crash, WTF, ANR) to the drop box.
7034 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7035 * @param process which caused the error, null means the system server
7036 * @param activity which triggered the error, null if unknown
7037 * @param parent activity related to the error, null if unknown
7038 * @param subject line related to the error, null if absent
7039 * @param report in long form describing the error, null if absent
7040 * @param logFile to include in the report, null if none
7041 * @param crashInfo giving an application stack trace, null if absent
7042 */
7043 public void addErrorToDropBox(String eventType,
7044 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7045 final String report, final File logFile,
7046 final ApplicationErrorReport.CrashInfo crashInfo) {
7047 // NOTE -- this must never acquire the ActivityManagerService lock,
7048 // otherwise the watchdog may be prevented from resetting the system.
7049
7050 final String dropboxTag = processClass(process) + "_" + eventType;
7051 final DropBoxManager dbox = (DropBoxManager)
7052 mContext.getSystemService(Context.DROPBOX_SERVICE);
7053
7054 // Exit early if the dropbox isn't configured to accept this report type.
7055 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7056
7057 final StringBuilder sb = new StringBuilder(1024);
7058 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007059 if (activity != null) {
7060 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7061 }
7062 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7063 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7064 }
7065 if (parent != null && parent != activity) {
7066 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7067 }
7068 if (subject != null) {
7069 sb.append("Subject: ").append(subject).append("\n");
7070 }
7071 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007072 if (Debug.isDebuggerConnected()) {
7073 sb.append("Debugger: Connected\n");
7074 }
Dan Egnora455d192010-03-12 08:52:28 -08007075 sb.append("\n");
7076
7077 // Do the rest in a worker thread to avoid blocking the caller on I/O
7078 // (After this point, we shouldn't access AMS internal data structures.)
7079 Thread worker = new Thread("Error dump: " + dropboxTag) {
7080 @Override
7081 public void run() {
7082 if (report != null) {
7083 sb.append(report);
7084 }
7085 if (logFile != null) {
7086 try {
7087 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7088 } catch (IOException e) {
7089 Slog.e(TAG, "Error reading " + logFile, e);
7090 }
7091 }
7092 if (crashInfo != null && crashInfo.stackTrace != null) {
7093 sb.append(crashInfo.stackTrace);
7094 }
7095
7096 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7097 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7098 if (lines > 0) {
7099 sb.append("\n");
7100
7101 // Merge several logcat streams, and take the last N lines
7102 InputStreamReader input = null;
7103 try {
7104 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7105 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7106 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7107
7108 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7109 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7110 input = new InputStreamReader(logcat.getInputStream());
7111
7112 int num;
7113 char[] buf = new char[8192];
7114 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7115 } catch (IOException e) {
7116 Slog.e(TAG, "Error running logcat", e);
7117 } finally {
7118 if (input != null) try { input.close(); } catch (IOException e) {}
7119 }
7120 }
7121
7122 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007123 }
Dan Egnora455d192010-03-12 08:52:28 -08007124 };
7125
7126 if (process == null || process.pid == MY_PID) {
7127 worker.run(); // We may be about to die -- need to run this synchronously
7128 } else {
7129 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007130 }
7131 }
7132
7133 /**
7134 * Bring up the "unexpected error" dialog box for a crashing app.
7135 * Deal with edge cases (intercepts from instrumented applications,
7136 * ActivityController, error intent receivers, that sort of thing).
7137 * @param r the application crashing
7138 * @param crashInfo describing the failure
7139 */
7140 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007141 long timeMillis = System.currentTimeMillis();
7142 String shortMsg = crashInfo.exceptionClassName;
7143 String longMsg = crashInfo.exceptionMessage;
7144 String stackTrace = crashInfo.stackTrace;
7145 if (shortMsg != null && longMsg != null) {
7146 longMsg = shortMsg + ": " + longMsg;
7147 } else if (shortMsg != null) {
7148 longMsg = shortMsg;
7149 }
7150
Dan Egnor60d87622009-12-16 16:32:58 -08007151 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007153 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007154 try {
7155 String name = r != null ? r.processName : null;
7156 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007157 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007158 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007159 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 + " at watcher's request");
7161 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007162 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007163 }
7164 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007165 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007166 }
7167 }
7168
7169 final long origId = Binder.clearCallingIdentity();
7170
7171 // If this process is running instrumentation, finish it.
7172 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007173 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007175 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7176 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 Bundle info = new Bundle();
7178 info.putString("shortMsg", shortMsg);
7179 info.putString("longMsg", longMsg);
7180 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7181 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007182 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007183 }
7184
Dan Egnor60d87622009-12-16 16:32:58 -08007185 // If we can't identify the process or it's already exceeded its crash quota,
7186 // quit right away without showing a crash dialog.
7187 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007189 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 }
7191
7192 Message msg = Message.obtain();
7193 msg.what = SHOW_ERROR_MSG;
7194 HashMap data = new HashMap();
7195 data.put("result", result);
7196 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 msg.obj = data;
7198 mHandler.sendMessage(msg);
7199
7200 Binder.restoreCallingIdentity(origId);
7201 }
7202
7203 int res = result.get();
7204
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007205 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 synchronized (this) {
7207 if (r != null) {
7208 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7209 SystemClock.uptimeMillis());
7210 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007211 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007212 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007213 }
7214 }
7215
7216 if (appErrorIntent != null) {
7217 try {
7218 mContext.startActivity(appErrorIntent);
7219 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007220 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007223 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007224
7225 Intent createAppErrorIntentLocked(ProcessRecord r,
7226 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7227 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007228 if (report == null) {
7229 return null;
7230 }
7231 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7232 result.setComponent(r.errorReportReceiver);
7233 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7234 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7235 return result;
7236 }
7237
Dan Egnorb7f03672009-12-09 16:22:32 -08007238 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7239 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007240 if (r.errorReportReceiver == null) {
7241 return null;
7242 }
7243
7244 if (!r.crashing && !r.notResponding) {
7245 return null;
7246 }
7247
Dan Egnorb7f03672009-12-09 16:22:32 -08007248 ApplicationErrorReport report = new ApplicationErrorReport();
7249 report.packageName = r.info.packageName;
7250 report.installerPackageName = r.errorReportReceiver.getPackageName();
7251 report.processName = r.processName;
7252 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007253 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007254
Dan Egnorb7f03672009-12-09 16:22:32 -08007255 if (r.crashing) {
7256 report.type = ApplicationErrorReport.TYPE_CRASH;
7257 report.crashInfo = crashInfo;
7258 } else if (r.notResponding) {
7259 report.type = ApplicationErrorReport.TYPE_ANR;
7260 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007261
Dan Egnorb7f03672009-12-09 16:22:32 -08007262 report.anrInfo.activity = r.notRespondingReport.tag;
7263 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7264 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007265 }
7266
Dan Egnorb7f03672009-12-09 16:22:32 -08007267 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007268 }
7269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7271 // assume our apps are happy - lazy create the list
7272 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7273
7274 synchronized (this) {
7275
7276 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007277 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7278 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7280 // This one's in trouble, so we'll generate a report for it
7281 // crashes are higher priority (in case there's a crash *and* an anr)
7282 ActivityManager.ProcessErrorStateInfo report = null;
7283 if (app.crashing) {
7284 report = app.crashingReport;
7285 } else if (app.notResponding) {
7286 report = app.notRespondingReport;
7287 }
7288
7289 if (report != null) {
7290 if (errList == null) {
7291 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7292 }
7293 errList.add(report);
7294 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007295 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 " crashing = " + app.crashing +
7297 " notResponding = " + app.notResponding);
7298 }
7299 }
7300 }
7301 }
7302
7303 return errList;
7304 }
7305
7306 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7307 // Lazy instantiation of list
7308 List<ActivityManager.RunningAppProcessInfo> runList = null;
7309 synchronized (this) {
7310 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007311 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7312 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007313 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7314 // Generate process state info for running application
7315 ActivityManager.RunningAppProcessInfo currApp =
7316 new ActivityManager.RunningAppProcessInfo(app.processName,
7317 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007318 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007319 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007320 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007321 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007322 if (app.persistent) {
7323 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7324 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007325 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007326 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007327 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7328 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7329 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007330 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7331 } else if (adj >= HOME_APP_ADJ) {
7332 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7333 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334 } else if (adj >= SECONDARY_SERVER_ADJ) {
7335 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007336 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007337 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007338 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7339 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 } else if (adj >= VISIBLE_APP_ADJ) {
7341 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7342 } else {
7343 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7344 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007345 currApp.importanceReasonCode = app.adjTypeCode;
7346 if (app.adjSource instanceof ProcessRecord) {
7347 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007348 } else if (app.adjSource instanceof ActivityRecord) {
7349 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007350 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7351 }
7352 if (app.adjTarget instanceof ComponentName) {
7353 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7354 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007355 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 // + " lru=" + currApp.lru);
7357 if (runList == null) {
7358 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7359 }
7360 runList.add(currApp);
7361 }
7362 }
7363 }
7364 return runList;
7365 }
7366
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007367 public List<ApplicationInfo> getRunningExternalApplications() {
7368 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7369 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7370 if (runningApps != null && runningApps.size() > 0) {
7371 Set<String> extList = new HashSet<String>();
7372 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7373 if (app.pkgList != null) {
7374 for (String pkg : app.pkgList) {
7375 extList.add(pkg);
7376 }
7377 }
7378 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007379 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007380 for (String pkg : extList) {
7381 try {
7382 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7383 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7384 retList.add(info);
7385 }
7386 } catch (RemoteException e) {
7387 }
7388 }
7389 }
7390 return retList;
7391 }
7392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 @Override
7394 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007395 if (checkCallingPermission(android.Manifest.permission.DUMP)
7396 != PackageManager.PERMISSION_GRANTED) {
7397 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7398 + Binder.getCallingPid()
7399 + ", uid=" + Binder.getCallingUid()
7400 + " without permission "
7401 + android.Manifest.permission.DUMP);
7402 return;
7403 }
7404
7405 boolean dumpAll = false;
7406
7407 int opti = 0;
7408 while (opti < args.length) {
7409 String opt = args[opti];
7410 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7411 break;
7412 }
7413 opti++;
7414 if ("-a".equals(opt)) {
7415 dumpAll = true;
7416 } else if ("-h".equals(opt)) {
7417 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007418 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007419 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007420 pw.println(" a[ctivities]: activity stack state");
7421 pw.println(" b[roadcasts]: broadcast state");
7422 pw.println(" i[ntents]: pending intent state");
7423 pw.println(" p[rocesses]: process state");
7424 pw.println(" o[om]: out of memory management");
7425 pw.println(" prov[iders]: content provider state");
7426 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007427 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007428 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7429 pw.println(" a partial substring in a component name, or an");
7430 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 } else {
7433 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007435 }
7436
7437 // Is the caller requesting to dump a particular piece of data?
7438 if (opti < args.length) {
7439 String cmd = args[opti];
7440 opti++;
7441 if ("activities".equals(cmd) || "a".equals(cmd)) {
7442 synchronized (this) {
7443 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007445 return;
7446 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7447 synchronized (this) {
7448 dumpBroadcastsLocked(fd, pw, args, opti, true);
7449 }
7450 return;
7451 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7452 synchronized (this) {
7453 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7454 }
7455 return;
7456 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7457 synchronized (this) {
7458 dumpProcessesLocked(fd, pw, args, opti, true);
7459 }
7460 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007461 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7462 synchronized (this) {
7463 dumpOomLocked(fd, pw, args, opti, true);
7464 }
7465 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007466 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7467 synchronized (this) {
7468 dumpProvidersLocked(fd, pw, args, opti, true);
7469 }
7470 return;
7471 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007472 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007473 return;
7474 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7475 synchronized (this) {
7476 dumpServicesLocked(fd, pw, args, opti, true);
7477 }
7478 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007479 } else {
7480 // Dumping a single activity?
7481 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7482 return;
7483 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007484 pw.println("Bad activity command, or no activities match: " + cmd);
7485 pw.println("Use -h for help.");
7486 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007488 }
7489
7490 // No piece of data specified, dump everything.
7491 synchronized (this) {
7492 boolean needSep;
7493 if (dumpAll) {
7494 pw.println("Providers in Current Activity Manager State:");
7495 }
7496 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7497 if (needSep) {
7498 pw.println(" ");
7499 }
7500 if (dumpAll) {
7501 pw.println("-------------------------------------------------------------------------------");
7502 pw.println("Broadcasts in Current Activity Manager State:");
7503 }
7504 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7505 if (needSep) {
7506 pw.println(" ");
7507 }
7508 if (dumpAll) {
7509 pw.println("-------------------------------------------------------------------------------");
7510 pw.println("Services in Current Activity Manager State:");
7511 }
7512 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7513 if (needSep) {
7514 pw.println(" ");
7515 }
7516 if (dumpAll) {
7517 pw.println("-------------------------------------------------------------------------------");
7518 pw.println("PendingIntents in Current Activity Manager State:");
7519 }
7520 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7521 if (needSep) {
7522 pw.println(" ");
7523 }
7524 if (dumpAll) {
7525 pw.println("-------------------------------------------------------------------------------");
7526 pw.println("Activities in Current Activity Manager State:");
7527 }
7528 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7529 if (needSep) {
7530 pw.println(" ");
7531 }
7532 if (dumpAll) {
7533 pw.println("-------------------------------------------------------------------------------");
7534 pw.println("Processes in Current Activity Manager State:");
7535 }
7536 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7537 }
7538 }
7539
7540 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7541 int opti, boolean dumpAll, boolean needHeader) {
7542 if (needHeader) {
7543 pw.println(" Activity stack:");
7544 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007545 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007546 pw.println(" ");
7547 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007548 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7549 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007551 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007552 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007553 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007554 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007555 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007556 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007557 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007558 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007559 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7560 pw.println(" ");
7561 pw.println(" Activities waiting to sleep:");
7562 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7563 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007564 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007565 pw.println(" ");
7566 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007567 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007570 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007571 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7572 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007573 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007574 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007575 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007577 if (dumpAll && mRecentTasks.size() > 0) {
7578 pw.println(" ");
7579 pw.println("Recent tasks in Current Activity Manager State:");
7580
7581 final int N = mRecentTasks.size();
7582 for (int i=0; i<N; i++) {
7583 TaskRecord tr = mRecentTasks.get(i);
7584 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7585 pw.println(tr);
7586 mRecentTasks.get(i).dump(pw, " ");
7587 }
7588 }
7589
7590 pw.println(" ");
7591 pw.println(" mCurTask: " + mCurTask);
7592
7593 return true;
7594 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007595
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007596 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7597 int opti, boolean dumpAll) {
7598 boolean needSep = false;
7599 int numPers = 0;
7600
7601 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7603 final int NA = procs.size();
7604 for (int ia=0; ia<NA; ia++) {
7605 if (!needSep) {
7606 pw.println(" All known processes:");
7607 needSep = true;
7608 }
7609 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007610 pw.print(r.persistent ? " *PERS*" : " *APP*");
7611 pw.print(" UID "); pw.print(procs.keyAt(ia));
7612 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 r.dump(pw, " ");
7614 if (r.persistent) {
7615 numPers++;
7616 }
7617 }
7618 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007619 }
7620
7621 if (mLruProcesses.size() > 0) {
7622 if (needSep) pw.println(" ");
7623 needSep = true;
7624 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007625 dumpProcessOomList(pw, this, mLruProcesses, " ",
7626 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007627 needSep = true;
7628 }
7629
7630 synchronized (mPidsSelfLocked) {
7631 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 if (needSep) pw.println(" ");
7633 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007634 pw.println(" PID mappings:");
7635 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7636 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7637 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007638 }
7639 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007640 }
7641
7642 if (mForegroundProcesses.size() > 0) {
7643 if (needSep) pw.println(" ");
7644 needSep = true;
7645 pw.println(" Foreground Processes:");
7646 for (int i=0; i<mForegroundProcesses.size(); i++) {
7647 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7648 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007649 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007650 }
7651
7652 if (mPersistentStartingProcesses.size() > 0) {
7653 if (needSep) pw.println(" ");
7654 needSep = true;
7655 pw.println(" Persisent processes that are starting:");
7656 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007657 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007660 if (mStartingProcesses.size() > 0) {
7661 if (needSep) pw.println(" ");
7662 needSep = true;
7663 pw.println(" Processes that are starting:");
7664 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007665 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 if (mRemovedProcesses.size() > 0) {
7669 if (needSep) pw.println(" ");
7670 needSep = true;
7671 pw.println(" Processes that are being removed:");
7672 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007673 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007674 }
7675
7676 if (mProcessesOnHold.size() > 0) {
7677 if (needSep) pw.println(" ");
7678 needSep = true;
7679 pw.println(" Processes that are on old until the system is ready:");
7680 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007681 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683
Dianne Hackborn287952c2010-09-22 22:34:31 -07007684 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007685
7686 if (mProcessCrashTimes.getMap().size() > 0) {
7687 if (needSep) pw.println(" ");
7688 needSep = true;
7689 pw.println(" Time since processes crashed:");
7690 long now = SystemClock.uptimeMillis();
7691 for (Map.Entry<String, SparseArray<Long>> procs
7692 : mProcessCrashTimes.getMap().entrySet()) {
7693 SparseArray<Long> uids = procs.getValue();
7694 final int N = uids.size();
7695 for (int i=0; i<N; i++) {
7696 pw.print(" Process "); pw.print(procs.getKey());
7697 pw.print(" uid "); pw.print(uids.keyAt(i));
7698 pw.print(": last crashed ");
7699 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007700 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007701 }
7702 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007705 if (mBadProcesses.getMap().size() > 0) {
7706 if (needSep) pw.println(" ");
7707 needSep = true;
7708 pw.println(" Bad processes:");
7709 for (Map.Entry<String, SparseArray<Long>> procs
7710 : mBadProcesses.getMap().entrySet()) {
7711 SparseArray<Long> uids = procs.getValue();
7712 final int N = uids.size();
7713 for (int i=0; i<N; i++) {
7714 pw.print(" Bad process "); pw.print(procs.getKey());
7715 pw.print(" uid "); pw.print(uids.keyAt(i));
7716 pw.print(": crashed at time ");
7717 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 }
7719 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007721
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007722 pw.println(" ");
7723 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007724 if (mHeavyWeightProcess != null) {
7725 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7726 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007727 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007728 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7730 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7731 || mOrigWaitForDebugger) {
7732 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7733 + " mDebugTransient=" + mDebugTransient
7734 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7735 }
7736 if (mAlwaysFinishActivities || mController != null) {
7737 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7738 + " mController=" + mController);
7739 }
7740 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007743 + " mProcessesReady=" + mProcessesReady
7744 + " mSystemReady=" + mSystemReady);
7745 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 + " mBooted=" + mBooted
7747 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007748 pw.print(" mLastPowerCheckRealtime=");
7749 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7750 pw.println("");
7751 pw.print(" mLastPowerCheckUptime=");
7752 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7753 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007754 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7755 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007756 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007757 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007758
7759 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 }
7761
Dianne Hackborn287952c2010-09-22 22:34:31 -07007762 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7763 int opti, boolean needSep, boolean dumpAll) {
7764 if (mProcessesToGc.size() > 0) {
7765 if (needSep) pw.println(" ");
7766 needSep = true;
7767 pw.println(" Processes that are waiting to GC:");
7768 long now = SystemClock.uptimeMillis();
7769 for (int i=0; i<mProcessesToGc.size(); i++) {
7770 ProcessRecord proc = mProcessesToGc.get(i);
7771 pw.print(" Process "); pw.println(proc);
7772 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7773 pw.print(", last gced=");
7774 pw.print(now-proc.lastRequestedGc);
7775 pw.print(" ms ago, last lowMem=");
7776 pw.print(now-proc.lastLowMemory);
7777 pw.println(" ms ago");
7778
7779 }
7780 }
7781 return needSep;
7782 }
7783
7784 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7785 int opti, boolean dumpAll) {
7786 boolean needSep = false;
7787
7788 if (mLruProcesses.size() > 0) {
7789 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7790
7791 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7792 @Override
7793 public int compare(ProcessRecord object1, ProcessRecord object2) {
7794 if (object1.setAdj != object2.setAdj) {
7795 return object1.setAdj > object2.setAdj ? -1 : 1;
7796 }
7797 if (object1.setSchedGroup != object2.setSchedGroup) {
7798 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7799 }
7800 if (object1.keeping != object2.keeping) {
7801 return object1.keeping ? -1 : 1;
7802 }
7803 if (object1.pid != object2.pid) {
7804 return object1.pid > object2.pid ? -1 : 1;
7805 }
7806 return 0;
7807 }
7808 };
7809
7810 Collections.sort(procs, comparator);
7811
7812 if (needSep) pw.println(" ");
7813 needSep = true;
7814 pw.println(" Process OOM control:");
7815 dumpProcessOomList(pw, this, procs, " ",
7816 "Proc", "PERS", true);
7817 needSep = true;
7818 }
7819
7820 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7821
7822 pw.println(" ");
7823 pw.println(" mHomeProcess: " + mHomeProcess);
7824 if (mHeavyWeightProcess != null) {
7825 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7826 }
7827
7828 return true;
7829 }
7830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 /**
7832 * There are three ways to call this:
7833 * - no service specified: dump all the services
7834 * - a flattened component name that matched an existing service was specified as the
7835 * first arg: dump that one service
7836 * - the first arg isn't the flattened component name of an existing service:
7837 * dump all services whose component contains the first arg as a substring
7838 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007839 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 String[] newArgs;
7841 String componentNameString;
7842 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007843 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844 componentNameString = null;
7845 newArgs = EMPTY_STRING_ARRAY;
7846 r = null;
7847 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007848 componentNameString = args[opti];
7849 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007850 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007851 synchronized (this) {
7852 r = componentName != null ? mServices.get(componentName) : null;
7853 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007854 newArgs = new String[args.length - opti];
7855 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 }
7857
7858 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007859 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007861 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7862 synchronized (this) {
7863 for (ServiceRecord r1 : mServices.values()) {
7864 if (componentNameString == null
7865 || r1.name.flattenToString().contains(componentNameString)) {
7866 services.add(r1);
7867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 }
7869 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007870 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007871 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007873 }
7874 }
7875
7876 /**
7877 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7878 * there is a thread associated with the service.
7879 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007880 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7881 pw.println("------------------------------------------------------------"
7882 + "-------------------");
7883 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 if (r.app != null && r.app.thread != null) {
7885 try {
7886 // flush anything that is already in the PrintWriter since the thread is going
7887 // to write to the file descriptor directly
7888 pw.flush();
7889 r.app.thread.dumpService(fd, r, args);
7890 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007891 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 } catch (RemoteException e) {
7893 pw.println("got a RemoteException while dumping the service");
7894 }
7895 }
7896 }
7897
Dianne Hackborn625ac272010-09-17 18:29:22 -07007898 /**
7899 * There are three things that cmd can be:
7900 * - a flattened component name that matched an existing activity
7901 * - the cmd arg isn't the flattened component name of an existing activity:
7902 * dump all activity whose component contains the cmd as a substring
7903 * - A hex number of the ActivityRecord object instance.
7904 */
7905 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7906 int opti, boolean dumpAll) {
7907 String[] newArgs;
7908 ComponentName componentName = ComponentName.unflattenFromString(name);
7909 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007910 if (componentName == null) {
7911 // Not a '/' separated full component name; maybe an object ID?
7912 try {
7913 objectId = Integer.parseInt(name, 16);
7914 name = null;
7915 componentName = null;
7916 } catch (RuntimeException e) {
7917 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007918 }
7919 newArgs = new String[args.length - opti];
7920 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7921
7922 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7923 synchronized (this) {
7924 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7925 if (componentName != null) {
7926 if (r1.intent.getComponent().equals(componentName)) {
7927 activities.add(r1);
7928 }
7929 } else if (name != null) {
7930 if (r1.intent.getComponent().flattenToString().contains(name)) {
7931 activities.add(r1);
7932 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007933 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007934 activities.add(r1);
7935 }
7936 }
7937 }
7938
7939 if (activities.size() <= 0) {
7940 return false;
7941 }
7942
Dianne Hackborn30d71892010-12-11 10:37:55 -08007943 TaskRecord lastTask = null;
7944 for (int i=activities.size()-1; i>=0; i--) {
7945 ActivityRecord r = (ActivityRecord)activities.get(i);
7946 if (lastTask != r.task) {
7947 lastTask = r.task;
7948 pw.print("* Task "); pw.print(lastTask.affinity);
7949 pw.print(" id="); pw.println(lastTask.taskId);
7950 if (dumpAll) {
7951 lastTask.dump(pw, " ");
7952 }
7953 }
7954 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007955 }
7956 return true;
7957 }
7958
7959 /**
7960 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7961 * there is a thread associated with the activity.
7962 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007963 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7964 ActivityRecord r, String[] args, boolean dumpAll) {
7965 synchronized (this) {
7966 pw.print(prefix); pw.print("* Activity ");
7967 pw.print(Integer.toHexString(System.identityHashCode(r)));
7968 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7969 if (r.app != null) pw.println(r.app.pid);
7970 else pw.println("(not running)");
7971 if (dumpAll) {
7972 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007973 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007974 }
7975 if (r.app != null && r.app.thread != null) {
7976 try {
7977 // flush anything that is already in the PrintWriter since the thread is going
7978 // to write to the file descriptor directly
7979 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08007980 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007981 pw.flush();
7982 } catch (RemoteException e) {
7983 pw.println("got a RemoteException while dumping the activity");
7984 }
7985 }
7986 }
7987
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007988 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7989 int opti, boolean dumpAll) {
7990 boolean needSep = false;
7991
7992 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007993 if (mRegisteredReceivers.size() > 0) {
7994 pw.println(" ");
7995 pw.println(" Registered Receivers:");
7996 Iterator it = mRegisteredReceivers.values().iterator();
7997 while (it.hasNext()) {
7998 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007999 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008000 r.dump(pw, " ");
8001 }
8002 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008004 pw.println(" ");
8005 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008006 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008007 needSep = true;
8008 }
8009
8010 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8011 || mPendingBroadcast != null) {
8012 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008016 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8017 pw.println(" Broadcast #" + i + ":");
8018 mParallelBroadcasts.get(i).dump(pw, " ");
8019 }
8020 if (mOrderedBroadcasts.size() > 0) {
8021 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008022 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008023 }
8024 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8025 pw.println(" Serialized Broadcast #" + i + ":");
8026 mOrderedBroadcasts.get(i).dump(pw, " ");
8027 }
8028 pw.println(" ");
8029 pw.println(" Pending broadcast:");
8030 if (mPendingBroadcast != null) {
8031 mPendingBroadcast.dump(pw, " ");
8032 } else {
8033 pw.println(" (null)");
8034 }
8035 needSep = true;
8036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008038 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008039 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008040 pw.println(" Historical broadcasts:");
8041 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8042 BroadcastRecord r = mBroadcastHistory[i];
8043 if (r == null) {
8044 break;
8045 }
8046 pw.println(" Historical Broadcast #" + i + ":");
8047 r.dump(pw, " ");
8048 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008049 needSep = true;
8050 }
8051
8052 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008053 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008054 pw.println(" Sticky broadcasts:");
8055 StringBuilder sb = new StringBuilder(128);
8056 for (Map.Entry<String, ArrayList<Intent>> ent
8057 : mStickyBroadcasts.entrySet()) {
8058 pw.print(" * Sticky action "); pw.print(ent.getKey());
8059 pw.println(":");
8060 ArrayList<Intent> intents = ent.getValue();
8061 final int N = intents.size();
8062 for (int i=0; i<N; i++) {
8063 sb.setLength(0);
8064 sb.append(" Intent: ");
8065 intents.get(i).toShortString(sb, true, false);
8066 pw.println(sb.toString());
8067 Bundle bundle = intents.get(i).getExtras();
8068 if (bundle != null) {
8069 pw.print(" ");
8070 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 }
8072 }
8073 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008074 needSep = true;
8075 }
8076
8077 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008078 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008079 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 pw.println(" mHandler:");
8081 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008082 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008084
8085 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 }
8087
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008088 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8089 int opti, boolean dumpAll) {
8090 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008092 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093 if (mServices.size() > 0) {
8094 pw.println(" Active services:");
8095 Iterator<ServiceRecord> it = mServices.values().iterator();
8096 while (it.hasNext()) {
8097 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008098 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008099 r.dump(pw, " ");
8100 }
8101 needSep = true;
8102 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008105 if (mPendingServices.size() > 0) {
8106 if (needSep) pw.println(" ");
8107 pw.println(" Pending services:");
8108 for (int i=0; i<mPendingServices.size(); i++) {
8109 ServiceRecord r = mPendingServices.get(i);
8110 pw.print(" * Pending "); pw.println(r);
8111 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008112 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008113 needSep = true;
8114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008116 if (mRestartingServices.size() > 0) {
8117 if (needSep) pw.println(" ");
8118 pw.println(" Restarting services:");
8119 for (int i=0; i<mRestartingServices.size(); i++) {
8120 ServiceRecord r = mRestartingServices.get(i);
8121 pw.print(" * Restarting "); pw.println(r);
8122 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008124 needSep = true;
8125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008126
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008127 if (mStoppingServices.size() > 0) {
8128 if (needSep) pw.println(" ");
8129 pw.println(" Stopping services:");
8130 for (int i=0; i<mStoppingServices.size(); i++) {
8131 ServiceRecord r = mStoppingServices.get(i);
8132 pw.print(" * Stopping "); pw.println(r);
8133 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008135 needSep = true;
8136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008138 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 if (mServiceConnections.size() > 0) {
8140 if (needSep) pw.println(" ");
8141 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008142 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 = mServiceConnections.values().iterator();
8144 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008145 ArrayList<ConnectionRecord> r = it.next();
8146 for (int i=0; i<r.size(); i++) {
8147 pw.print(" * "); pw.println(r.get(i));
8148 r.get(i).dump(pw, " ");
8149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008150 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008151 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008152 }
8153 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008154
8155 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156 }
8157
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008158 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8159 int opti, boolean dumpAll) {
8160 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008162 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008163 if (mProvidersByClass.size() > 0) {
8164 if (needSep) pw.println(" ");
8165 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008166 Iterator<Map.Entry<String, ContentProviderRecord>> it
8167 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008168 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008169 Map.Entry<String, ContentProviderRecord> e = it.next();
8170 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008171 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 r.dump(pw, " ");
8173 }
8174 needSep = true;
8175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008176
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008177 if (mProvidersByName.size() > 0) {
8178 pw.println(" ");
8179 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008180 Iterator<Map.Entry<String, ContentProviderRecord>> it
8181 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008182 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008183 Map.Entry<String, ContentProviderRecord> e = it.next();
8184 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008185 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8186 pw.println(r);
8187 }
8188 needSep = true;
8189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008191
8192 if (mLaunchingProviders.size() > 0) {
8193 if (needSep) pw.println(" ");
8194 pw.println(" Launching content providers:");
8195 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8196 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8197 pw.println(mLaunchingProviders.get(i));
8198 }
8199 needSep = true;
8200 }
8201
8202 if (mGrantedUriPermissions.size() > 0) {
8203 pw.println();
8204 pw.println("Granted Uri Permissions:");
8205 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8206 int uid = mGrantedUriPermissions.keyAt(i);
8207 HashMap<Uri, UriPermission> perms
8208 = mGrantedUriPermissions.valueAt(i);
8209 pw.print(" * UID "); pw.print(uid);
8210 pw.println(" holds:");
8211 for (UriPermission perm : perms.values()) {
8212 pw.print(" "); pw.println(perm);
8213 perm.dump(pw, " ");
8214 }
8215 }
8216 needSep = true;
8217 }
8218
8219 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 }
8221
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008222 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8223 int opti, boolean dumpAll) {
8224 boolean needSep = false;
8225
8226 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008227 if (this.mIntentSenderRecords.size() > 0) {
8228 Iterator<WeakReference<PendingIntentRecord>> it
8229 = mIntentSenderRecords.values().iterator();
8230 while (it.hasNext()) {
8231 WeakReference<PendingIntentRecord> ref = it.next();
8232 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008233 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008234 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008235 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 rec.dump(pw, " ");
8237 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008238 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008239 }
8240 }
8241 }
8242 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008243
8244 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 }
8246
8247 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008248 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 TaskRecord lastTask = null;
8250 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008251 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008252 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008253 if (lastTask != r.task) {
8254 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008255 pw.print(prefix);
8256 pw.print(full ? "* " : " ");
8257 pw.println(lastTask);
8258 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008259 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008262 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8263 pw.print(" #"); pw.print(i); pw.print(": ");
8264 pw.println(r);
8265 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008266 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 }
8269 }
8270
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008271 private static String buildOomTag(String prefix, String space, int val, int base) {
8272 if (val == base) {
8273 if (space == null) return prefix;
8274 return prefix + " ";
8275 }
8276 return prefix + "+" + Integer.toString(val-base);
8277 }
8278
8279 private static final int dumpProcessList(PrintWriter pw,
8280 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008281 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008283 final int N = list.size()-1;
8284 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008286 pw.println(String.format("%s%s #%2d: %s",
8287 prefix, (r.persistent ? persistentLabel : normalLabel),
8288 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 if (r.persistent) {
8290 numPers++;
8291 }
8292 }
8293 return numPers;
8294 }
8295
Dianne Hackborn287952c2010-09-22 22:34:31 -07008296 private static final void dumpProcessOomList(PrintWriter pw,
8297 ActivityManagerService service, List<ProcessRecord> list,
8298 String prefix, String normalLabel, String persistentLabel,
8299 boolean inclDetails) {
8300
8301 final long curRealtime = SystemClock.elapsedRealtime();
8302 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8303 final long curUptime = SystemClock.uptimeMillis();
8304 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8305
8306 final int N = list.size()-1;
8307 for (int i=N; i>=0; i--) {
8308 ProcessRecord r = list.get(i);
8309 String oomAdj;
8310 if (r.setAdj >= EMPTY_APP_ADJ) {
8311 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8312 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8313 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8314 } else if (r.setAdj >= HOME_APP_ADJ) {
8315 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8316 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8317 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8318 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8319 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8320 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8321 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8322 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8323 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8324 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8325 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8326 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8327 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8328 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8329 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8330 } else if (r.setAdj >= SYSTEM_ADJ) {
8331 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8332 } else {
8333 oomAdj = Integer.toString(r.setAdj);
8334 }
8335 String schedGroup;
8336 switch (r.setSchedGroup) {
8337 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8338 schedGroup = "B";
8339 break;
8340 case Process.THREAD_GROUP_DEFAULT:
8341 schedGroup = "F";
8342 break;
8343 default:
8344 schedGroup = Integer.toString(r.setSchedGroup);
8345 break;
8346 }
8347 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8348 prefix, (r.persistent ? persistentLabel : normalLabel),
8349 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8350 if (r.adjSource != null || r.adjTarget != null) {
8351 pw.print(prefix);
8352 pw.print(" ");
8353 if (r.adjTarget instanceof ComponentName) {
8354 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8355 } else if (r.adjTarget != null) {
8356 pw.print(r.adjTarget.toString());
8357 } else {
8358 pw.print("{null}");
8359 }
8360 pw.print("<=");
8361 if (r.adjSource instanceof ProcessRecord) {
8362 pw.print("Proc{");
8363 pw.print(((ProcessRecord)r.adjSource).toShortString());
8364 pw.println("}");
8365 } else if (r.adjSource != null) {
8366 pw.println(r.adjSource.toString());
8367 } else {
8368 pw.println("{null}");
8369 }
8370 }
8371 if (inclDetails) {
8372 pw.print(prefix);
8373 pw.print(" ");
8374 pw.print("oom: max="); pw.print(r.maxAdj);
8375 pw.print(" hidden="); pw.print(r.hiddenAdj);
8376 pw.print(" curRaw="); pw.print(r.curRawAdj);
8377 pw.print(" setRaw="); pw.print(r.setRawAdj);
8378 pw.print(" cur="); pw.print(r.curAdj);
8379 pw.print(" set="); pw.println(r.setAdj);
8380 pw.print(prefix);
8381 pw.print(" ");
8382 pw.print("keeping="); pw.print(r.keeping);
8383 pw.print(" hidden="); pw.print(r.hidden);
8384 pw.print(" empty="); pw.println(r.empty);
8385
8386 if (!r.keeping) {
8387 if (r.lastWakeTime != 0) {
8388 long wtime;
8389 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8390 synchronized (stats) {
8391 wtime = stats.getProcessWakeTime(r.info.uid,
8392 r.pid, curRealtime);
8393 }
8394 long timeUsed = wtime - r.lastWakeTime;
8395 pw.print(prefix);
8396 pw.print(" ");
8397 pw.print("keep awake over ");
8398 TimeUtils.formatDuration(realtimeSince, pw);
8399 pw.print(" used ");
8400 TimeUtils.formatDuration(timeUsed, pw);
8401 pw.print(" (");
8402 pw.print((timeUsed*100)/realtimeSince);
8403 pw.println("%)");
8404 }
8405 if (r.lastCpuTime != 0) {
8406 long timeUsed = r.curCpuTime - r.lastCpuTime;
8407 pw.print(prefix);
8408 pw.print(" ");
8409 pw.print("run cpu over ");
8410 TimeUtils.formatDuration(uptimeSince, pw);
8411 pw.print(" used ");
8412 TimeUtils.formatDuration(timeUsed, pw);
8413 pw.print(" (");
8414 pw.print((timeUsed*100)/uptimeSince);
8415 pw.println("%)");
8416 }
8417 }
8418 }
8419 }
8420 }
8421
Dianne Hackborn472ad872010-04-07 17:31:48 -07008422 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008423 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008424 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 long uptime = SystemClock.uptimeMillis();
8426 long realtime = SystemClock.elapsedRealtime();
8427
8428 if (isCheckinRequest) {
8429 // short checkin version
8430 pw.println(uptime + "," + realtime);
8431 pw.flush();
8432 } else {
8433 pw.println("Applications Memory Usage (kB):");
8434 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8435 }
8436 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8437 ProcessRecord r = (ProcessRecord)list.get(i);
8438 if (r.thread != null) {
8439 if (!isCheckinRequest) {
8440 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8441 pw.flush();
8442 }
8443 try {
8444 r.thread.asBinder().dump(fd, args);
8445 } catch (RemoteException e) {
8446 if (!isCheckinRequest) {
8447 pw.println("Got RemoteException!");
8448 pw.flush();
8449 }
8450 }
8451 }
8452 }
8453 }
8454
8455 /**
8456 * Searches array of arguments for the specified string
8457 * @param args array of argument strings
8458 * @param value value to search for
8459 * @return true if the value is contained in the array
8460 */
8461 private static boolean scanArgs(String[] args, String value) {
8462 if (args != null) {
8463 for (String arg : args) {
8464 if (value.equals(arg)) {
8465 return true;
8466 }
8467 }
8468 }
8469 return false;
8470 }
8471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008472 private final void killServicesLocked(ProcessRecord app,
8473 boolean allowRestart) {
8474 // Report disconnected services.
8475 if (false) {
8476 // XXX we are letting the client link to the service for
8477 // death notifications.
8478 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008479 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008481 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008483 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 = r.connections.values().iterator();
8485 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008486 ArrayList<ConnectionRecord> cl = jt.next();
8487 for (int i=0; i<cl.size(); i++) {
8488 ConnectionRecord c = cl.get(i);
8489 if (c.binding.client != app) {
8490 try {
8491 //c.conn.connected(r.className, null);
8492 } catch (Exception e) {
8493 // todo: this should be asynchronous!
8494 Slog.w(TAG, "Exception thrown disconnected servce "
8495 + r.shortName
8496 + " from app " + app.processName, e);
8497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008498 }
8499 }
8500 }
8501 }
8502 }
8503 }
8504 }
8505
8506 // Clean up any connections this application has to other services.
8507 if (app.connections.size() > 0) {
8508 Iterator<ConnectionRecord> it = app.connections.iterator();
8509 while (it.hasNext()) {
8510 ConnectionRecord r = it.next();
8511 removeConnectionLocked(r, app, null);
8512 }
8513 }
8514 app.connections.clear();
8515
8516 if (app.services.size() != 0) {
8517 // Any services running in the application need to be placed
8518 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008519 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008521 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 synchronized (sr.stats.getBatteryStats()) {
8523 sr.stats.stopLaunchedLocked();
8524 }
8525 sr.app = null;
8526 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008527 if (mStoppingServices.remove(sr)) {
8528 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8529 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008530
8531 boolean hasClients = sr.bindings.size() > 0;
8532 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 Iterator<IntentBindRecord> bindings
8534 = sr.bindings.values().iterator();
8535 while (bindings.hasNext()) {
8536 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008537 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 + ": shouldUnbind=" + b.hasBound);
8539 b.binder = null;
8540 b.requested = b.received = b.hasBound = false;
8541 }
8542 }
8543
Dianne Hackborn070783f2010-12-29 16:46:28 -08008544 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8545 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008546 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008547 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008548 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008549 sr.crashCount, sr.shortName, app.pid);
8550 bringDownServiceLocked(sr, true);
8551 } else if (!allowRestart) {
8552 bringDownServiceLocked(sr, true);
8553 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008554 boolean canceled = scheduleServiceRestartLocked(sr, true);
8555
8556 // Should the service remain running? Note that in the
8557 // extreme case of so many attempts to deliver a command
8558 // that it failed, that we also will stop it here.
8559 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8560 if (sr.pendingStarts.size() == 0) {
8561 sr.startRequested = false;
8562 if (!hasClients) {
8563 // Whoops, no reason to restart!
8564 bringDownServiceLocked(sr, true);
8565 }
8566 }
8567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 }
8569 }
8570
8571 if (!allowRestart) {
8572 app.services.clear();
8573 }
8574 }
8575
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008576 // Make sure we have no more records on the stopping list.
8577 int i = mStoppingServices.size();
8578 while (i > 0) {
8579 i--;
8580 ServiceRecord sr = mStoppingServices.get(i);
8581 if (sr.app == app) {
8582 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008583 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008584 }
8585 }
8586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008587 app.executingServices.clear();
8588 }
8589
8590 private final void removeDyingProviderLocked(ProcessRecord proc,
8591 ContentProviderRecord cpr) {
8592 synchronized (cpr) {
8593 cpr.launchingApp = null;
8594 cpr.notifyAll();
8595 }
8596
8597 mProvidersByClass.remove(cpr.info.name);
8598 String names[] = cpr.info.authority.split(";");
8599 for (int j = 0; j < names.length; j++) {
8600 mProvidersByName.remove(names[j]);
8601 }
8602
8603 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8604 while (cit.hasNext()) {
8605 ProcessRecord capp = cit.next();
8606 if (!capp.persistent && capp.thread != null
8607 && capp.pid != 0
8608 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008609 Slog.i(TAG, "Kill " + capp.processName
8610 + " (pid " + capp.pid + "): provider " + cpr.info.name
8611 + " in dying process " + proc.processName);
8612 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8613 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 Process.killProcess(capp.pid);
8615 }
8616 }
8617
8618 mLaunchingProviders.remove(cpr);
8619 }
8620
8621 /**
8622 * Main code for cleaning up a process when it has gone away. This is
8623 * called both as a result of the process dying, or directly when stopping
8624 * a process when running in single process mode.
8625 */
8626 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8627 boolean restarting, int index) {
8628 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008629 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 }
8631
Dianne Hackborn36124872009-10-08 16:22:03 -07008632 mProcessesToGc.remove(app);
8633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 // Dismiss any open dialogs.
8635 if (app.crashDialog != null) {
8636 app.crashDialog.dismiss();
8637 app.crashDialog = null;
8638 }
8639 if (app.anrDialog != null) {
8640 app.anrDialog.dismiss();
8641 app.anrDialog = null;
8642 }
8643 if (app.waitDialog != null) {
8644 app.waitDialog.dismiss();
8645 app.waitDialog = null;
8646 }
8647
8648 app.crashing = false;
8649 app.notResponding = false;
8650
8651 app.resetPackageList();
8652 app.thread = null;
8653 app.forcingToForeground = null;
8654 app.foregroundServices = false;
8655
8656 killServicesLocked(app, true);
8657
8658 boolean restart = false;
8659
8660 int NL = mLaunchingProviders.size();
8661
8662 // Remove published content providers.
8663 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008664 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008665 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008666 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008667 cpr.provider = null;
8668 cpr.app = null;
8669
8670 // See if someone is waiting for this provider... in which
8671 // case we don't remove it, but just let it restart.
8672 int i = 0;
8673 if (!app.bad) {
8674 for (; i<NL; i++) {
8675 if (mLaunchingProviders.get(i) == cpr) {
8676 restart = true;
8677 break;
8678 }
8679 }
8680 } else {
8681 i = NL;
8682 }
8683
8684 if (i >= NL) {
8685 removeDyingProviderLocked(app, cpr);
8686 NL = mLaunchingProviders.size();
8687 }
8688 }
8689 app.pubProviders.clear();
8690 }
8691
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008692 // Take care of any launching providers waiting for this process.
8693 if (checkAppInLaunchingProvidersLocked(app, false)) {
8694 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008695 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 // Unregister from connected content providers.
8698 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008699 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008700 while (it.hasNext()) {
8701 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8702 cpr.clients.remove(app);
8703 }
8704 app.conProviders.clear();
8705 }
8706
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008707 // At this point there may be remaining entries in mLaunchingProviders
8708 // where we were the only one waiting, so they are no longer of use.
8709 // Look for these and clean up if found.
8710 // XXX Commented out for now. Trying to figure out a way to reproduce
8711 // the actual situation to identify what is actually going on.
8712 if (false) {
8713 for (int i=0; i<NL; i++) {
8714 ContentProviderRecord cpr = (ContentProviderRecord)
8715 mLaunchingProviders.get(i);
8716 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8717 synchronized (cpr) {
8718 cpr.launchingApp = null;
8719 cpr.notifyAll();
8720 }
8721 }
8722 }
8723 }
8724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 skipCurrentReceiverLocked(app);
8726
8727 // Unregister any receivers.
8728 if (app.receivers.size() > 0) {
8729 Iterator<ReceiverList> it = app.receivers.iterator();
8730 while (it.hasNext()) {
8731 removeReceiverLocked(it.next());
8732 }
8733 app.receivers.clear();
8734 }
8735
Christopher Tate181fafa2009-05-14 11:12:14 -07008736 // If the app is undergoing backup, tell the backup manager about it
8737 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008738 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008739 try {
8740 IBackupManager bm = IBackupManager.Stub.asInterface(
8741 ServiceManager.getService(Context.BACKUP_SERVICE));
8742 bm.agentDisconnected(app.info.packageName);
8743 } catch (RemoteException e) {
8744 // can't happen; backup manager is local
8745 }
8746 }
8747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748 // If the caller is restarting this app, then leave it in its
8749 // current lists and let the caller take care of it.
8750 if (restarting) {
8751 return;
8752 }
8753
8754 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008755 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 "Removing non-persistent process during cleanup: " + app);
8757 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008758 if (mHeavyWeightProcess == app) {
8759 mHeavyWeightProcess = null;
8760 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 } else if (!app.removed) {
8763 // This app is persistent, so we need to keep its record around.
8764 // If it is not already on the pending app list, add it there
8765 // and start a new process for it.
8766 app.thread = null;
8767 app.forcingToForeground = null;
8768 app.foregroundServices = false;
8769 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8770 mPersistentStartingProcesses.add(app);
8771 restart = true;
8772 }
8773 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008774 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8775 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 mProcessesOnHold.remove(app);
8777
The Android Open Source Project4df24232009-03-05 14:34:35 -08008778 if (app == mHomeProcess) {
8779 mHomeProcess = null;
8780 }
8781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 if (restart) {
8783 // We have components that still need to be running in the
8784 // process, so re-launch it.
8785 mProcessNames.put(app.processName, app.info.uid, app);
8786 startProcessLocked(app, "restart", app.processName);
8787 } else if (app.pid > 0 && app.pid != MY_PID) {
8788 // Goodbye!
8789 synchronized (mPidsSelfLocked) {
8790 mPidsSelfLocked.remove(app.pid);
8791 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8792 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008793 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 }
8795 }
8796
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008797 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8798 // Look through the content providers we are waiting to have launched,
8799 // and if any run in this process then either schedule a restart of
8800 // the process or kill the client waiting for it if this process has
8801 // gone bad.
8802 int NL = mLaunchingProviders.size();
8803 boolean restart = false;
8804 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008805 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008806 if (cpr.launchingApp == app) {
8807 if (!alwaysBad && !app.bad) {
8808 restart = true;
8809 } else {
8810 removeDyingProviderLocked(app, cpr);
8811 NL = mLaunchingProviders.size();
8812 }
8813 }
8814 }
8815 return restart;
8816 }
8817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008818 // =========================================================
8819 // SERVICES
8820 // =========================================================
8821
8822 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8823 ActivityManager.RunningServiceInfo info =
8824 new ActivityManager.RunningServiceInfo();
8825 info.service = r.name;
8826 if (r.app != null) {
8827 info.pid = r.app.pid;
8828 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008829 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 info.process = r.processName;
8831 info.foreground = r.isForeground;
8832 info.activeSince = r.createTime;
8833 info.started = r.startRequested;
8834 info.clientCount = r.connections.size();
8835 info.crashCount = r.crashCount;
8836 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008837 if (r.isForeground) {
8838 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8839 }
8840 if (r.startRequested) {
8841 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8842 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008843 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008844 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8845 }
8846 if (r.app != null && r.app.persistent) {
8847 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8848 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008849
8850 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8851 for (int i=0; i<connl.size(); i++) {
8852 ConnectionRecord conn = connl.get(i);
8853 if (conn.clientLabel != 0) {
8854 info.clientPackage = conn.binding.client.info.packageName;
8855 info.clientLabel = conn.clientLabel;
8856 return info;
8857 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008858 }
8859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 return info;
8861 }
8862
8863 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8864 int flags) {
8865 synchronized (this) {
8866 ArrayList<ActivityManager.RunningServiceInfo> res
8867 = new ArrayList<ActivityManager.RunningServiceInfo>();
8868
8869 if (mServices.size() > 0) {
8870 Iterator<ServiceRecord> it = mServices.values().iterator();
8871 while (it.hasNext() && res.size() < maxNum) {
8872 res.add(makeRunningServiceInfoLocked(it.next()));
8873 }
8874 }
8875
8876 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8877 ServiceRecord r = mRestartingServices.get(i);
8878 ActivityManager.RunningServiceInfo info =
8879 makeRunningServiceInfoLocked(r);
8880 info.restarting = r.nextRestartTime;
8881 res.add(info);
8882 }
8883
8884 return res;
8885 }
8886 }
8887
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008888 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8889 synchronized (this) {
8890 ServiceRecord r = mServices.get(name);
8891 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008892 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8893 for (int i=0; i<conn.size(); i++) {
8894 if (conn.get(i).clientIntent != null) {
8895 return conn.get(i).clientIntent;
8896 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008897 }
8898 }
8899 }
8900 }
8901 return null;
8902 }
8903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 private final ServiceRecord findServiceLocked(ComponentName name,
8905 IBinder token) {
8906 ServiceRecord r = mServices.get(name);
8907 return r == token ? r : null;
8908 }
8909
8910 private final class ServiceLookupResult {
8911 final ServiceRecord record;
8912 final String permission;
8913
8914 ServiceLookupResult(ServiceRecord _record, String _permission) {
8915 record = _record;
8916 permission = _permission;
8917 }
8918 };
8919
8920 private ServiceLookupResult findServiceLocked(Intent service,
8921 String resolvedType) {
8922 ServiceRecord r = null;
8923 if (service.getComponent() != null) {
8924 r = mServices.get(service.getComponent());
8925 }
8926 if (r == null) {
8927 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8928 r = mServicesByIntent.get(filter);
8929 }
8930
8931 if (r == null) {
8932 try {
8933 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008934 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 service, resolvedType, 0);
8936 ServiceInfo sInfo =
8937 rInfo != null ? rInfo.serviceInfo : null;
8938 if (sInfo == null) {
8939 return null;
8940 }
8941
8942 ComponentName name = new ComponentName(
8943 sInfo.applicationInfo.packageName, sInfo.name);
8944 r = mServices.get(name);
8945 } catch (RemoteException ex) {
8946 // pm is in same process, this will never happen.
8947 }
8948 }
8949 if (r != null) {
8950 int callingPid = Binder.getCallingPid();
8951 int callingUid = Binder.getCallingUid();
8952 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008953 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008955 if (!r.exported) {
8956 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
8957 + " from pid=" + callingPid
8958 + ", uid=" + callingUid
8959 + " that is not exported from uid " + r.appInfo.uid);
8960 return new ServiceLookupResult(null, "not exported from uid "
8961 + r.appInfo.uid);
8962 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008963 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 + " from pid=" + callingPid
8965 + ", uid=" + callingUid
8966 + " requires " + r.permission);
8967 return new ServiceLookupResult(null, r.permission);
8968 }
8969 return new ServiceLookupResult(r, null);
8970 }
8971 return null;
8972 }
8973
8974 private class ServiceRestarter implements Runnable {
8975 private ServiceRecord mService;
8976
8977 void setService(ServiceRecord service) {
8978 mService = service;
8979 }
8980
8981 public void run() {
8982 synchronized(ActivityManagerService.this) {
8983 performServiceRestartLocked(mService);
8984 }
8985 }
8986 }
8987
8988 private ServiceLookupResult retrieveServiceLocked(Intent service,
8989 String resolvedType, int callingPid, int callingUid) {
8990 ServiceRecord r = null;
8991 if (service.getComponent() != null) {
8992 r = mServices.get(service.getComponent());
8993 }
8994 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8995 r = mServicesByIntent.get(filter);
8996 if (r == null) {
8997 try {
8998 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008999 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009000 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 ServiceInfo sInfo =
9002 rInfo != null ? rInfo.serviceInfo : null;
9003 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009004 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 ": not found");
9006 return null;
9007 }
9008
9009 ComponentName name = new ComponentName(
9010 sInfo.applicationInfo.packageName, sInfo.name);
9011 r = mServices.get(name);
9012 if (r == null) {
9013 filter = new Intent.FilterComparison(service.cloneFilter());
9014 ServiceRestarter res = new ServiceRestarter();
9015 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9016 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9017 synchronized (stats) {
9018 ss = stats.getServiceStatsLocked(
9019 sInfo.applicationInfo.uid, sInfo.packageName,
9020 sInfo.name);
9021 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009022 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009023 res.setService(r);
9024 mServices.put(name, r);
9025 mServicesByIntent.put(filter, r);
9026
9027 // Make sure this component isn't in the pending list.
9028 int N = mPendingServices.size();
9029 for (int i=0; i<N; i++) {
9030 ServiceRecord pr = mPendingServices.get(i);
9031 if (pr.name.equals(name)) {
9032 mPendingServices.remove(i);
9033 i--;
9034 N--;
9035 }
9036 }
9037 }
9038 } catch (RemoteException ex) {
9039 // pm is in same process, this will never happen.
9040 }
9041 }
9042 if (r != null) {
9043 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009044 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009046 if (!r.exported) {
9047 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9048 + " from pid=" + callingPid
9049 + ", uid=" + callingUid
9050 + " that is not exported from uid " + r.appInfo.uid);
9051 return new ServiceLookupResult(null, "not exported from uid "
9052 + r.appInfo.uid);
9053 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009054 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009055 + " from pid=" + callingPid
9056 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 + " requires " + r.permission);
9058 return new ServiceLookupResult(null, r.permission);
9059 }
9060 return new ServiceLookupResult(r, null);
9061 }
9062 return null;
9063 }
9064
Dianne Hackborn287952c2010-09-22 22:34:31 -07009065 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9066 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9067 + why + " of " + r + " in app " + r.app);
9068 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9069 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009070 long now = SystemClock.uptimeMillis();
9071 if (r.executeNesting == 0 && r.app != null) {
9072 if (r.app.executingServices.size() == 0) {
9073 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9074 msg.obj = r.app;
9075 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9076 }
9077 r.app.executingServices.add(r);
9078 }
9079 r.executeNesting++;
9080 r.executingStart = now;
9081 }
9082
9083 private final void sendServiceArgsLocked(ServiceRecord r,
9084 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009085 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 if (N == 0) {
9087 return;
9088 }
9089
Dianne Hackborn39792d22010-08-19 18:01:52 -07009090 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009092 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009093 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9094 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009095 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009096 // If somehow we got a dummy start at the front, then
9097 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009098 continue;
9099 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009100 si.deliveredTime = SystemClock.uptimeMillis();
9101 r.deliveredStarts.add(si);
9102 si.deliveryCount++;
9103 if (si.targetPermissionUid >= 0) {
9104 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009105 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009106 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009107 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 if (!oomAdjusted) {
9109 oomAdjusted = true;
9110 updateOomAdjLocked(r.app);
9111 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009112 int flags = 0;
9113 if (si.deliveryCount > 0) {
9114 flags |= Service.START_FLAG_RETRY;
9115 }
9116 if (si.doneExecutingCount > 0) {
9117 flags |= Service.START_FLAG_REDELIVERY;
9118 }
9119 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009120 } catch (RemoteException e) {
9121 // Remote process gone... we'll let the normal cleanup take
9122 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009123 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009124 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009126 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009127 break;
9128 }
9129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 }
9131
9132 private final boolean requestServiceBindingLocked(ServiceRecord r,
9133 IntentBindRecord i, boolean rebind) {
9134 if (r.app == null || r.app.thread == null) {
9135 // If service is not currently running, can't yet bind.
9136 return false;
9137 }
9138 if ((!i.requested || rebind) && i.apps.size() > 0) {
9139 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009140 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9142 if (!rebind) {
9143 i.requested = true;
9144 }
9145 i.hasBound = true;
9146 i.doRebind = false;
9147 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009148 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009149 return false;
9150 }
9151 }
9152 return true;
9153 }
9154
9155 private final void requestServiceBindingsLocked(ServiceRecord r) {
9156 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9157 while (bindings.hasNext()) {
9158 IntentBindRecord i = bindings.next();
9159 if (!requestServiceBindingLocked(r, i, false)) {
9160 break;
9161 }
9162 }
9163 }
9164
9165 private final void realStartServiceLocked(ServiceRecord r,
9166 ProcessRecord app) throws RemoteException {
9167 if (app.thread == null) {
9168 throw new RemoteException();
9169 }
9170
9171 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009172 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173
9174 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009175 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009176 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177
9178 boolean created = false;
9179 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009180 mStringBuilder.setLength(0);
9181 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009182 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009184 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009185 synchronized (r.stats.getBatteryStats()) {
9186 r.stats.startLaunchedLocked();
9187 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009188 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009190 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009191 created = true;
9192 } finally {
9193 if (!created) {
9194 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009195 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 }
9197 }
9198
9199 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009200
9201 // If the service is in the started state, and there are no
9202 // pending arguments, then fake up one so its onStartCommand() will
9203 // be called.
9204 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9205 r.lastStartId++;
9206 if (r.lastStartId < 1) {
9207 r.lastStartId = 1;
9208 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009209 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009210 }
9211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 sendServiceArgsLocked(r, true);
9213 }
9214
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009215 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9216 boolean allowCancel) {
9217 boolean canceled = false;
9218
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009219 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009220 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009221 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009222
Dianne Hackborn070783f2010-12-29 16:46:28 -08009223 if ((r.serviceInfo.applicationInfo.flags
9224 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9225 minDuration /= 4;
9226 }
9227
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009228 // Any delivered but not yet finished starts should be put back
9229 // on the pending list.
9230 final int N = r.deliveredStarts.size();
9231 if (N > 0) {
9232 for (int i=N-1; i>=0; i--) {
9233 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009234 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009235 if (si.intent == null) {
9236 // We'll generate this again if needed.
9237 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9238 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9239 r.pendingStarts.add(0, si);
9240 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9241 dur *= 2;
9242 if (minDuration < dur) minDuration = dur;
9243 if (resetTime < dur) resetTime = dur;
9244 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009245 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009246 + r.name);
9247 canceled = true;
9248 }
9249 }
9250 r.deliveredStarts.clear();
9251 }
9252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009253 r.totalRestartCount++;
9254 if (r.restartDelay == 0) {
9255 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009256 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 } else {
9258 // If it has been a "reasonably long time" since the service
9259 // was started, then reset our restart duration back to
9260 // the beginning, so we don't infinitely increase the duration
9261 // on a service that just occasionally gets killed (which is
9262 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009263 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009265 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009267 if ((r.serviceInfo.applicationInfo.flags
9268 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9269 // Services in peristent processes will restart much more
9270 // quickly, since they are pretty important. (Think SystemUI).
9271 r.restartDelay += minDuration/2;
9272 } else {
9273 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9274 if (r.restartDelay < minDuration) {
9275 r.restartDelay = minDuration;
9276 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 }
9279 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009280
9281 r.nextRestartTime = now + r.restartDelay;
9282
9283 // Make sure that we don't end up restarting a bunch of services
9284 // all at the same time.
9285 boolean repeat;
9286 do {
9287 repeat = false;
9288 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9289 ServiceRecord r2 = mRestartingServices.get(i);
9290 if (r2 != r && r.nextRestartTime
9291 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9292 && r.nextRestartTime
9293 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9294 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9295 r.restartDelay = r.nextRestartTime - now;
9296 repeat = true;
9297 break;
9298 }
9299 }
9300 } while (repeat);
9301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 if (!mRestartingServices.contains(r)) {
9303 mRestartingServices.add(r);
9304 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009305
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009306 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009309 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009311 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009313 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 r.shortName, r.restartDelay);
9315
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009316 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 }
9318
9319 final void performServiceRestartLocked(ServiceRecord r) {
9320 if (!mRestartingServices.contains(r)) {
9321 return;
9322 }
9323 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9324 }
9325
9326 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9327 if (r.restartDelay == 0) {
9328 return false;
9329 }
9330 r.resetRestartCounter();
9331 mRestartingServices.remove(r);
9332 mHandler.removeCallbacks(r.restarter);
9333 return true;
9334 }
9335
9336 private final boolean bringUpServiceLocked(ServiceRecord r,
9337 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009338 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 //r.dump(" ");
9340
Dianne Hackborn36124872009-10-08 16:22:03 -07009341 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 sendServiceArgsLocked(r, false);
9343 return true;
9344 }
9345
9346 if (!whileRestarting && r.restartDelay > 0) {
9347 // If waiting for a restart, then do nothing.
9348 return true;
9349 }
9350
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009351 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009352
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009353 // We are now bringing the service up, so no longer in the
9354 // restarting state.
9355 mRestartingServices.remove(r);
9356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 final String appName = r.processName;
9358 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9359 if (app != null && app.thread != null) {
9360 try {
9361 realStartServiceLocked(r, app);
9362 return true;
9363 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009364 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 }
9366
9367 // If a dead object exception was thrown -- fall through to
9368 // restart the application.
9369 }
9370
Dianne Hackborn36124872009-10-08 16:22:03 -07009371 // Not running -- get it started, and enqueue this service record
9372 // to be executed when the app comes up.
9373 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9374 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009375 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009376 + r.appInfo.packageName + "/"
9377 + r.appInfo.uid + " for service "
9378 + r.intent.getIntent() + ": process is bad");
9379 bringDownServiceLocked(r, true);
9380 return false;
9381 }
9382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009383 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009384 mPendingServices.add(r);
9385 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 return true;
9388 }
9389
9390 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009391 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 //r.dump(" ");
9393
9394 // Does it still need to run?
9395 if (!force && r.startRequested) {
9396 return;
9397 }
9398 if (r.connections.size() > 0) {
9399 if (!force) {
9400 // XXX should probably keep a count of the number of auto-create
9401 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009402 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009404 ArrayList<ConnectionRecord> cr = it.next();
9405 for (int i=0; i<cr.size(); i++) {
9406 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9407 return;
9408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409 }
9410 }
9411 }
9412
9413 // Report to all of the connections that the service is no longer
9414 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009415 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009417 ArrayList<ConnectionRecord> c = it.next();
9418 for (int i=0; i<c.size(); i++) {
9419 try {
9420 c.get(i).conn.connected(r.name, null);
9421 } catch (Exception e) {
9422 Slog.w(TAG, "Failure disconnecting service " + r.name +
9423 " to connection " + c.get(i).conn.asBinder() +
9424 " (in " + c.get(i).binding.client.processName + ")", e);
9425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426 }
9427 }
9428 }
9429
9430 // Tell the service that it has been unbound.
9431 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9432 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9433 while (it.hasNext()) {
9434 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009435 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 + ": hasBound=" + ibr.hasBound);
9437 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9438 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009439 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009440 updateOomAdjLocked(r.app);
9441 ibr.hasBound = false;
9442 r.app.thread.scheduleUnbindService(r,
9443 ibr.intent.getIntent());
9444 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009445 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 + r.shortName, e);
9447 serviceDoneExecutingLocked(r, true);
9448 }
9449 }
9450 }
9451 }
9452
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009453 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009454 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009455 System.identityHashCode(r), r.shortName,
9456 (r.app != null) ? r.app.pid : -1);
9457
9458 mServices.remove(r.name);
9459 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460 r.totalRestartCount = 0;
9461 unscheduleServiceRestartLocked(r);
9462
9463 // Also make sure it is not on the pending list.
9464 int N = mPendingServices.size();
9465 for (int i=0; i<N; i++) {
9466 if (mPendingServices.get(i) == r) {
9467 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009468 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 i--;
9470 N--;
9471 }
9472 }
9473
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009474 r.cancelNotification();
9475 r.isForeground = false;
9476 r.foregroundId = 0;
9477 r.foregroundNoti = null;
9478
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009479 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009480 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009481 r.pendingStarts.clear();
9482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483 if (r.app != null) {
9484 synchronized (r.stats.getBatteryStats()) {
9485 r.stats.stopLaunchedLocked();
9486 }
9487 r.app.services.remove(r);
9488 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009490 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009491 mStoppingServices.add(r);
9492 updateOomAdjLocked(r.app);
9493 r.app.thread.scheduleStopService(r);
9494 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009495 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009496 + r.shortName, e);
9497 serviceDoneExecutingLocked(r, true);
9498 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009499 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009501 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009502 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 }
9504 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009505 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009506 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009508
9509 if (r.bindings.size() > 0) {
9510 r.bindings.clear();
9511 }
9512
9513 if (r.restarter instanceof ServiceRestarter) {
9514 ((ServiceRestarter)r.restarter).setService(null);
9515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 }
9517
9518 ComponentName startServiceLocked(IApplicationThread caller,
9519 Intent service, String resolvedType,
9520 int callingPid, int callingUid) {
9521 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009522 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 + " type=" + resolvedType + " args=" + service.getExtras());
9524
9525 if (caller != null) {
9526 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9527 if (callerApp == null) {
9528 throw new SecurityException(
9529 "Unable to find app for caller " + caller
9530 + " (pid=" + Binder.getCallingPid()
9531 + ") when starting service " + service);
9532 }
9533 }
9534
9535 ServiceLookupResult res =
9536 retrieveServiceLocked(service, resolvedType,
9537 callingPid, callingUid);
9538 if (res == null) {
9539 return null;
9540 }
9541 if (res.record == null) {
9542 return new ComponentName("!", res.permission != null
9543 ? res.permission : "private to package");
9544 }
9545 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009546 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9547 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009548 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009549 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 }
9551 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009552 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009553 r.lastStartId++;
9554 if (r.lastStartId < 1) {
9555 r.lastStartId = 1;
9556 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009557 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9558 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 r.lastActivity = SystemClock.uptimeMillis();
9560 synchronized (r.stats.getBatteryStats()) {
9561 r.stats.startRunningLocked();
9562 }
9563 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9564 return new ComponentName("!", "Service process is bad");
9565 }
9566 return r.name;
9567 }
9568 }
9569
9570 public ComponentName startService(IApplicationThread caller, Intent service,
9571 String resolvedType) {
9572 // Refuse possible leaked file descriptors
9573 if (service != null && service.hasFileDescriptors() == true) {
9574 throw new IllegalArgumentException("File descriptors passed in Intent");
9575 }
9576
9577 synchronized(this) {
9578 final int callingPid = Binder.getCallingPid();
9579 final int callingUid = Binder.getCallingUid();
9580 final long origId = Binder.clearCallingIdentity();
9581 ComponentName res = startServiceLocked(caller, service,
9582 resolvedType, callingPid, callingUid);
9583 Binder.restoreCallingIdentity(origId);
9584 return res;
9585 }
9586 }
9587
9588 ComponentName startServiceInPackage(int uid,
9589 Intent service, String resolvedType) {
9590 synchronized(this) {
9591 final long origId = Binder.clearCallingIdentity();
9592 ComponentName res = startServiceLocked(null, service,
9593 resolvedType, -1, uid);
9594 Binder.restoreCallingIdentity(origId);
9595 return res;
9596 }
9597 }
9598
9599 public int stopService(IApplicationThread caller, Intent service,
9600 String resolvedType) {
9601 // Refuse possible leaked file descriptors
9602 if (service != null && service.hasFileDescriptors() == true) {
9603 throw new IllegalArgumentException("File descriptors passed in Intent");
9604 }
9605
9606 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009607 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 + " type=" + resolvedType);
9609
9610 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9611 if (caller != null && callerApp == null) {
9612 throw new SecurityException(
9613 "Unable to find app for caller " + caller
9614 + " (pid=" + Binder.getCallingPid()
9615 + ") when stopping service " + service);
9616 }
9617
9618 // If this service is active, make sure it is stopped.
9619 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9620 if (r != null) {
9621 if (r.record != null) {
9622 synchronized (r.record.stats.getBatteryStats()) {
9623 r.record.stats.stopRunningLocked();
9624 }
9625 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009626 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 final long origId = Binder.clearCallingIdentity();
9628 bringDownServiceLocked(r.record, false);
9629 Binder.restoreCallingIdentity(origId);
9630 return 1;
9631 }
9632 return -1;
9633 }
9634 }
9635
9636 return 0;
9637 }
9638
9639 public IBinder peekService(Intent service, String resolvedType) {
9640 // Refuse possible leaked file descriptors
9641 if (service != null && service.hasFileDescriptors() == true) {
9642 throw new IllegalArgumentException("File descriptors passed in Intent");
9643 }
9644
9645 IBinder ret = null;
9646
9647 synchronized(this) {
9648 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9649
9650 if (r != null) {
9651 // r.record is null if findServiceLocked() failed the caller permission check
9652 if (r.record == null) {
9653 throw new SecurityException(
9654 "Permission Denial: Accessing service " + r.record.name
9655 + " from pid=" + Binder.getCallingPid()
9656 + ", uid=" + Binder.getCallingUid()
9657 + " requires " + r.permission);
9658 }
9659 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9660 if (ib != null) {
9661 ret = ib.binder;
9662 }
9663 }
9664 }
9665
9666 return ret;
9667 }
9668
9669 public boolean stopServiceToken(ComponentName className, IBinder token,
9670 int startId) {
9671 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009672 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 + " " + token + " startId=" + startId);
9674 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009675 if (r != null) {
9676 if (startId >= 0) {
9677 // Asked to only stop if done with all work. Note that
9678 // to avoid leaks, we will take this as dropping all
9679 // start items up to and including this one.
9680 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9681 if (si != null) {
9682 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009683 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9684 cur.removeUriPermissionsLocked();
9685 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009686 break;
9687 }
9688 }
9689 }
9690
9691 if (r.lastStartId != startId) {
9692 return false;
9693 }
9694
9695 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009696 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009697 + " is last, but have " + r.deliveredStarts.size()
9698 + " remaining args");
9699 }
9700 }
9701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 synchronized (r.stats.getBatteryStats()) {
9703 r.stats.stopRunningLocked();
9704 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009705 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706 }
9707 final long origId = Binder.clearCallingIdentity();
9708 bringDownServiceLocked(r, false);
9709 Binder.restoreCallingIdentity(origId);
9710 return true;
9711 }
9712 }
9713 return false;
9714 }
9715
9716 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009717 int id, Notification notification, boolean removeNotification) {
9718 final long origId = Binder.clearCallingIdentity();
9719 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720 synchronized(this) {
9721 ServiceRecord r = findServiceLocked(className, token);
9722 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009723 if (id != 0) {
9724 if (notification == null) {
9725 throw new IllegalArgumentException("null notification");
9726 }
9727 if (r.foregroundId != id) {
9728 r.cancelNotification();
9729 r.foregroundId = id;
9730 }
9731 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9732 r.foregroundNoti = notification;
9733 r.isForeground = true;
9734 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 if (r.app != null) {
9736 updateServiceForegroundLocked(r.app, true);
9737 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009738 } else {
9739 if (r.isForeground) {
9740 r.isForeground = false;
9741 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009742 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009743 updateServiceForegroundLocked(r.app, true);
9744 }
9745 }
9746 if (removeNotification) {
9747 r.cancelNotification();
9748 r.foregroundId = 0;
9749 r.foregroundNoti = null;
9750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 }
9752 }
9753 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009754 } finally {
9755 Binder.restoreCallingIdentity(origId);
9756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 }
9758
9759 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9760 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009761 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 if (sr.isForeground) {
9763 anyForeground = true;
9764 break;
9765 }
9766 }
9767 if (anyForeground != proc.foregroundServices) {
9768 proc.foregroundServices = anyForeground;
9769 if (oomAdj) {
9770 updateOomAdjLocked();
9771 }
9772 }
9773 }
9774
9775 public int bindService(IApplicationThread caller, IBinder token,
9776 Intent service, String resolvedType,
9777 IServiceConnection connection, int flags) {
9778 // Refuse possible leaked file descriptors
9779 if (service != null && service.hasFileDescriptors() == true) {
9780 throw new IllegalArgumentException("File descriptors passed in Intent");
9781 }
9782
9783 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009784 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 + " type=" + resolvedType + " conn=" + connection.asBinder()
9786 + " flags=0x" + Integer.toHexString(flags));
9787 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9788 if (callerApp == null) {
9789 throw new SecurityException(
9790 "Unable to find app for caller " + caller
9791 + " (pid=" + Binder.getCallingPid()
9792 + ") when binding service " + service);
9793 }
9794
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009795 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009797 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009799 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009800 return 0;
9801 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009802 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009803 }
9804
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009805 int clientLabel = 0;
9806 PendingIntent clientIntent = null;
9807
9808 if (callerApp.info.uid == Process.SYSTEM_UID) {
9809 // Hacky kind of thing -- allow system stuff to tell us
9810 // what they are, so we can report this elsewhere for
9811 // others to know why certain services are running.
9812 try {
9813 clientIntent = (PendingIntent)service.getParcelableExtra(
9814 Intent.EXTRA_CLIENT_INTENT);
9815 } catch (RuntimeException e) {
9816 }
9817 if (clientIntent != null) {
9818 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9819 if (clientLabel != 0) {
9820 // There are no useful extras in the intent, trash them.
9821 // System code calling with this stuff just needs to know
9822 // this will happen.
9823 service = service.cloneFilter();
9824 }
9825 }
9826 }
9827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 ServiceLookupResult res =
9829 retrieveServiceLocked(service, resolvedType,
9830 Binder.getCallingPid(), Binder.getCallingUid());
9831 if (res == null) {
9832 return 0;
9833 }
9834 if (res.record == null) {
9835 return -1;
9836 }
9837 ServiceRecord s = res.record;
9838
9839 final long origId = Binder.clearCallingIdentity();
9840
9841 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009842 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009843 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 }
9845
9846 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9847 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009848 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009849
9850 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009851 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9852 if (clist == null) {
9853 clist = new ArrayList<ConnectionRecord>();
9854 s.connections.put(binder, clist);
9855 }
9856 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 b.connections.add(c);
9858 if (activity != null) {
9859 if (activity.connections == null) {
9860 activity.connections = new HashSet<ConnectionRecord>();
9861 }
9862 activity.connections.add(c);
9863 }
9864 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009865 clist = mServiceConnections.get(binder);
9866 if (clist == null) {
9867 clist = new ArrayList<ConnectionRecord>();
9868 mServiceConnections.put(binder, clist);
9869 }
9870 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871
9872 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9873 s.lastActivity = SystemClock.uptimeMillis();
9874 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9875 return 0;
9876 }
9877 }
9878
9879 if (s.app != null) {
9880 // This could have made the service more important.
9881 updateOomAdjLocked(s.app);
9882 }
9883
Joe Onorato8a9b2202010-02-26 18:56:32 -08009884 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 + ": received=" + b.intent.received
9886 + " apps=" + b.intent.apps.size()
9887 + " doRebind=" + b.intent.doRebind);
9888
9889 if (s.app != null && b.intent.received) {
9890 // Service is already running, so we can immediately
9891 // publish the connection.
9892 try {
9893 c.conn.connected(s.name, b.intent.binder);
9894 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009895 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 + " to connection " + c.conn.asBinder()
9897 + " (in " + c.binding.client.processName + ")", e);
9898 }
9899
9900 // If this is the first app connected back to this binding,
9901 // and the service had previously asked to be told when
9902 // rebound, then do so.
9903 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9904 requestServiceBindingLocked(s, b.intent, true);
9905 }
9906 } else if (!b.intent.requested) {
9907 requestServiceBindingLocked(s, b.intent, false);
9908 }
9909
9910 Binder.restoreCallingIdentity(origId);
9911 }
9912
9913 return 1;
9914 }
9915
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009916 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009917 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 IBinder binder = c.conn.asBinder();
9919 AppBindRecord b = c.binding;
9920 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009921 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9922 if (clist != null) {
9923 clist.remove(c);
9924 if (clist.size() == 0) {
9925 s.connections.remove(binder);
9926 }
9927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 b.connections.remove(c);
9929 if (c.activity != null && c.activity != skipAct) {
9930 if (c.activity.connections != null) {
9931 c.activity.connections.remove(c);
9932 }
9933 }
9934 if (b.client != skipApp) {
9935 b.client.connections.remove(c);
9936 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009937 clist = mServiceConnections.get(binder);
9938 if (clist != null) {
9939 clist.remove(c);
9940 if (clist.size() == 0) {
9941 mServiceConnections.remove(binder);
9942 }
9943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009944
9945 if (b.connections.size() == 0) {
9946 b.intent.apps.remove(b.client);
9947 }
9948
Joe Onorato8a9b2202010-02-26 18:56:32 -08009949 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009950 + ": shouldUnbind=" + b.intent.hasBound);
9951 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9952 && b.intent.hasBound) {
9953 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009954 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009955 updateOomAdjLocked(s.app);
9956 b.intent.hasBound = false;
9957 // Assume the client doesn't want to know about a rebind;
9958 // we will deal with that later if it asks for one.
9959 b.intent.doRebind = false;
9960 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9961 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009962 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 serviceDoneExecutingLocked(s, true);
9964 }
9965 }
9966
9967 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9968 bringDownServiceLocked(s, false);
9969 }
9970 }
9971
9972 public boolean unbindService(IServiceConnection connection) {
9973 synchronized (this) {
9974 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009975 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009976 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9977 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009978 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 + connection.asBinder());
9980 return false;
9981 }
9982
9983 final long origId = Binder.clearCallingIdentity();
9984
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009985 while (clist.size() > 0) {
9986 ConnectionRecord r = clist.get(0);
9987 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009989 if (r.binding.service.app != null) {
9990 // This could have made the service less important.
9991 updateOomAdjLocked(r.binding.service.app);
9992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009993 }
9994
9995 Binder.restoreCallingIdentity(origId);
9996 }
9997
9998 return true;
9999 }
10000
10001 public void publishService(IBinder token, Intent intent, IBinder service) {
10002 // Refuse possible leaked file descriptors
10003 if (intent != null && intent.hasFileDescriptors() == true) {
10004 throw new IllegalArgumentException("File descriptors passed in Intent");
10005 }
10006
10007 synchronized(this) {
10008 if (!(token instanceof ServiceRecord)) {
10009 throw new IllegalArgumentException("Invalid service token");
10010 }
10011 ServiceRecord r = (ServiceRecord)token;
10012
10013 final long origId = Binder.clearCallingIdentity();
10014
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010015 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016 + " " + intent + ": " + service);
10017 if (r != null) {
10018 Intent.FilterComparison filter
10019 = new Intent.FilterComparison(intent);
10020 IntentBindRecord b = r.bindings.get(filter);
10021 if (b != null && !b.received) {
10022 b.binder = service;
10023 b.requested = true;
10024 b.received = true;
10025 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010026 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027 = r.connections.values().iterator();
10028 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010029 ArrayList<ConnectionRecord> clist = it.next();
10030 for (int i=0; i<clist.size(); i++) {
10031 ConnectionRecord c = clist.get(i);
10032 if (!filter.equals(c.binding.intent.intent)) {
10033 if (DEBUG_SERVICE) Slog.v(
10034 TAG, "Not publishing to: " + c);
10035 if (DEBUG_SERVICE) Slog.v(
10036 TAG, "Bound intent: " + c.binding.intent.intent);
10037 if (DEBUG_SERVICE) Slog.v(
10038 TAG, "Published intent: " + intent);
10039 continue;
10040 }
10041 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10042 try {
10043 c.conn.connected(r.name, service);
10044 } catch (Exception e) {
10045 Slog.w(TAG, "Failure sending service " + r.name +
10046 " to connection " + c.conn.asBinder() +
10047 " (in " + c.binding.client.processName + ")", e);
10048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 }
10050 }
10051 }
10052 }
10053
10054 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10055
10056 Binder.restoreCallingIdentity(origId);
10057 }
10058 }
10059 }
10060
10061 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10062 // Refuse possible leaked file descriptors
10063 if (intent != null && intent.hasFileDescriptors() == true) {
10064 throw new IllegalArgumentException("File descriptors passed in Intent");
10065 }
10066
10067 synchronized(this) {
10068 if (!(token instanceof ServiceRecord)) {
10069 throw new IllegalArgumentException("Invalid service token");
10070 }
10071 ServiceRecord r = (ServiceRecord)token;
10072
10073 final long origId = Binder.clearCallingIdentity();
10074
10075 if (r != null) {
10076 Intent.FilterComparison filter
10077 = new Intent.FilterComparison(intent);
10078 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010079 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 + " at " + b + ": apps="
10081 + (b != null ? b.apps.size() : 0));
10082 if (b != null) {
10083 if (b.apps.size() > 0) {
10084 // Applications have already bound since the last
10085 // unbind, so just rebind right here.
10086 requestServiceBindingLocked(r, b, true);
10087 } else {
10088 // Note to tell the service the next time there is
10089 // a new client.
10090 b.doRebind = true;
10091 }
10092 }
10093
10094 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10095
10096 Binder.restoreCallingIdentity(origId);
10097 }
10098 }
10099 }
10100
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010101 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 synchronized(this) {
10103 if (!(token instanceof ServiceRecord)) {
10104 throw new IllegalArgumentException("Invalid service token");
10105 }
10106 ServiceRecord r = (ServiceRecord)token;
10107 boolean inStopping = mStoppingServices.contains(token);
10108 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010110 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010111 + " with incorrect token: given " + token
10112 + ", expected " + r);
10113 return;
10114 }
10115
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010116 if (type == 1) {
10117 // This is a call from a service start... take care of
10118 // book-keeping.
10119 r.callStart = true;
10120 switch (res) {
10121 case Service.START_STICKY_COMPATIBILITY:
10122 case Service.START_STICKY: {
10123 // We are done with the associated start arguments.
10124 r.findDeliveredStart(startId, true);
10125 // Don't stop if killed.
10126 r.stopIfKilled = false;
10127 break;
10128 }
10129 case Service.START_NOT_STICKY: {
10130 // We are done with the associated start arguments.
10131 r.findDeliveredStart(startId, true);
10132 if (r.lastStartId == startId) {
10133 // There is no more work, and this service
10134 // doesn't want to hang around if killed.
10135 r.stopIfKilled = true;
10136 }
10137 break;
10138 }
10139 case Service.START_REDELIVER_INTENT: {
10140 // We'll keep this item until they explicitly
10141 // call stop for it, but keep track of the fact
10142 // that it was delivered.
10143 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10144 if (si != null) {
10145 si.deliveryCount = 0;
10146 si.doneExecutingCount++;
10147 // Don't stop if killed.
10148 r.stopIfKilled = true;
10149 }
10150 break;
10151 }
10152 default:
10153 throw new IllegalArgumentException(
10154 "Unknown service start result: " + res);
10155 }
10156 if (res == Service.START_STICKY_COMPATIBILITY) {
10157 r.callStart = false;
10158 }
10159 }
10160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010161 final long origId = Binder.clearCallingIdentity();
10162 serviceDoneExecutingLocked(r, inStopping);
10163 Binder.restoreCallingIdentity(origId);
10164 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010165 Slog.w(TAG, "Done executing unknown service from pid "
10166 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 }
10168 }
10169 }
10170
10171 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010172 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10173 + ": nesting=" + r.executeNesting
10174 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010175 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 r.executeNesting--;
10177 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010178 if (DEBUG_SERVICE) Slog.v(TAG,
10179 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010180 r.app.executingServices.remove(r);
10181 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010182 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10183 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10185 }
10186 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010187 if (DEBUG_SERVICE) Slog.v(TAG,
10188 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010190 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 }
10192 updateOomAdjLocked(r.app);
10193 }
10194 }
10195
10196 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010197 String anrMessage = null;
10198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010199 synchronized(this) {
10200 if (proc.executingServices.size() == 0 || proc.thread == null) {
10201 return;
10202 }
10203 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10204 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10205 ServiceRecord timeout = null;
10206 long nextTime = 0;
10207 while (it.hasNext()) {
10208 ServiceRecord sr = it.next();
10209 if (sr.executingStart < maxTime) {
10210 timeout = sr;
10211 break;
10212 }
10213 if (sr.executingStart > nextTime) {
10214 nextTime = sr.executingStart;
10215 }
10216 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010217 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010218 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010219 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010220 } else {
10221 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10222 msg.obj = proc;
10223 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10224 }
10225 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010226
10227 if (anrMessage != null) {
10228 appNotResponding(proc, null, null, anrMessage);
10229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 }
10231
10232 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010233 // BACKUP AND RESTORE
10234 // =========================================================
10235
10236 // Cause the target app to be launched if necessary and its backup agent
10237 // instantiated. The backup agent will invoke backupAgentCreated() on the
10238 // activity manager to announce its creation.
10239 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010240 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010241 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10242
10243 synchronized(this) {
10244 // !!! TODO: currently no check here that we're already bound
10245 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10246 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10247 synchronized (stats) {
10248 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10249 }
10250
10251 BackupRecord r = new BackupRecord(ss, app, backupMode);
10252 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10253 // startProcessLocked() returns existing proc's record if it's already running
10254 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010255 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010256 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010257 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010258 return false;
10259 }
10260
10261 r.app = proc;
10262 mBackupTarget = r;
10263 mBackupAppName = app.packageName;
10264
Christopher Tate6fa95972009-06-05 18:43:55 -070010265 // Try not to kill the process during backup
10266 updateOomAdjLocked(proc);
10267
Christopher Tate181fafa2009-05-14 11:12:14 -070010268 // If the process is already attached, schedule the creation of the backup agent now.
10269 // If it is not yet live, this will be done when it attaches to the framework.
10270 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010271 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010272 try {
10273 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10274 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010275 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010276 }
10277 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010278 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010279 }
10280 // Invariants: at this point, the target app process exists and the application
10281 // is either already running or in the process of coming up. mBackupTarget and
10282 // mBackupAppName describe the app, so that when it binds back to the AM we
10283 // know that it's scheduled for a backup-agent operation.
10284 }
10285
10286 return true;
10287 }
10288
10289 // A backup agent has just come up
10290 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010291 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010292 + " = " + agent);
10293
10294 synchronized(this) {
10295 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010296 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010297 return;
10298 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010299 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010300
Dianne Hackborn06740692010-09-22 22:46:21 -070010301 long oldIdent = Binder.clearCallingIdentity();
10302 try {
10303 IBackupManager bm = IBackupManager.Stub.asInterface(
10304 ServiceManager.getService(Context.BACKUP_SERVICE));
10305 bm.agentConnected(agentPackageName, agent);
10306 } catch (RemoteException e) {
10307 // can't happen; the backup manager service is local
10308 } catch (Exception e) {
10309 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10310 e.printStackTrace();
10311 } finally {
10312 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010313 }
10314 }
10315
10316 // done with this agent
10317 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010318 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010319 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010320 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010321 return;
10322 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010323
10324 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010325 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010326 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010327 return;
10328 }
10329
Christopher Tate181fafa2009-05-14 11:12:14 -070010330 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010331 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010332 return;
10333 }
10334
Christopher Tate6fa95972009-06-05 18:43:55 -070010335 ProcessRecord proc = mBackupTarget.app;
10336 mBackupTarget = null;
10337 mBackupAppName = null;
10338
10339 // Not backing this app up any more; reset its OOM adjustment
10340 updateOomAdjLocked(proc);
10341
Christopher Tatec7b31e32009-06-10 15:49:30 -070010342 // If the app crashed during backup, 'thread' will be null here
10343 if (proc.thread != null) {
10344 try {
10345 proc.thread.scheduleDestroyBackupAgent(appInfo);
10346 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010347 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010348 e.printStackTrace();
10349 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010350 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010351 }
10352 }
10353 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 // BROADCASTS
10355 // =========================================================
10356
Josh Bartel7f208742010-02-25 11:01:44 -060010357 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 List cur) {
10359 final ContentResolver resolver = mContext.getContentResolver();
10360 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10361 if (list == null) {
10362 return cur;
10363 }
10364 int N = list.size();
10365 for (int i=0; i<N; i++) {
10366 Intent intent = list.get(i);
10367 if (filter.match(resolver, intent, true, TAG) >= 0) {
10368 if (cur == null) {
10369 cur = new ArrayList<Intent>();
10370 }
10371 cur.add(intent);
10372 }
10373 }
10374 return cur;
10375 }
10376
10377 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010378 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 + mBroadcastsScheduled);
10380
10381 if (mBroadcastsScheduled) {
10382 return;
10383 }
10384 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10385 mBroadcastsScheduled = true;
10386 }
10387
10388 public Intent registerReceiver(IApplicationThread caller,
10389 IIntentReceiver receiver, IntentFilter filter, String permission) {
10390 synchronized(this) {
10391 ProcessRecord callerApp = null;
10392 if (caller != null) {
10393 callerApp = getRecordForAppLocked(caller);
10394 if (callerApp == null) {
10395 throw new SecurityException(
10396 "Unable to find app for caller " + caller
10397 + " (pid=" + Binder.getCallingPid()
10398 + ") when registering receiver " + receiver);
10399 }
10400 }
10401
10402 List allSticky = null;
10403
10404 // Look for any matching sticky broadcasts...
10405 Iterator actions = filter.actionsIterator();
10406 if (actions != null) {
10407 while (actions.hasNext()) {
10408 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010409 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 }
10411 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010412 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010413 }
10414
10415 // The first sticky in the list is returned directly back to
10416 // the client.
10417 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10418
Joe Onorato8a9b2202010-02-26 18:56:32 -080010419 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 + ": " + sticky);
10421
10422 if (receiver == null) {
10423 return sticky;
10424 }
10425
10426 ReceiverList rl
10427 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10428 if (rl == null) {
10429 rl = new ReceiverList(this, callerApp,
10430 Binder.getCallingPid(),
10431 Binder.getCallingUid(), receiver);
10432 if (rl.app != null) {
10433 rl.app.receivers.add(rl);
10434 } else {
10435 try {
10436 receiver.asBinder().linkToDeath(rl, 0);
10437 } catch (RemoteException e) {
10438 return sticky;
10439 }
10440 rl.linkedToDeath = true;
10441 }
10442 mRegisteredReceivers.put(receiver.asBinder(), rl);
10443 }
10444 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10445 rl.add(bf);
10446 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010447 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448 }
10449 mReceiverResolver.addFilter(bf);
10450
10451 // Enqueue broadcasts for all existing stickies that match
10452 // this filter.
10453 if (allSticky != null) {
10454 ArrayList receivers = new ArrayList();
10455 receivers.add(bf);
10456
10457 int N = allSticky.size();
10458 for (int i=0; i<N; i++) {
10459 Intent intent = (Intent)allSticky.get(i);
10460 BroadcastRecord r = new BroadcastRecord(intent, null,
10461 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010462 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 if (mParallelBroadcasts.size() == 0) {
10464 scheduleBroadcastsLocked();
10465 }
10466 mParallelBroadcasts.add(r);
10467 }
10468 }
10469
10470 return sticky;
10471 }
10472 }
10473
10474 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010475 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010476
10477 boolean doNext = false;
10478
10479 synchronized(this) {
10480 ReceiverList rl
10481 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10482 if (rl != null) {
10483 if (rl.curBroadcast != null) {
10484 BroadcastRecord r = rl.curBroadcast;
10485 doNext = finishReceiverLocked(
10486 receiver.asBinder(), r.resultCode, r.resultData,
10487 r.resultExtras, r.resultAbort, true);
10488 }
10489
10490 if (rl.app != null) {
10491 rl.app.receivers.remove(rl);
10492 }
10493 removeReceiverLocked(rl);
10494 if (rl.linkedToDeath) {
10495 rl.linkedToDeath = false;
10496 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10497 }
10498 }
10499 }
10500
10501 if (!doNext) {
10502 return;
10503 }
10504
10505 final long origId = Binder.clearCallingIdentity();
10506 processNextBroadcast(false);
10507 trimApplications();
10508 Binder.restoreCallingIdentity(origId);
10509 }
10510
10511 void removeReceiverLocked(ReceiverList rl) {
10512 mRegisteredReceivers.remove(rl.receiver.asBinder());
10513 int N = rl.size();
10514 for (int i=0; i<N; i++) {
10515 mReceiverResolver.removeFilter(rl.get(i));
10516 }
10517 }
10518
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010519 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10520 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10521 ProcessRecord r = mLruProcesses.get(i);
10522 if (r.thread != null) {
10523 try {
10524 r.thread.dispatchPackageBroadcast(cmd, packages);
10525 } catch (RemoteException ex) {
10526 }
10527 }
10528 }
10529 }
10530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 private final int broadcastIntentLocked(ProcessRecord callerApp,
10532 String callerPackage, Intent intent, String resolvedType,
10533 IIntentReceiver resultTo, int resultCode, String resultData,
10534 Bundle map, String requiredPermission,
10535 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10536 intent = new Intent(intent);
10537
Joe Onorato8a9b2202010-02-26 18:56:32 -080010538 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10540 + " ordered=" + ordered);
10541 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010542 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 }
10544
10545 // Handle special intents: if this broadcast is from the package
10546 // manager about a package being removed, we need to remove all of
10547 // its activities from the history stack.
10548 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10549 intent.getAction());
10550 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10551 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010552 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 || uidRemoved) {
10554 if (checkComponentPermission(
10555 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010556 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557 == PackageManager.PERMISSION_GRANTED) {
10558 if (uidRemoved) {
10559 final Bundle intentExtras = intent.getExtras();
10560 final int uid = intentExtras != null
10561 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10562 if (uid >= 0) {
10563 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10564 synchronized (bs) {
10565 bs.removeUidStatsLocked(uid);
10566 }
10567 }
10568 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010569 // If resources are unvailble just force stop all
10570 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010571 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010572 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10573 if (list != null && (list.length > 0)) {
10574 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010575 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010576 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010577 sendPackageBroadcastLocked(
10578 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010579 }
10580 } else {
10581 Uri data = intent.getData();
10582 String ssp;
10583 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10584 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10585 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010586 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010587 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010588 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10589 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10590 new String[] {ssp});
10591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 }
10593 }
10594 }
10595 } else {
10596 String msg = "Permission Denial: " + intent.getAction()
10597 + " broadcast from " + callerPackage + " (pid=" + callingPid
10598 + ", uid=" + callingUid + ")"
10599 + " requires "
10600 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 throw new SecurityException(msg);
10603 }
10604 }
10605
10606 /*
10607 * If this is the time zone changed action, queue up a message that will reset the timezone
10608 * of all currently running processes. This message will get queued up before the broadcast
10609 * happens.
10610 */
10611 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10612 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10613 }
10614
Robert Greenwalt03595d02010-11-02 14:08:23 -070010615 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10616 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10617 }
10618
Robert Greenwalt434203a2010-10-11 16:00:27 -070010619 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10620 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10621 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10622 }
10623
Dianne Hackborn854060af2009-07-09 18:14:31 -070010624 /*
10625 * Prevent non-system code (defined here to be non-persistent
10626 * processes) from sending protected broadcasts.
10627 */
10628 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10629 || callingUid == Process.SHELL_UID || callingUid == 0) {
10630 // Always okay.
10631 } else if (callerApp == null || !callerApp.persistent) {
10632 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010633 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010634 intent.getAction())) {
10635 String msg = "Permission Denial: not allowed to send broadcast "
10636 + intent.getAction() + " from pid="
10637 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010638 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010639 throw new SecurityException(msg);
10640 }
10641 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010642 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010643 return BROADCAST_SUCCESS;
10644 }
10645 }
10646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010647 // Add to the sticky list if requested.
10648 if (sticky) {
10649 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10650 callingPid, callingUid)
10651 != PackageManager.PERMISSION_GRANTED) {
10652 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10653 + callingPid + ", uid=" + callingUid
10654 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010655 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 throw new SecurityException(msg);
10657 }
10658 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010659 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010660 + " and enforce permission " + requiredPermission);
10661 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10662 }
10663 if (intent.getComponent() != null) {
10664 throw new SecurityException(
10665 "Sticky broadcasts can't target a specific component");
10666 }
10667 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10668 if (list == null) {
10669 list = new ArrayList<Intent>();
10670 mStickyBroadcasts.put(intent.getAction(), list);
10671 }
10672 int N = list.size();
10673 int i;
10674 for (i=0; i<N; i++) {
10675 if (intent.filterEquals(list.get(i))) {
10676 // This sticky already exists, replace it.
10677 list.set(i, new Intent(intent));
10678 break;
10679 }
10680 }
10681 if (i >= N) {
10682 list.add(new Intent(intent));
10683 }
10684 }
10685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010686 // Figure out who all will receive this broadcast.
10687 List receivers = null;
10688 List<BroadcastFilter> registeredReceivers = null;
10689 try {
10690 if (intent.getComponent() != null) {
10691 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010692 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010693 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010694 if (ai != null) {
10695 receivers = new ArrayList();
10696 ResolveInfo ri = new ResolveInfo();
10697 ri.activityInfo = ai;
10698 receivers.add(ri);
10699 }
10700 } else {
10701 // Need to resolve the intent to interested receivers...
10702 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10703 == 0) {
10704 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010705 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010706 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 }
Mihai Preda074edef2009-05-18 17:13:31 +020010708 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 }
10710 } catch (RemoteException ex) {
10711 // pm is in same process, this will never happen.
10712 }
10713
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010714 final boolean replacePending =
10715 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10716
Joe Onorato8a9b2202010-02-26 18:56:32 -080010717 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010718 + " replacePending=" + replacePending);
10719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10721 if (!ordered && NR > 0) {
10722 // If we are not serializing this broadcast, then send the
10723 // registered receivers separately so they don't wait for the
10724 // components to be launched.
10725 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10726 callerPackage, callingPid, callingUid, requiredPermission,
10727 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010728 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010729 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 TAG, "Enqueueing parallel broadcast " + r
10731 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010732 boolean replaced = false;
10733 if (replacePending) {
10734 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10735 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010736 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010737 "***** DROPPING PARALLEL: " + intent);
10738 mParallelBroadcasts.set(i, r);
10739 replaced = true;
10740 break;
10741 }
10742 }
10743 }
10744 if (!replaced) {
10745 mParallelBroadcasts.add(r);
10746 scheduleBroadcastsLocked();
10747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 registeredReceivers = null;
10749 NR = 0;
10750 }
10751
10752 // Merge into one list.
10753 int ir = 0;
10754 if (receivers != null) {
10755 // A special case for PACKAGE_ADDED: do not allow the package
10756 // being added to see this broadcast. This prevents them from
10757 // using this as a back door to get run as soon as they are
10758 // installed. Maybe in the future we want to have a special install
10759 // broadcast or such for apps, but we'd like to deliberately make
10760 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010761 String skipPackages[] = null;
10762 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10763 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10764 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10765 Uri data = intent.getData();
10766 if (data != null) {
10767 String pkgName = data.getSchemeSpecificPart();
10768 if (pkgName != null) {
10769 skipPackages = new String[] { pkgName };
10770 }
10771 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010772 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010773 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010774 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010775 if (skipPackages != null && (skipPackages.length > 0)) {
10776 for (String skipPackage : skipPackages) {
10777 if (skipPackage != null) {
10778 int NT = receivers.size();
10779 for (int it=0; it<NT; it++) {
10780 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10781 if (curt.activityInfo.packageName.equals(skipPackage)) {
10782 receivers.remove(it);
10783 it--;
10784 NT--;
10785 }
10786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 }
10788 }
10789 }
10790
10791 int NT = receivers != null ? receivers.size() : 0;
10792 int it = 0;
10793 ResolveInfo curt = null;
10794 BroadcastFilter curr = null;
10795 while (it < NT && ir < NR) {
10796 if (curt == null) {
10797 curt = (ResolveInfo)receivers.get(it);
10798 }
10799 if (curr == null) {
10800 curr = registeredReceivers.get(ir);
10801 }
10802 if (curr.getPriority() >= curt.priority) {
10803 // Insert this broadcast record into the final list.
10804 receivers.add(it, curr);
10805 ir++;
10806 curr = null;
10807 it++;
10808 NT++;
10809 } else {
10810 // Skip to the next ResolveInfo in the final list.
10811 it++;
10812 curt = null;
10813 }
10814 }
10815 }
10816 while (ir < NR) {
10817 if (receivers == null) {
10818 receivers = new ArrayList();
10819 }
10820 receivers.add(registeredReceivers.get(ir));
10821 ir++;
10822 }
10823
10824 if ((receivers != null && receivers.size() > 0)
10825 || resultTo != null) {
10826 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10827 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010828 receivers, resultTo, resultCode, resultData, map, ordered,
10829 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010830 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 TAG, "Enqueueing ordered broadcast " + r
10832 + ": prev had " + mOrderedBroadcasts.size());
10833 if (DEBUG_BROADCAST) {
10834 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010835 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010837 boolean replaced = false;
10838 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010839 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010840 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010841 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010842 "***** DROPPING ORDERED: " + intent);
10843 mOrderedBroadcasts.set(i, r);
10844 replaced = true;
10845 break;
10846 }
10847 }
10848 }
10849 if (!replaced) {
10850 mOrderedBroadcasts.add(r);
10851 scheduleBroadcastsLocked();
10852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 }
10854
10855 return BROADCAST_SUCCESS;
10856 }
10857
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010858 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 // Refuse possible leaked file descriptors
10860 if (intent != null && intent.hasFileDescriptors() == true) {
10861 throw new IllegalArgumentException("File descriptors passed in Intent");
10862 }
10863
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010864 int flags = intent.getFlags();
10865
10866 if (!mProcessesReady) {
10867 // if the caller really truly claims to know what they're doing, go
10868 // ahead and allow the broadcast without launching any receivers
10869 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10870 intent = new Intent(intent);
10871 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10872 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10873 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10874 + " before boot completion");
10875 throw new IllegalStateException("Cannot broadcast before boot completed");
10876 }
10877 }
10878
10879 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10880 throw new IllegalArgumentException(
10881 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10882 }
10883
10884 return intent;
10885 }
10886
10887 public final int broadcastIntent(IApplicationThread caller,
10888 Intent intent, String resolvedType, IIntentReceiver resultTo,
10889 int resultCode, String resultData, Bundle map,
10890 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010892 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10895 final int callingPid = Binder.getCallingPid();
10896 final int callingUid = Binder.getCallingUid();
10897 final long origId = Binder.clearCallingIdentity();
10898 int res = broadcastIntentLocked(callerApp,
10899 callerApp != null ? callerApp.info.packageName : null,
10900 intent, resolvedType, resultTo,
10901 resultCode, resultData, map, requiredPermission, serialized,
10902 sticky, callingPid, callingUid);
10903 Binder.restoreCallingIdentity(origId);
10904 return res;
10905 }
10906 }
10907
10908 int broadcastIntentInPackage(String packageName, int uid,
10909 Intent intent, String resolvedType, IIntentReceiver resultTo,
10910 int resultCode, String resultData, Bundle map,
10911 String requiredPermission, boolean serialized, boolean sticky) {
10912 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010913 intent = verifyBroadcastLocked(intent);
10914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 final long origId = Binder.clearCallingIdentity();
10916 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10917 resultTo, resultCode, resultData, map, requiredPermission,
10918 serialized, sticky, -1, uid);
10919 Binder.restoreCallingIdentity(origId);
10920 return res;
10921 }
10922 }
10923
10924 public final void unbroadcastIntent(IApplicationThread caller,
10925 Intent intent) {
10926 // Refuse possible leaked file descriptors
10927 if (intent != null && intent.hasFileDescriptors() == true) {
10928 throw new IllegalArgumentException("File descriptors passed in Intent");
10929 }
10930
10931 synchronized(this) {
10932 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10933 != PackageManager.PERMISSION_GRANTED) {
10934 String msg = "Permission Denial: unbroadcastIntent() from pid="
10935 + Binder.getCallingPid()
10936 + ", uid=" + Binder.getCallingUid()
10937 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010938 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939 throw new SecurityException(msg);
10940 }
10941 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10942 if (list != null) {
10943 int N = list.size();
10944 int i;
10945 for (i=0; i<N; i++) {
10946 if (intent.filterEquals(list.get(i))) {
10947 list.remove(i);
10948 break;
10949 }
10950 }
10951 }
10952 }
10953 }
10954
10955 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10956 String resultData, Bundle resultExtras, boolean resultAbort,
10957 boolean explicit) {
10958 if (mOrderedBroadcasts.size() == 0) {
10959 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010960 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 }
10962 return false;
10963 }
10964 BroadcastRecord r = mOrderedBroadcasts.get(0);
10965 if (r.receiver == null) {
10966 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010967 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 }
10969 return false;
10970 }
10971 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010972 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 return false;
10974 }
10975 int state = r.state;
10976 r.state = r.IDLE;
10977 if (state == r.IDLE) {
10978 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010979 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 }
10981 }
10982 r.receiver = null;
10983 r.intent.setComponent(null);
10984 if (r.curApp != null) {
10985 r.curApp.curReceiver = null;
10986 }
10987 if (r.curFilter != null) {
10988 r.curFilter.receiverList.curBroadcast = null;
10989 }
10990 r.curFilter = null;
10991 r.curApp = null;
10992 r.curComponent = null;
10993 r.curReceiver = null;
10994 mPendingBroadcast = null;
10995
10996 r.resultCode = resultCode;
10997 r.resultData = resultData;
10998 r.resultExtras = resultExtras;
10999 r.resultAbort = resultAbort;
11000
11001 // We will process the next receiver right now if this is finishing
11002 // an app receiver (which is always asynchronous) or after we have
11003 // come back from calling a receiver.
11004 return state == BroadcastRecord.APP_RECEIVE
11005 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11006 }
11007
11008 public void finishReceiver(IBinder who, int resultCode, String resultData,
11009 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011010 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011
11012 // Refuse possible leaked file descriptors
11013 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11014 throw new IllegalArgumentException("File descriptors passed in Bundle");
11015 }
11016
11017 boolean doNext;
11018
11019 final long origId = Binder.clearCallingIdentity();
11020
11021 synchronized(this) {
11022 doNext = finishReceiverLocked(
11023 who, resultCode, resultData, resultExtras, resultAbort, true);
11024 }
11025
11026 if (doNext) {
11027 processNextBroadcast(false);
11028 }
11029 trimApplications();
11030
11031 Binder.restoreCallingIdentity(origId);
11032 }
11033
Jeff Brown4d94a762010-09-23 11:33:28 -070011034 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 if (r.nextReceiver > 0) {
11036 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11037 if (curReceiver instanceof BroadcastFilter) {
11038 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011039 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 System.identityHashCode(r),
11041 r.intent.getAction(),
11042 r.nextReceiver - 1,
11043 System.identityHashCode(bf));
11044 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011045 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 System.identityHashCode(r),
11047 r.intent.getAction(),
11048 r.nextReceiver - 1,
11049 ((ResolveInfo)curReceiver).toString());
11050 }
11051 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011052 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011054 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 System.identityHashCode(r),
11056 r.intent.getAction(),
11057 r.nextReceiver,
11058 "NONE");
11059 }
11060 }
11061
Jeff Brown4d94a762010-09-23 11:33:28 -070011062 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11063 if (! mPendingBroadcastTimeoutMessage) {
11064 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11065 mHandler.sendMessageAtTime(msg, timeoutTime);
11066 mPendingBroadcastTimeoutMessage = true;
11067 }
11068 }
11069
11070 private final void cancelBroadcastTimeoutLocked() {
11071 if (mPendingBroadcastTimeoutMessage) {
11072 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11073 mPendingBroadcastTimeoutMessage = false;
11074 }
11075 }
11076
11077 private final void broadcastTimeoutLocked(boolean fromMsg) {
11078 if (fromMsg) {
11079 mPendingBroadcastTimeoutMessage = false;
11080 }
11081
11082 if (mOrderedBroadcasts.size() == 0) {
11083 return;
11084 }
11085
11086 long now = SystemClock.uptimeMillis();
11087 BroadcastRecord r = mOrderedBroadcasts.get(0);
11088 if (fromMsg) {
11089 if (mDidDexOpt) {
11090 // Delay timeouts until dexopt finishes.
11091 mDidDexOpt = false;
11092 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11093 setBroadcastTimeoutLocked(timeoutTime);
11094 return;
11095 }
11096 if (! mProcessesReady) {
11097 // Only process broadcast timeouts if the system is ready. That way
11098 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11099 // to do heavy lifting for system up.
11100 return;
11101 }
11102
11103 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11104 if (timeoutTime > now) {
11105 // We can observe premature timeouts because we do not cancel and reset the
11106 // broadcast timeout message after each receiver finishes. Instead, we set up
11107 // an initial timeout then kick it down the road a little further as needed
11108 // when it expires.
11109 if (DEBUG_BROADCAST) Slog.v(TAG,
11110 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11111 + timeoutTime);
11112 setBroadcastTimeoutLocked(timeoutTime);
11113 return;
11114 }
11115 }
11116
11117 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11118 + ", started " + (now - r.receiverTime) + "ms ago");
11119 r.receiverTime = now;
11120 r.anrCount++;
11121
11122 // Current receiver has passed its expiration date.
11123 if (r.nextReceiver <= 0) {
11124 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11125 return;
11126 }
11127
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011128 ProcessRecord app = null;
11129 String anrMessage = null;
11130
Jeff Brown4d94a762010-09-23 11:33:28 -070011131 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11132 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11133 logBroadcastReceiverDiscardLocked(r);
11134 if (curReceiver instanceof BroadcastFilter) {
11135 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11136 if (bf.receiverList.pid != 0
11137 && bf.receiverList.pid != MY_PID) {
11138 synchronized (this.mPidsSelfLocked) {
11139 app = this.mPidsSelfLocked.get(
11140 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011143 } else {
11144 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011146
Jeff Brown4d94a762010-09-23 11:33:28 -070011147 if (app != null) {
11148 anrMessage = "Broadcast of " + r.intent.toString();
11149 }
11150
11151 if (mPendingBroadcast == r) {
11152 mPendingBroadcast = null;
11153 }
11154
11155 // Move on to the next receiver.
11156 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11157 r.resultExtras, r.resultAbort, true);
11158 scheduleBroadcastsLocked();
11159
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011160 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011161 // Post the ANR to the handler since we do not want to process ANRs while
11162 // potentially holding our lock.
11163 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 }
11166
11167 private final void processCurBroadcastLocked(BroadcastRecord r,
11168 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011169 if (DEBUG_BROADCAST) Slog.v(TAG,
11170 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 if (app.thread == null) {
11172 throw new RemoteException();
11173 }
11174 r.receiver = app.thread.asBinder();
11175 r.curApp = app;
11176 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011177 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178
11179 // Tell the application to launch this receiver.
11180 r.intent.setComponent(r.curComponent);
11181
11182 boolean started = false;
11183 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011184 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 "Delivering to component " + r.curComponent
11186 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011187 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11189 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011190 if (DEBUG_BROADCAST) Slog.v(TAG,
11191 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 started = true;
11193 } finally {
11194 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011195 if (DEBUG_BROADCAST) Slog.v(TAG,
11196 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 r.receiver = null;
11198 r.curApp = null;
11199 app.curReceiver = null;
11200 }
11201 }
11202
11203 }
11204
Jeff Brown4d94a762010-09-23 11:33:28 -070011205 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011206 Intent intent, int resultCode, String data, Bundle extras,
11207 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011208 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209 if (app != null && app.thread != null) {
11210 // If we have an app thread, do the call through that so it is
11211 // correctly ordered with other one-way calls.
11212 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011213 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011215 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216 }
11217 }
11218
Jeff Brown4d94a762010-09-23 11:33:28 -070011219 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 BroadcastFilter filter, boolean ordered) {
11221 boolean skip = false;
11222 if (filter.requiredPermission != null) {
11223 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011224 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011225 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011226 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 + r.intent.toString()
11228 + " from " + r.callerPackage + " (pid="
11229 + r.callingPid + ", uid=" + r.callingUid + ")"
11230 + " requires " + filter.requiredPermission
11231 + " due to registered receiver " + filter);
11232 skip = true;
11233 }
11234 }
11235 if (r.requiredPermission != null) {
11236 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011237 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011239 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 + r.intent.toString()
11241 + " to " + filter.receiverList.app
11242 + " (pid=" + filter.receiverList.pid
11243 + ", uid=" + filter.receiverList.uid + ")"
11244 + " requires " + r.requiredPermission
11245 + " due to sender " + r.callerPackage
11246 + " (uid " + r.callingUid + ")");
11247 skip = true;
11248 }
11249 }
11250
11251 if (!skip) {
11252 // If this is not being sent as an ordered broadcast, then we
11253 // don't want to touch the fields that keep track of the current
11254 // state of ordered broadcasts.
11255 if (ordered) {
11256 r.receiver = filter.receiverList.receiver.asBinder();
11257 r.curFilter = filter;
11258 filter.receiverList.curBroadcast = r;
11259 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011260 if (filter.receiverList.app != null) {
11261 // Bump hosting application to no longer be in background
11262 // scheduling class. Note that we can't do that if there
11263 // isn't an app... but we can only be in that case for
11264 // things that directly call the IActivityManager API, which
11265 // are already core system stuff so don't matter for this.
11266 r.curApp = filter.receiverList.app;
11267 filter.receiverList.app.curReceiver = r;
11268 updateOomAdjLocked();
11269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 }
11271 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011272 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011274 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011275 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011277 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011279 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 if (ordered) {
11281 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11282 }
11283 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011284 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 if (ordered) {
11286 r.receiver = null;
11287 r.curFilter = null;
11288 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011289 if (filter.receiverList.app != null) {
11290 filter.receiverList.app.curReceiver = null;
11291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 }
11293 }
11294 }
11295 }
11296
Dianne Hackborn12527f92009-11-11 17:39:50 -080011297 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11298 if (r.callingUid < 0) {
11299 // This was from a registerReceiver() call; ignore it.
11300 return;
11301 }
11302 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11303 MAX_BROADCAST_HISTORY-1);
11304 r.finishTime = SystemClock.uptimeMillis();
11305 mBroadcastHistory[0] = r;
11306 }
11307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308 private final void processNextBroadcast(boolean fromMsg) {
11309 synchronized(this) {
11310 BroadcastRecord r;
11311
Joe Onorato8a9b2202010-02-26 18:56:32 -080011312 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011314 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315
11316 updateCpuStats();
11317
11318 if (fromMsg) {
11319 mBroadcastsScheduled = false;
11320 }
11321
11322 // First, deliver any non-serialized broadcasts right away.
11323 while (mParallelBroadcasts.size() > 0) {
11324 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011325 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011326 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011327 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011328 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 for (int i=0; i<N; i++) {
11330 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011331 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011332 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011334 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011335 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011336 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011337 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011338 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 }
11340
11341 // Now take care of the next serialized one...
11342
11343 // If we are waiting for a process to come up to handle the next
11344 // broadcast, then do nothing at this point. Just in case, we
11345 // check that the process we're waiting for still exists.
11346 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011347 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011348 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011349 + mPendingBroadcast.curApp);
11350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351
11352 boolean isDead;
11353 synchronized (mPidsSelfLocked) {
11354 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11355 }
11356 if (!isDead) {
11357 // It's still alive, so keep waiting
11358 return;
11359 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011360 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011362 mPendingBroadcast.state = BroadcastRecord.IDLE;
11363 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 mPendingBroadcast = null;
11365 }
11366 }
11367
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011368 boolean looped = false;
11369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 do {
11371 if (mOrderedBroadcasts.size() == 0) {
11372 // No more broadcasts pending, so all done!
11373 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011374 if (looped) {
11375 // If we had finished the last ordered broadcast, then
11376 // make sure all processes have correct oom and sched
11377 // adjustments.
11378 updateOomAdjLocked();
11379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 return;
11381 }
11382 r = mOrderedBroadcasts.get(0);
11383 boolean forceReceive = false;
11384
11385 // Ensure that even if something goes awry with the timeout
11386 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011387 // and continue to make progress.
11388 //
11389 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011390 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011391 // one time heavy lifting after system upgrades and can take
11392 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011394 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011395 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 if ((numReceivers > 0) &&
11397 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 + " now=" + now
11400 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011401 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 + " intent=" + r.intent
11403 + " numReceivers=" + numReceivers
11404 + " nextReceiver=" + r.nextReceiver
11405 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011406 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 forceReceive = true;
11408 r.state = BroadcastRecord.IDLE;
11409 }
11410 }
11411
11412 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011413 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 "processNextBroadcast() called when not idle (state="
11415 + r.state + ")");
11416 return;
11417 }
11418
11419 if (r.receivers == null || r.nextReceiver >= numReceivers
11420 || r.resultAbort || forceReceive) {
11421 // No more receivers for this broadcast! Send the final
11422 // result if requested...
11423 if (r.resultTo != null) {
11424 try {
11425 if (DEBUG_BROADCAST) {
11426 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011427 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011428 + " seq=" + seq + " app=" + r.callerApp);
11429 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011430 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011431 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011432 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011433 // Set this to null so that the reference
11434 // (local and remote) isnt kept in the mBroadcastHistory.
11435 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011437 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 }
11439 }
11440
Joe Onorato8a9b2202010-02-26 18:56:32 -080011441 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011442 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443
Joe Onorato8a9b2202010-02-26 18:56:32 -080011444 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011445 + r);
11446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011447 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011448 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011449 mOrderedBroadcasts.remove(0);
11450 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011451 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 continue;
11453 }
11454 } while (r == null);
11455
11456 // Get the next receiver...
11457 int recIdx = r.nextReceiver++;
11458
11459 // Keep track of when this receiver started, and make sure there
11460 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011461 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011463 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464
Joe Onorato8a9b2202010-02-26 18:56:32 -080011465 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011466 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011467 }
11468 if (! mPendingBroadcastTimeoutMessage) {
11469 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011470 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011471 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11472 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011473 }
11474
11475 Object nextReceiver = r.receivers.get(recIdx);
11476 if (nextReceiver instanceof BroadcastFilter) {
11477 // Simple case: this is a registered receiver who gets
11478 // a direct call.
11479 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011480 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011481 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011483 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011484 if (r.receiver == null || !r.ordered) {
11485 // The receiver has already finished, so schedule to
11486 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011487 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11488 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011489 r.state = BroadcastRecord.IDLE;
11490 scheduleBroadcastsLocked();
11491 }
11492 return;
11493 }
11494
11495 // Hard case: need to instantiate the receiver, possibly
11496 // starting its application process to host it.
11497
11498 ResolveInfo info =
11499 (ResolveInfo)nextReceiver;
11500
11501 boolean skip = false;
11502 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011503 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11504 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011505 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011506 if (!info.activityInfo.exported) {
11507 Slog.w(TAG, "Permission Denial: broadcasting "
11508 + r.intent.toString()
11509 + " from " + r.callerPackage + " (pid=" + r.callingPid
11510 + ", uid=" + r.callingUid + ")"
11511 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11512 + " due to receiver " + info.activityInfo.packageName
11513 + "/" + info.activityInfo.name);
11514 } else {
11515 Slog.w(TAG, "Permission Denial: broadcasting "
11516 + r.intent.toString()
11517 + " from " + r.callerPackage + " (pid=" + r.callingPid
11518 + ", uid=" + r.callingUid + ")"
11519 + " requires " + info.activityInfo.permission
11520 + " due to receiver " + info.activityInfo.packageName
11521 + "/" + info.activityInfo.name);
11522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011523 skip = true;
11524 }
11525 if (r.callingUid != Process.SYSTEM_UID &&
11526 r.requiredPermission != null) {
11527 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011528 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011529 checkPermission(r.requiredPermission,
11530 info.activityInfo.applicationInfo.packageName);
11531 } catch (RemoteException e) {
11532 perm = PackageManager.PERMISSION_DENIED;
11533 }
11534 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011535 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 + r.intent + " to "
11537 + info.activityInfo.applicationInfo.packageName
11538 + " requires " + r.requiredPermission
11539 + " due to sender " + r.callerPackage
11540 + " (uid " + r.callingUid + ")");
11541 skip = true;
11542 }
11543 }
11544 if (r.curApp != null && r.curApp.crashing) {
11545 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011546 if (DEBUG_BROADCAST) Slog.v(TAG,
11547 "Skipping deliver ordered " + r + " to " + r.curApp
11548 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 skip = true;
11550 }
11551
11552 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011553 if (DEBUG_BROADCAST) Slog.v(TAG,
11554 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011555 r.receiver = null;
11556 r.curFilter = null;
11557 r.state = BroadcastRecord.IDLE;
11558 scheduleBroadcastsLocked();
11559 return;
11560 }
11561
11562 r.state = BroadcastRecord.APP_RECEIVE;
11563 String targetProcess = info.activityInfo.processName;
11564 r.curComponent = new ComponentName(
11565 info.activityInfo.applicationInfo.packageName,
11566 info.activityInfo.name);
11567 r.curReceiver = info.activityInfo;
11568
11569 // Is this receiver's application already running?
11570 ProcessRecord app = getProcessRecordLocked(targetProcess,
11571 info.activityInfo.applicationInfo.uid);
11572 if (app != null && app.thread != null) {
11573 try {
11574 processCurBroadcastLocked(r, app);
11575 return;
11576 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011577 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 + r.curComponent, e);
11579 }
11580
11581 // If a dead object exception was thrown -- fall through to
11582 // restart the application.
11583 }
11584
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011585 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011586 if (DEBUG_BROADCAST) Slog.v(TAG,
11587 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 if ((r.curApp=startProcessLocked(targetProcess,
11589 info.activityInfo.applicationInfo, true,
11590 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011591 "broadcast", r.curComponent,
11592 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11593 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 // Ah, this recipient is unavailable. Finish it if necessary,
11595 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011596 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011597 + info.activityInfo.applicationInfo.packageName + "/"
11598 + info.activityInfo.applicationInfo.uid + " for broadcast "
11599 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011600 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011601 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11602 r.resultExtras, r.resultAbort, true);
11603 scheduleBroadcastsLocked();
11604 r.state = BroadcastRecord.IDLE;
11605 return;
11606 }
11607
11608 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011609 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 }
11611 }
11612
11613 // =========================================================
11614 // INSTRUMENTATION
11615 // =========================================================
11616
11617 public boolean startInstrumentation(ComponentName className,
11618 String profileFile, int flags, Bundle arguments,
11619 IInstrumentationWatcher watcher) {
11620 // Refuse possible leaked file descriptors
11621 if (arguments != null && arguments.hasFileDescriptors()) {
11622 throw new IllegalArgumentException("File descriptors passed in Bundle");
11623 }
11624
11625 synchronized(this) {
11626 InstrumentationInfo ii = null;
11627 ApplicationInfo ai = null;
11628 try {
11629 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011630 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011632 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 } catch (PackageManager.NameNotFoundException e) {
11634 }
11635 if (ii == null) {
11636 reportStartInstrumentationFailure(watcher, className,
11637 "Unable to find instrumentation info for: " + className);
11638 return false;
11639 }
11640 if (ai == null) {
11641 reportStartInstrumentationFailure(watcher, className,
11642 "Unable to find instrumentation target package: " + ii.targetPackage);
11643 return false;
11644 }
11645
11646 int match = mContext.getPackageManager().checkSignatures(
11647 ii.targetPackage, ii.packageName);
11648 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11649 String msg = "Permission Denial: starting instrumentation "
11650 + className + " from pid="
11651 + Binder.getCallingPid()
11652 + ", uid=" + Binder.getCallingPid()
11653 + " not allowed because package " + ii.packageName
11654 + " does not have a signature matching the target "
11655 + ii.targetPackage;
11656 reportStartInstrumentationFailure(watcher, className, msg);
11657 throw new SecurityException(msg);
11658 }
11659
11660 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011661 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011662 ProcessRecord app = addAppLocked(ai);
11663 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011664 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 app.instrumentationProfileFile = profileFile;
11666 app.instrumentationArguments = arguments;
11667 app.instrumentationWatcher = watcher;
11668 app.instrumentationResultClass = className;
11669 Binder.restoreCallingIdentity(origId);
11670 }
11671
11672 return true;
11673 }
11674
11675 /**
11676 * Report errors that occur while attempting to start Instrumentation. Always writes the
11677 * error to the logs, but if somebody is watching, send the report there too. This enables
11678 * the "am" command to report errors with more information.
11679 *
11680 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11681 * @param cn The component name of the instrumentation.
11682 * @param report The error report.
11683 */
11684 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11685 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011686 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 try {
11688 if (watcher != null) {
11689 Bundle results = new Bundle();
11690 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11691 results.putString("Error", report);
11692 watcher.instrumentationStatus(cn, -1, results);
11693 }
11694 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011695 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 }
11697 }
11698
11699 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11700 if (app.instrumentationWatcher != null) {
11701 try {
11702 // NOTE: IInstrumentationWatcher *must* be oneway here
11703 app.instrumentationWatcher.instrumentationFinished(
11704 app.instrumentationClass,
11705 resultCode,
11706 results);
11707 } catch (RemoteException e) {
11708 }
11709 }
11710 app.instrumentationWatcher = null;
11711 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011712 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011713 app.instrumentationProfileFile = null;
11714 app.instrumentationArguments = null;
11715
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011716 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011717 }
11718
11719 public void finishInstrumentation(IApplicationThread target,
11720 int resultCode, Bundle results) {
11721 // Refuse possible leaked file descriptors
11722 if (results != null && results.hasFileDescriptors()) {
11723 throw new IllegalArgumentException("File descriptors passed in Intent");
11724 }
11725
11726 synchronized(this) {
11727 ProcessRecord app = getRecordForAppLocked(target);
11728 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011729 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 return;
11731 }
11732 final long origId = Binder.clearCallingIdentity();
11733 finishInstrumentationLocked(app, resultCode, results);
11734 Binder.restoreCallingIdentity(origId);
11735 }
11736 }
11737
11738 // =========================================================
11739 // CONFIGURATION
11740 // =========================================================
11741
11742 public ConfigurationInfo getDeviceConfigurationInfo() {
11743 ConfigurationInfo config = new ConfigurationInfo();
11744 synchronized (this) {
11745 config.reqTouchScreen = mConfiguration.touchscreen;
11746 config.reqKeyboardType = mConfiguration.keyboard;
11747 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011748 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11749 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11751 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011752 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11753 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11755 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011756 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 }
11758 return config;
11759 }
11760
11761 public Configuration getConfiguration() {
11762 Configuration ci;
11763 synchronized(this) {
11764 ci = new Configuration(mConfiguration);
11765 }
11766 return ci;
11767 }
11768
11769 public void updateConfiguration(Configuration values) {
11770 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11771 "updateConfiguration()");
11772
11773 synchronized(this) {
11774 if (values == null && mWindowManager != null) {
11775 // sentinel: fetch the current configuration from the window manager
11776 values = mWindowManager.computeNewConfiguration();
11777 }
11778
11779 final long origId = Binder.clearCallingIdentity();
11780 updateConfigurationLocked(values, null);
11781 Binder.restoreCallingIdentity(origId);
11782 }
11783 }
11784
11785 /**
11786 * Do either or both things: (1) change the current configuration, and (2)
11787 * make sure the given activity is running with the (now) current
11788 * configuration. Returns true if the activity has been left running, or
11789 * false if <var>starting</var> is being destroyed to match the new
11790 * configuration.
11791 */
11792 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011793 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 int changes = 0;
11795
11796 boolean kept = true;
11797
11798 if (values != null) {
11799 Configuration newConfig = new Configuration(mConfiguration);
11800 changes = newConfig.updateFrom(values);
11801 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011802 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011803 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 }
11805
Doug Zongker2bec3d42009-12-04 12:52:44 -080011806 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807
11808 if (values.locale != null) {
11809 saveLocaleLocked(values.locale,
11810 !values.locale.equals(mConfiguration.locale),
11811 values.userSetLocale);
11812 }
11813
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011814 mConfigurationSeq++;
11815 if (mConfigurationSeq <= 0) {
11816 mConfigurationSeq = 1;
11817 }
11818 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011820 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011821
11822 AttributeCache ac = AttributeCache.instance();
11823 if (ac != null) {
11824 ac.updateConfiguration(mConfiguration);
11825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011827 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11828 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11829 msg.obj = new Configuration(mConfiguration);
11830 mHandler.sendMessage(msg);
11831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011832
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011833 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11834 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 try {
11836 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011837 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011838 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 app.thread.scheduleConfigurationChanged(mConfiguration);
11840 }
11841 } catch (Exception e) {
11842 }
11843 }
11844 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011845 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11846 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011847 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11848 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011849 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11850 broadcastIntentLocked(null, null,
11851 new Intent(Intent.ACTION_LOCALE_CHANGED),
11852 null, null, 0, null, null,
11853 null, false, false, MY_PID, Process.SYSTEM_UID);
11854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011855 }
11856 }
11857
11858 if (changes != 0 && starting == null) {
11859 // If the configuration changed, and the caller is not already
11860 // in the process of starting an activity, then find the top
11861 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011862 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863 }
11864
11865 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011866 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011867 // And we need to make sure at this point that all other activities
11868 // are made visible with the correct configuration.
11869 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 }
11871
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011872 if (values != null && mWindowManager != null) {
11873 mWindowManager.setNewConfiguration(mConfiguration);
11874 }
11875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 return kept;
11877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878
11879 /**
11880 * Save the locale. You must be inside a synchronized (this) block.
11881 */
11882 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11883 if(isDiff) {
11884 SystemProperties.set("user.language", l.getLanguage());
11885 SystemProperties.set("user.region", l.getCountry());
11886 }
11887
11888 if(isPersist) {
11889 SystemProperties.set("persist.sys.language", l.getLanguage());
11890 SystemProperties.set("persist.sys.country", l.getCountry());
11891 SystemProperties.set("persist.sys.localevar", l.getVariant());
11892 }
11893 }
11894
11895 // =========================================================
11896 // LIFETIME MANAGEMENT
11897 // =========================================================
11898
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011899 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11900 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011901 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011902 // This adjustment has already been computed. If we are calling
11903 // from the top, we may have already computed our adjustment with
11904 // an earlier hidden adjustment that isn't really for us... if
11905 // so, use the new hidden adjustment.
11906 if (!recursed && app.hidden) {
11907 app.curAdj = hiddenAdj;
11908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 return app.curAdj;
11910 }
11911
11912 if (app.thread == null) {
11913 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011914 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011915 return (app.curAdj=EMPTY_APP_ADJ);
11916 }
11917
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011918 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11919 // The max adjustment doesn't allow this app to be anything
11920 // below foreground, so it is not worth doing work for it.
11921 app.adjType = "fixed";
11922 app.adjSeq = mAdjSeq;
11923 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011924 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011925 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11926 return (app.curAdj=app.maxAdj);
11927 }
11928
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011929 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011930 app.adjSource = null;
11931 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011932 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011933 app.empty = false;
11934 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011935
The Android Open Source Project4df24232009-03-05 14:34:35 -080011936 // Determine the importance of the process, starting with most
11937 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011939 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011941 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942 // The last app on the list is the foreground app.
11943 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011944 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011945 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011946 } else if (app.instrumentationClass != null) {
11947 // Don't want to kill running instrumentation.
11948 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011949 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011950 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011951 } else if (app.curReceiver != null ||
11952 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11953 // An app that is currently receiving a broadcast also
11954 // counts as being in the foreground.
11955 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011956 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011957 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011958 } else if (app.executingServices.size() > 0) {
11959 // An app that is currently executing a service callback also
11960 // counts as being in the foreground.
11961 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011962 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011963 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011964 } else if ((N=app.activities.size()) != 0) {
11965 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011966 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011967 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011968 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011969 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011970 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011972 ActivityRecord r = app.activities.get(j);
11973 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011974 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011975 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011977 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011978 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011980 } else if (r.state == ActivityState.PAUSING
11981 || r.state == ActivityState.PAUSED
11982 || r.state == ActivityState.STOPPING) {
11983 adj = PERCEPTIBLE_APP_ADJ;
11984 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011985 }
11986 }
11987 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011988 // A very not-needed process. If this is lower in the lru list,
11989 // we will push it in to the empty bucket.
11990 app.hidden = true;
11991 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011992 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011993 adj = hiddenAdj;
11994 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011995 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080011996
11997 if (adj > PERCEPTIBLE_APP_ADJ) {
11998 if (app.foregroundServices) {
11999 // The user is aware of this app, so make it visible.
12000 adj = PERCEPTIBLE_APP_ADJ;
12001 schedGroup = Process.THREAD_GROUP_DEFAULT;
12002 app.adjType = "foreground-service";
12003 } else if (app.forcingToForeground != null) {
12004 // The user is aware of this app, so make it visible.
12005 adj = PERCEPTIBLE_APP_ADJ;
12006 schedGroup = Process.THREAD_GROUP_DEFAULT;
12007 app.adjType = "force-foreground";
12008 app.adjSource = app.forcingToForeground;
12009 }
12010 }
12011
12012 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12013 // We don't want to kill the current heavy-weight process.
12014 adj = HEAVY_WEIGHT_APP_ADJ;
12015 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12016 app.adjType = "heavy";
12017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012019 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12020 // This process is hosting what we currently consider to be the
12021 // home app, so we don't want to let it go into the background.
12022 adj = HOME_APP_ADJ;
12023 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12024 app.adjType = "home";
12025 }
12026
Joe Onorato8a9b2202010-02-26 18:56:32 -080012027 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012028
The Android Open Source Project4df24232009-03-05 14:34:35 -080012029 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030 // there are applications dependent on our services or providers, but
12031 // this gives us a baseline and makes sure we don't get into an
12032 // infinite recursion.
12033 app.adjSeq = mAdjSeq;
12034 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035
Christopher Tate6fa95972009-06-05 18:43:55 -070012036 if (mBackupTarget != null && app == mBackupTarget.app) {
12037 // If possible we want to avoid killing apps while they're being backed up
12038 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012039 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012040 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012041 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012042 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012043 }
12044 }
12045
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012046 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12047 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048 final long now = SystemClock.uptimeMillis();
12049 // This process is more important if the top activity is
12050 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012051 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012053 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012054 if (s.startRequested) {
12055 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12056 // This service has seen some activity within
12057 // recent memory, so we will keep its process ahead
12058 // of the background processes.
12059 if (adj > SECONDARY_SERVER_ADJ) {
12060 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012061 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012062 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 }
12064 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012065 // If we have let the service slide into the background
12066 // state, still have some text describing what it is doing
12067 // even though the service no longer has an impact.
12068 if (adj > SECONDARY_SERVER_ADJ) {
12069 app.adjType = "started-bg-services";
12070 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012071 // Don't kill this process because it is doing work; it
12072 // has said it is doing work.
12073 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012075 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12076 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012077 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012078 = s.connections.values().iterator();
12079 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012080 ArrayList<ConnectionRecord> clist = kt.next();
12081 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12082 // XXX should compute this based on the max of
12083 // all connected clients.
12084 ConnectionRecord cr = clist.get(i);
12085 if (cr.binding.client == app) {
12086 // Binding to ourself is not interesting.
12087 continue;
12088 }
12089 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12090 ProcessRecord client = cr.binding.client;
12091 int myHiddenAdj = hiddenAdj;
12092 if (myHiddenAdj > client.hiddenAdj) {
12093 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12094 myHiddenAdj = client.hiddenAdj;
12095 } else {
12096 myHiddenAdj = VISIBLE_APP_ADJ;
12097 }
12098 }
12099 int clientAdj = computeOomAdjLocked(
12100 client, myHiddenAdj, TOP_APP, true);
12101 if (adj > clientAdj) {
12102 adj = clientAdj >= VISIBLE_APP_ADJ
12103 ? clientAdj : VISIBLE_APP_ADJ;
12104 if (!client.hidden) {
12105 app.hidden = false;
12106 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012107 if (client.keeping) {
12108 app.keeping = true;
12109 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012110 app.adjType = "service";
12111 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12112 .REASON_SERVICE_IN_USE;
12113 app.adjSource = cr.binding.client;
12114 app.adjTarget = s.name;
12115 }
12116 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12117 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12118 schedGroup = Process.THREAD_GROUP_DEFAULT;
12119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 }
12121 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012122 ActivityRecord a = cr.activity;
12123 //if (a != null) {
12124 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12125 //}
12126 if (a != null && adj > FOREGROUND_APP_ADJ &&
12127 (a.state == ActivityState.RESUMED
12128 || a.state == ActivityState.PAUSING)) {
12129 adj = FOREGROUND_APP_ADJ;
12130 schedGroup = Process.THREAD_GROUP_DEFAULT;
12131 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012132 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012133 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12134 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012135 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012136 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012138 }
12139 }
12140 }
12141 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012142
Dianne Hackborn287952c2010-09-22 22:34:31 -070012143 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012144 // would like to avoid killing it unless it would prevent the current
12145 // application from running. By default we put the process in
12146 // with the rest of the background processes; as we scan through
12147 // its services we may bump it up from there.
12148 if (adj > hiddenAdj) {
12149 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012150 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012151 app.adjType = "bg-services";
12152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 }
12154
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012155 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12156 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012157 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012158 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12159 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012160 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012161 if (cpr.clients.size() != 0) {
12162 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12163 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12164 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012165 if (client == app) {
12166 // Being our own client is not interesting.
12167 continue;
12168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 int myHiddenAdj = hiddenAdj;
12170 if (myHiddenAdj > client.hiddenAdj) {
12171 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12172 myHiddenAdj = client.hiddenAdj;
12173 } else {
12174 myHiddenAdj = FOREGROUND_APP_ADJ;
12175 }
12176 }
12177 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012178 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012179 if (adj > clientAdj) {
12180 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012181 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012182 if (!client.hidden) {
12183 app.hidden = false;
12184 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012185 if (client.keeping) {
12186 app.keeping = true;
12187 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012188 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012189 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12190 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012191 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012192 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012193 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012194 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12195 schedGroup = Process.THREAD_GROUP_DEFAULT;
12196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 }
12198 }
12199 // If the provider has external (non-framework) process
12200 // dependencies, ensure that its adjustment is at least
12201 // FOREGROUND_APP_ADJ.
12202 if (cpr.externals != 0) {
12203 if (adj > FOREGROUND_APP_ADJ) {
12204 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012205 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012206 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012207 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012208 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012209 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 }
12211 }
12212 }
12213 }
12214
12215 app.curRawAdj = adj;
12216
Joe Onorato8a9b2202010-02-26 18:56:32 -080012217 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012218 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12219 if (adj > app.maxAdj) {
12220 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012221 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012222 schedGroup = Process.THREAD_GROUP_DEFAULT;
12223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012224 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012225 if (adj < HIDDEN_APP_MIN_ADJ) {
12226 app.keeping = true;
12227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012228
12229 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012230 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232 return adj;
12233 }
12234
12235 /**
12236 * Ask a given process to GC right now.
12237 */
12238 final void performAppGcLocked(ProcessRecord app) {
12239 try {
12240 app.lastRequestedGc = SystemClock.uptimeMillis();
12241 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012242 if (app.reportLowMemory) {
12243 app.reportLowMemory = false;
12244 app.thread.scheduleLowMemory();
12245 } else {
12246 app.thread.processInBackground();
12247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012248 }
12249 } catch (Exception e) {
12250 // whatever.
12251 }
12252 }
12253
12254 /**
12255 * Returns true if things are idle enough to perform GCs.
12256 */
Josh Bartel7f208742010-02-25 11:01:44 -060012257 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 return mParallelBroadcasts.size() == 0
12259 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012260 && (mSleeping || (mMainStack.mResumedActivity != null &&
12261 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 }
12263
12264 /**
12265 * Perform GCs on all processes that are waiting for it, but only
12266 * if things are idle.
12267 */
12268 final void performAppGcsLocked() {
12269 final int N = mProcessesToGc.size();
12270 if (N <= 0) {
12271 return;
12272 }
Josh Bartel7f208742010-02-25 11:01:44 -060012273 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 while (mProcessesToGc.size() > 0) {
12275 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012276 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012277 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12278 <= SystemClock.uptimeMillis()) {
12279 // To avoid spamming the system, we will GC processes one
12280 // at a time, waiting a few seconds between each.
12281 performAppGcLocked(proc);
12282 scheduleAppGcsLocked();
12283 return;
12284 } else {
12285 // It hasn't been long enough since we last GCed this
12286 // process... put it in the list to wait for its time.
12287 addProcessToGcListLocked(proc);
12288 break;
12289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012290 }
12291 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012292
12293 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 }
12295 }
12296
12297 /**
12298 * If all looks good, perform GCs on all processes waiting for them.
12299 */
12300 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012301 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012302 performAppGcsLocked();
12303 return;
12304 }
12305 // Still not idle, wait some more.
12306 scheduleAppGcsLocked();
12307 }
12308
12309 /**
12310 * Schedule the execution of all pending app GCs.
12311 */
12312 final void scheduleAppGcsLocked() {
12313 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012314
12315 if (mProcessesToGc.size() > 0) {
12316 // Schedule a GC for the time to the next process.
12317 ProcessRecord proc = mProcessesToGc.get(0);
12318 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12319
12320 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12321 long now = SystemClock.uptimeMillis();
12322 if (when < (now+GC_TIMEOUT)) {
12323 when = now + GC_TIMEOUT;
12324 }
12325 mHandler.sendMessageAtTime(msg, when);
12326 }
12327 }
12328
12329 /**
12330 * Add a process to the array of processes waiting to be GCed. Keeps the
12331 * list in sorted order by the last GC time. The process can't already be
12332 * on the list.
12333 */
12334 final void addProcessToGcListLocked(ProcessRecord proc) {
12335 boolean added = false;
12336 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12337 if (mProcessesToGc.get(i).lastRequestedGc <
12338 proc.lastRequestedGc) {
12339 added = true;
12340 mProcessesToGc.add(i+1, proc);
12341 break;
12342 }
12343 }
12344 if (!added) {
12345 mProcessesToGc.add(0, proc);
12346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 }
12348
12349 /**
12350 * Set up to ask a process to GC itself. This will either do it
12351 * immediately, or put it on the list of processes to gc the next
12352 * time things are idle.
12353 */
12354 final void scheduleAppGcLocked(ProcessRecord app) {
12355 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012356 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012357 return;
12358 }
12359 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012360 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012361 scheduleAppGcsLocked();
12362 }
12363 }
12364
Dianne Hackborn287952c2010-09-22 22:34:31 -070012365 final void checkExcessivePowerUsageLocked(boolean doKills) {
12366 updateCpuStatsNow();
12367
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012368 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012369 boolean doWakeKills = doKills;
12370 boolean doCpuKills = doKills;
12371 if (mLastPowerCheckRealtime == 0) {
12372 doWakeKills = false;
12373 }
12374 if (mLastPowerCheckUptime == 0) {
12375 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012376 }
12377 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012378 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012379 }
12380 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012381 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12382 final long curUptime = SystemClock.uptimeMillis();
12383 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12384 mLastPowerCheckRealtime = curRealtime;
12385 mLastPowerCheckUptime = curUptime;
12386 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12387 doWakeKills = false;
12388 }
12389 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12390 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012391 }
12392 int i = mLruProcesses.size();
12393 while (i > 0) {
12394 i--;
12395 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012396 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012397 long wtime;
12398 synchronized (stats) {
12399 wtime = stats.getProcessWakeTime(app.info.uid,
12400 app.pid, curRealtime);
12401 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012402 long wtimeUsed = wtime - app.lastWakeTime;
12403 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12404 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012405 StringBuilder sb = new StringBuilder(128);
12406 sb.append("Wake for ");
12407 app.toShortString(sb);
12408 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012409 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012410 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012411 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012412 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012413 sb.append((wtimeUsed*100)/realtimeSince);
12414 sb.append("%)");
12415 Slog.i(TAG, sb.toString());
12416 sb.setLength(0);
12417 sb.append("CPU for ");
12418 app.toShortString(sb);
12419 sb.append(": over ");
12420 TimeUtils.formatDuration(uptimeSince, sb);
12421 sb.append(" used ");
12422 TimeUtils.formatDuration(cputimeUsed, sb);
12423 sb.append(" (");
12424 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012425 sb.append("%)");
12426 Slog.i(TAG, sb.toString());
12427 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012428 // If a process has held a wake lock for more
12429 // than 50% of the time during this period,
12430 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012431 if (doWakeKills && realtimeSince > 0
12432 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12433 synchronized (stats) {
12434 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12435 realtimeSince, wtimeUsed);
12436 }
12437 Slog.w(TAG, "Excessive wake lock in " + app.processName
12438 + " (pid " + app.pid + "): held " + wtimeUsed
12439 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012440 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12441 app.processName, app.setAdj, "excessive wake lock");
12442 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012443 } else if (doCpuKills && uptimeSince > 0
12444 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12445 synchronized (stats) {
12446 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12447 uptimeSince, cputimeUsed);
12448 }
12449 Slog.w(TAG, "Excessive CPU in " + app.processName
12450 + " (pid " + app.pid + "): used " + cputimeUsed
12451 + " during " + uptimeSince);
12452 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12453 app.processName, app.setAdj, "excessive cpu");
12454 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012455 } else {
12456 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012457 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012458 }
12459 }
12460 }
12461 }
12462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012463 private final boolean updateOomAdjLocked(
12464 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12465 app.hiddenAdj = hiddenAdj;
12466
12467 if (app.thread == null) {
12468 return true;
12469 }
12470
Dianne Hackborn287952c2010-09-22 22:34:31 -070012471 final boolean wasKeeping = app.keeping;
12472
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012473 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012474
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012475 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012476 if (app.curRawAdj != app.setRawAdj) {
12477 if (app.curRawAdj > FOREGROUND_APP_ADJ
12478 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12479 // If this app is transitioning from foreground to
12480 // non-foreground, have it do a gc.
12481 scheduleAppGcLocked(app);
12482 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12483 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12484 // Likewise do a gc when an app is moving in to the
12485 // background (such as a service stopping).
12486 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012487 }
12488
12489 if (wasKeeping && !app.keeping) {
12490 // This app is no longer something we want to keep. Note
12491 // its current wake lock time to later know to kill it if
12492 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012493 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12494 synchronized (stats) {
12495 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12496 app.pid, SystemClock.elapsedRealtime());
12497 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012498 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012499 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012501 app.setRawAdj = app.curRawAdj;
12502 }
12503 if (adj != app.setAdj) {
12504 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012505 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 TAG, "Set app " + app.processName +
12507 " oom adj to " + adj);
12508 app.setAdj = adj;
12509 } else {
12510 return false;
12511 }
12512 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012513 if (app.setSchedGroup != app.curSchedGroup) {
12514 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012515 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012516 "Setting process group of " + app.processName
12517 + " to " + app.curSchedGroup);
12518 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012519 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012520 try {
12521 Process.setProcessGroup(app.pid, app.curSchedGroup);
12522 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012523 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012524 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012525 e.printStackTrace();
12526 } finally {
12527 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012528 }
12529 }
12530 if (false) {
12531 if (app.thread != null) {
12532 try {
12533 app.thread.setSchedulingGroup(app.curSchedGroup);
12534 } catch (RemoteException e) {
12535 }
12536 }
12537 }
12538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539 }
12540
12541 return true;
12542 }
12543
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012544 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012545 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012546 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012547 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012549 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 }
12551 }
12552 return resumedActivity;
12553 }
12554
12555 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012556 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012557 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12558 int curAdj = app.curAdj;
12559 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12560 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12561
12562 mAdjSeq++;
12563
12564 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12565 if (res) {
12566 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12567 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12568 if (nowHidden != wasHidden) {
12569 // Changed to/from hidden state, so apps after it in the LRU
12570 // list may also be changed.
12571 updateOomAdjLocked();
12572 }
12573 }
12574 return res;
12575 }
12576
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012577 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012579 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012580 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12581
12582 if (false) {
12583 RuntimeException e = new RuntimeException();
12584 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012585 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012586 }
12587
12588 mAdjSeq++;
12589
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012590 // Let's determine how many processes we have running vs.
12591 // how many slots we have for background processes; we may want
12592 // to put multiple processes in a slot of there are enough of
12593 // them.
12594 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12595 int factor = (mLruProcesses.size()-4)/numSlots;
12596 if (factor < 1) factor = 1;
12597 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012598 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 // First try updating the OOM adjustment for each of the
12601 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012602 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12604 while (i > 0) {
12605 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012606 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012607 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012608 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012609 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012610 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012611 step++;
12612 if (step >= factor) {
12613 step = 0;
12614 curHiddenAdj++;
12615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012616 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012617 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012618 if (!app.killedBackground) {
12619 numHidden++;
12620 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012621 Slog.i(TAG, "No longer want " + app.processName
12622 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012623 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12624 app.processName, app.setAdj, "too many background");
12625 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012626 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012627 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012628 }
12629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630 } else {
12631 didOomAdj = false;
12632 }
12633 }
12634
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012635 // If we return false, we will fall back on killing processes to
12636 // have a fixed limit. Do this if a limit has been requested; else
12637 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012638 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12639 }
12640
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012641 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 synchronized (this) {
12643 int i;
12644
12645 // First remove any unused application processes whose package
12646 // has been removed.
12647 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12648 final ProcessRecord app = mRemovedProcesses.get(i);
12649 if (app.activities.size() == 0
12650 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012651 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012652 TAG, "Exiting empty application process "
12653 + app.processName + " ("
12654 + (app.thread != null ? app.thread.asBinder() : null)
12655 + ")\n");
12656 if (app.pid > 0 && app.pid != MY_PID) {
12657 Process.killProcess(app.pid);
12658 } else {
12659 try {
12660 app.thread.scheduleExit();
12661 } catch (Exception e) {
12662 // Ignore exceptions.
12663 }
12664 }
12665 cleanUpApplicationRecordLocked(app, false, -1);
12666 mRemovedProcesses.remove(i);
12667
12668 if (app.persistent) {
12669 if (app.persistent) {
12670 addAppLocked(app.info);
12671 }
12672 }
12673 }
12674 }
12675
12676 // Now try updating the OOM adjustment for each of the
12677 // application processes based on their current state.
12678 // If the setOomAdj() API is not supported, then go with our
12679 // back-up plan...
12680 if (!updateOomAdjLocked()) {
12681
12682 // Count how many processes are running services.
12683 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012684 for (i=mLruProcesses.size()-1; i>=0; i--) {
12685 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012686
12687 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012688 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012689 // Don't count processes holding services against our
12690 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012691 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012692 TAG, "Not trimming app " + app + " with services: "
12693 + app.services);
12694 numServiceProcs++;
12695 }
12696 }
12697
12698 int curMaxProcs = mProcessLimit;
12699 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12700 if (mAlwaysFinishActivities) {
12701 curMaxProcs = 1;
12702 }
12703 curMaxProcs += numServiceProcs;
12704
12705 // Quit as many processes as we can to get down to the desired
12706 // process count. First remove any processes that no longer
12707 // have activites running in them.
12708 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012709 i<mLruProcesses.size()
12710 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012712 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012713 // Quit an application only if it is not currently
12714 // running any activities.
12715 if (!app.persistent && app.activities.size() == 0
12716 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012717 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 TAG, "Exiting empty application process "
12719 + app.processName + " ("
12720 + (app.thread != null ? app.thread.asBinder() : null)
12721 + ")\n");
12722 if (app.pid > 0 && app.pid != MY_PID) {
12723 Process.killProcess(app.pid);
12724 } else {
12725 try {
12726 app.thread.scheduleExit();
12727 } catch (Exception e) {
12728 // Ignore exceptions.
12729 }
12730 }
12731 // todo: For now we assume the application is not buggy
12732 // or evil, and will quit as a result of our request.
12733 // Eventually we need to drive this off of the death
12734 // notification, and kill the process if it takes too long.
12735 cleanUpApplicationRecordLocked(app, false, i);
12736 i--;
12737 }
12738 }
12739
12740 // If we still have too many processes, now from the least
12741 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012742 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012743 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012744 " of " + curMaxProcs + " processes");
12745 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012746 i<mLruProcesses.size()
12747 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012748 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012749 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012750 // Quit the application only if we have a state saved for
12751 // all of its activities.
12752 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012753 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012754 int NUMA = app.activities.size();
12755 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012756 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 TAG, "Looking to quit " + app.processName);
12758 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012759 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012760 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012761 TAG, " " + r.intent.getComponent().flattenToShortString()
12762 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12763 canQuit = (r.haveState || !r.stateNotNeeded)
12764 && !r.visible && r.stopped;
12765 }
12766 if (canQuit) {
12767 // Finish all of the activities, and then the app itself.
12768 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012769 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012771 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012772 }
12773 r.resultTo = null;
12774 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012775 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012776 + app.processName + " ("
12777 + (app.thread != null ? app.thread.asBinder() : null)
12778 + ")\n");
12779 if (app.pid > 0 && app.pid != MY_PID) {
12780 Process.killProcess(app.pid);
12781 } else {
12782 try {
12783 app.thread.scheduleExit();
12784 } catch (Exception e) {
12785 // Ignore exceptions.
12786 }
12787 }
12788 // todo: For now we assume the application is not buggy
12789 // or evil, and will quit as a result of our request.
12790 // Eventually we need to drive this off of the death
12791 // notification, and kill the process if it takes too long.
12792 cleanUpApplicationRecordLocked(app, false, i);
12793 i--;
12794 //dump();
12795 }
12796 }
12797
12798 }
12799
12800 int curMaxActivities = MAX_ACTIVITIES;
12801 if (mAlwaysFinishActivities) {
12802 curMaxActivities = 1;
12803 }
12804
12805 // Finally, if there are too many activities now running, try to
12806 // finish as many as we can to get back down to the limit.
12807 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012808 i<mMainStack.mLRUActivities.size()
12809 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012810 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012811 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012812 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012813
12814 // We can finish this one if we have its icicle saved and
12815 // it is not persistent.
12816 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012817 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012818 final int origSize = mMainStack.mLRUActivities.size();
12819 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012820
12821 // This will remove it from the LRU list, so keep
12822 // our index at the same value. Note that this check to
12823 // see if the size changes is just paranoia -- if
12824 // something unexpected happens, we don't want to end up
12825 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012826 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012827 i--;
12828 }
12829 }
12830 }
12831 }
12832 }
12833
12834 /** This method sends the specified signal to each of the persistent apps */
12835 public void signalPersistentProcesses(int sig) throws RemoteException {
12836 if (sig != Process.SIGNAL_USR1) {
12837 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12838 }
12839
12840 synchronized (this) {
12841 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12842 != PackageManager.PERMISSION_GRANTED) {
12843 throw new SecurityException("Requires permission "
12844 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12845 }
12846
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012847 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12848 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012849 if (r.thread != null && r.persistent) {
12850 Process.sendSignal(r.pid, sig);
12851 }
12852 }
12853 }
12854 }
12855
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012856 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012857 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012858
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012859 try {
12860 synchronized (this) {
12861 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12862 // its own permission.
12863 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12864 != PackageManager.PERMISSION_GRANTED) {
12865 throw new SecurityException("Requires permission "
12866 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012867 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012868
12869 if (start && fd == null) {
12870 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012871 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012872
12873 ProcessRecord proc = null;
12874 try {
12875 int pid = Integer.parseInt(process);
12876 synchronized (mPidsSelfLocked) {
12877 proc = mPidsSelfLocked.get(pid);
12878 }
12879 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012880 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012881
12882 if (proc == null) {
12883 HashMap<String, SparseArray<ProcessRecord>> all
12884 = mProcessNames.getMap();
12885 SparseArray<ProcessRecord> procs = all.get(process);
12886 if (procs != null && procs.size() > 0) {
12887 proc = procs.valueAt(0);
12888 }
12889 }
12890
12891 if (proc == null || proc.thread == null) {
12892 throw new IllegalArgumentException("Unknown process: " + process);
12893 }
12894
12895 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12896 if (isSecure) {
12897 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12898 throw new SecurityException("Process not debuggable: " + proc);
12899 }
12900 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012901
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012902 proc.thread.profilerControl(start, path, fd);
12903 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012904 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012905 }
12906 } catch (RemoteException e) {
12907 throw new IllegalStateException("Process disappeared");
12908 } finally {
12909 if (fd != null) {
12910 try {
12911 fd.close();
12912 } catch (IOException e) {
12913 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012914 }
12915 }
12916 }
Andy McFadden824c5102010-07-09 16:26:57 -070012917
12918 public boolean dumpHeap(String process, boolean managed,
12919 String path, ParcelFileDescriptor fd) throws RemoteException {
12920
12921 try {
12922 synchronized (this) {
12923 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12924 // its own permission (same as profileControl).
12925 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12926 != PackageManager.PERMISSION_GRANTED) {
12927 throw new SecurityException("Requires permission "
12928 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12929 }
12930
12931 if (fd == null) {
12932 throw new IllegalArgumentException("null fd");
12933 }
12934
12935 ProcessRecord proc = null;
12936 try {
12937 int pid = Integer.parseInt(process);
12938 synchronized (mPidsSelfLocked) {
12939 proc = mPidsSelfLocked.get(pid);
12940 }
12941 } catch (NumberFormatException e) {
12942 }
12943
12944 if (proc == null) {
12945 HashMap<String, SparseArray<ProcessRecord>> all
12946 = mProcessNames.getMap();
12947 SparseArray<ProcessRecord> procs = all.get(process);
12948 if (procs != null && procs.size() > 0) {
12949 proc = procs.valueAt(0);
12950 }
12951 }
12952
12953 if (proc == null || proc.thread == null) {
12954 throw new IllegalArgumentException("Unknown process: " + process);
12955 }
12956
12957 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12958 if (isSecure) {
12959 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12960 throw new SecurityException("Process not debuggable: " + proc);
12961 }
12962 }
12963
12964 proc.thread.dumpHeap(managed, path, fd);
12965 fd = null;
12966 return true;
12967 }
12968 } catch (RemoteException e) {
12969 throw new IllegalStateException("Process disappeared");
12970 } finally {
12971 if (fd != null) {
12972 try {
12973 fd.close();
12974 } catch (IOException e) {
12975 }
12976 }
12977 }
12978 }
12979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012980 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12981 public void monitor() {
12982 synchronized (this) { }
12983 }
12984}