blob: 92721fe988deff6595ddfd322e88b472b2624a91 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
79import android.net.Uri;
80import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080081import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070083import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080086import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.FileUtils;
88import android.os.Handler;
89import android.os.IBinder;
90import android.os.IPermissionController;
91import android.os.Looper;
92import android.os.Message;
93import android.os.Parcel;
94import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070096import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.RemoteException;
98import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070099import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.SystemClock;
101import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.Config;
104import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800105import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800106import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.PrintWriterPrinter;
108import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700109import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.view.Gravity;
111import android.view.LayoutInflater;
112import android.view.View;
113import android.view.WindowManager;
114import android.view.WindowManagerPolicy;
115
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700116import java.io.BufferedInputStream;
117import java.io.BufferedOutputStream;
118import java.io.DataInputStream;
119import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.File;
121import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700122import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200125import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800126import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.PrintWriter;
128import java.lang.IllegalStateException;
129import java.lang.ref.WeakReference;
130import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700131import java.util.Collections;
132import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.HashMap;
134import java.util.HashSet;
135import java.util.Iterator;
136import java.util.List;
137import java.util.Locale;
138import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700139import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700140import java.util.concurrent.atomic.AtomicBoolean;
141import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700143public final class ActivityManagerService extends ActivityManagerNative
144 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final String TAG = "ActivityManager";
146 static final boolean DEBUG = false;
147 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
148 static final boolean DEBUG_SWITCH = localLOGV || false;
149 static final boolean DEBUG_TASKS = localLOGV || false;
150 static final boolean DEBUG_PAUSE = localLOGV || false;
151 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
152 static final boolean DEBUG_TRANSITION = localLOGV || false;
153 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700154 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700156 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_VISBILITY = localLOGV || false;
158 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700159 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800160 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700162 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700163 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700164 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700165 static final boolean DEBUG_POWER = localLOGV || false;
166 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 static final boolean VALIDATE_TOKENS = false;
168 static final boolean SHOW_ACTIVITY_START_TIME = true;
169
170 // Control over CPU and battery monitoring.
171 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
172 static final boolean MONITOR_CPU_USAGE = true;
173 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
174 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
175 static final boolean MONITOR_THREAD_CPU_USAGE = false;
176
Dianne Hackborn1655be42009-05-08 14:29:01 -0700177 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700178 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 private static final String SYSTEM_SECURE = "ro.secure";
181
182 // This is the maximum number of application processes we would like
183 // to have running. Due to the asynchronous nature of things, we can
184 // temporarily go beyond this limit.
185 static final int MAX_PROCESSES = 2;
186
187 // Set to false to leave processes running indefinitely, relying on
188 // the kernel killing them as resources are required.
189 static final boolean ENFORCE_PROCESS_LIMIT = false;
190
191 // This is the maximum number of activities that we would like to have
192 // running at a given time.
193 static final int MAX_ACTIVITIES = 20;
194
195 // Maximum number of recent tasks that we can remember.
196 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700197
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700198 // Amount of time after a call to stopAppSwitches() during which we will
199 // prevent further untrusted switches from happening.
200 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
Dianne Hackborn287952c2010-09-22 22:34:31 -0700212 // The rate at which we check for apps using excessive power -- 15 mins.
213 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
214
215 // The minimum sample duration we will allow before deciding we have
216 // enough data on wake locks to start killing things.
217 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
218
219 // The minimum sample duration we will allow before deciding we have
220 // enough data on CPU usage to start killing things.
221 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // How long we allow a receiver to run before giving up on it.
224 static final int BROADCAST_TIMEOUT = 10*1000;
225
226 // How long we wait for a service to finish executing.
227 static final int SERVICE_TIMEOUT = 20*1000;
228
229 // How long a service needs to be running until restarting its process
230 // is no longer considered to be a relaunch of the service.
231 static final int SERVICE_RESTART_DURATION = 5*1000;
232
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700233 // How long a service needs to be running until it will start back at
234 // SERVICE_RESTART_DURATION after being killed.
235 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
236
237 // Multiplying factor to increase restart duration time by, for each time
238 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
239 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
240
241 // The minimum amount of time between restarting services that we allow.
242 // That is, when multiple services are restarting, we won't allow each
243 // to restart less than this amount of time from the last one.
244 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Maximum amount of time for there to be no activity on a service before
247 // we consider it non-essential and allow its process to go on the
248 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700249 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250
251 // How long we wait until we timeout on key dispatching.
252 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
253
254 // The minimum time we allow between crashes, for us to consider this
255 // application to be bad and stop and its services and reject broadcasts.
256 static final int MIN_CRASH_INTERVAL = 60*1000;
257
258 // How long we wait until we timeout on key dispatching during instrumentation.
259 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
260
261 // OOM adjustments for processes in various states:
262
263 // This is a process without anything currently running in it. Definitely
264 // the first to go! Value set in system/rootdir/init.rc on startup.
265 // This value is initalized in the constructor, careful when refering to
266 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269 // This is a process only hosting activities that are not visible,
270 // so it can be killed without any disruption. Value set in
271 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 static int HIDDEN_APP_MIN_ADJ;
274
The Android Open Source Project4df24232009-03-05 14:34:35 -0800275 // This is a process holding the home application -- we want to try
276 // avoiding killing it, even if it would normally be in the background,
277 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800279
Christopher Tate6fa95972009-06-05 18:43:55 -0700280 // This is a process currently hosting a backup operation. Killing it
281 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 // This is a process holding a secondary server -- killing it will not
285 // have much of an impact as far as the user is concerned. Value set in
286 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700289 // This is a process with a heavy-weight application. It is in the
290 // background, but we want to try to avoid killing it. Value set in
291 // system/rootdir/init.rc on startup.
292 static final int HEAVY_WEIGHT_APP_ADJ;
293
294 // This is a process only hosting components that are perceptible to the
295 // user, and we really want to avoid killing them, but they are not
296 // immediately visible. An example is background music playback. Value set in
297 // system/rootdir/init.rc on startup.
298 static final int PERCEPTIBLE_APP_ADJ;
299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 // This is a process only hosting activities that are visible to the
301 // user, so we'd prefer they don't disappear. Value set in
302 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800303 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304
305 // This is the process running the current foreground app. We'd really
306 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 // This is a process running a core server, such as telephony. Definitely
310 // don't want to kill it, but doing so is not completely fatal.
311 static final int CORE_SERVER_ADJ = -12;
312
313 // The system process runs at the default adjustment.
314 static final int SYSTEM_ADJ = -16;
315
316 // Memory pages are 4K.
317 static final int PAGE_SIZE = 4*1024;
318
319 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800320 static final int EMPTY_APP_MEM;
321 static final int HIDDEN_APP_MEM;
322 static final int HOME_APP_MEM;
323 static final int BACKUP_APP_MEM;
324 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700325 static final int HEAVY_WEIGHT_APP_MEM;
326 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327 static final int VISIBLE_APP_MEM;
328 static final int FOREGROUND_APP_MEM;
329
330 // The minimum number of hidden apps we want to be able to keep around,
331 // without empty apps being able to push them out of memory.
332 static final int MIN_HIDDEN_APPS = 2;
333
Dianne Hackborn8633e682010-04-22 16:03:41 -0700334 // The maximum number of hidden processes we will keep around before
335 // killing them; this is just a control to not let us go too crazy with
336 // keeping around processes on devices with large amounts of RAM.
337 static final int MAX_HIDDEN_APPS = 15;
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700340 // been idle for less than 15 seconds.
341 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342
343 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700344 // been idle for less than 120 seconds.
345 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700347 static int getIntProp(String name, boolean allowZero) {
348 String str = SystemProperties.get(name);
349 if (str == null) {
350 throw new IllegalArgumentException("Property not defined: " + name);
351 }
352 int val = Integer.valueOf(str);
353 if (val == 0 && !allowZero) {
354 throw new IllegalArgumentException("Property must not be zero: " + name);
355 }
356 return val;
357 }
358
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800359 static {
360 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700361 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
362 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
363 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
364 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
365 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
366 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
367 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
368 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
369 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
370 // These days we use the last empty slot for hidden apps as well.
371 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
372 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
373 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
374 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
375 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
376 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
377 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
378 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
379 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
380 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382
Dan Egnor42471dd2010-01-07 17:25:22 -0800383 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
385 static final String[] EMPTY_STRING_ARRAY = new String[0];
386
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700387 public ActivityStack mMainStack;
388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700390 * Description of a request to start a new activity, which has been held
391 * due to app switches being disabled.
392 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700393 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700394 ActivityRecord r;
395 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700396 Uri[] grantedUriPermissions;
397 int grantedMode;
398 boolean onlyIfNeeded;
399 }
400
401 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
402 = new ArrayList<PendingActivityLaunch>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * Activity we have told the window manager to have key focus.
435 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700436 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * List of intents that were used to start the most recent tasks.
439 */
440 final ArrayList<TaskRecord> mRecentTasks
441 = new ArrayList<TaskRecord>();
442
443 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 * All of the applications we currently have running organized by name.
445 * The keys are strings of the application package name (as
446 * returned by the package manager), and the keys are ApplicationRecord
447 * objects.
448 */
449 final ProcessMap<ProcessRecord> mProcessNames
450 = new ProcessMap<ProcessRecord>();
451
452 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700453 * The currently running heavy-weight process, if any.
454 */
455 ProcessRecord mHeavyWeightProcess = null;
456
457 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 * The last time that various processes have crashed.
459 */
460 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
461
462 /**
463 * Set of applications that we consider to be bad, and will reject
464 * incoming broadcasts from (which the user has no control over).
465 * Processes are added to this set when they have crashed twice within
466 * a minimum amount of time; they are removed from it when they are
467 * later restarted (hopefully due to some user action). The value is the
468 * time it was added to the list.
469 */
470 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
471
472 /**
473 * All of the processes we currently have running organized by pid.
474 * The keys are the pid running the application.
475 *
476 * <p>NOTE: This object is protected by its own lock, NOT the global
477 * activity manager lock!
478 */
479 final SparseArray<ProcessRecord> mPidsSelfLocked
480 = new SparseArray<ProcessRecord>();
481
482 /**
483 * All of the processes that have been forced to be foreground. The key
484 * is the pid of the caller who requested it (we hold a death
485 * link on it).
486 */
487 abstract class ForegroundToken implements IBinder.DeathRecipient {
488 int pid;
489 IBinder token;
490 }
491 final SparseArray<ForegroundToken> mForegroundProcesses
492 = new SparseArray<ForegroundToken>();
493
494 /**
495 * List of records for processes that someone had tried to start before the
496 * system was ready. We don't start them at that point, but ensure they
497 * are started by the time booting is complete.
498 */
499 final ArrayList<ProcessRecord> mProcessesOnHold
500 = new ArrayList<ProcessRecord>();
501
502 /**
503 * List of records for processes that we have started and are waiting
504 * for them to call back. This is really only needed when running in
505 * single processes mode, in which case we do not have a unique pid for
506 * each process.
507 */
508 final ArrayList<ProcessRecord> mStartingProcesses
509 = new ArrayList<ProcessRecord>();
510
511 /**
512 * List of persistent applications that are in the process
513 * of being started.
514 */
515 final ArrayList<ProcessRecord> mPersistentStartingProcesses
516 = new ArrayList<ProcessRecord>();
517
518 /**
519 * Processes that are being forcibly torn down.
520 */
521 final ArrayList<ProcessRecord> mRemovedProcesses
522 = new ArrayList<ProcessRecord>();
523
524 /**
525 * List of running applications, sorted by recent usage.
526 * The first entry in the list is the least recently used.
527 * It contains ApplicationRecord objects. This list does NOT include
528 * any persistent application records (since we never want to exit them).
529 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800530 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 = new ArrayList<ProcessRecord>();
532
533 /**
534 * List of processes that should gc as soon as things are idle.
535 */
536 final ArrayList<ProcessRecord> mProcessesToGc
537 = new ArrayList<ProcessRecord>();
538
539 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800540 * This is the process holding what we currently consider to be
541 * the "home" activity.
542 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700543 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800544
545 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 * Set of PendingResultRecord objects that are currently active.
547 */
548 final HashSet mPendingResultRecords = new HashSet();
549
550 /**
551 * Set of IntentSenderRecord objects that are currently active.
552 */
553 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
554 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
555
556 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700557 * Fingerprints (String.hashCode()) of stack traces that we've
558 * already logged DropBox entries for. Guarded by itself. If
559 * something (rogue user app) forces this over
560 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
561 */
562 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
563 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
564
565 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700566 * Strict Mode background batched logging state.
567 *
568 * The string buffer is guarded by itself, and its lock is also
569 * used to determine if another batched write is already
570 * in-flight.
571 */
572 private final StringBuilder mStrictModeBuffer = new StringBuilder();
573
574 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700575 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
576 */
577 private boolean mPendingBroadcastTimeoutMessage;
578
579 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 * Intent broadcast that we have tried to start, but are
581 * waiting for its application's process to be created. We only
582 * need one (instead of a list) because we always process broadcasts
583 * one at a time, so no others can be started while waiting for this
584 * one.
585 */
586 BroadcastRecord mPendingBroadcast = null;
587
588 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700589 * The receiver index that is pending, to restart the broadcast if needed.
590 */
591 int mPendingBroadcastRecvIndex;
592
593 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 * Keeps track of all IIntentReceivers that have been registered for
595 * broadcasts. Hash keys are the receiver IBinder, hash value is
596 * a ReceiverList.
597 */
598 final HashMap mRegisteredReceivers = new HashMap();
599
600 /**
601 * Resolver for broadcast intents to registered receivers.
602 * Holds BroadcastFilter (subclass of IntentFilter).
603 */
604 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
605 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
606 @Override
607 protected boolean allowFilterResult(
608 BroadcastFilter filter, List<BroadcastFilter> dest) {
609 IBinder target = filter.receiverList.receiver.asBinder();
610 for (int i=dest.size()-1; i>=0; i--) {
611 if (dest.get(i).receiverList.receiver.asBinder() == target) {
612 return false;
613 }
614 }
615 return true;
616 }
617 };
618
619 /**
620 * State of all active sticky broadcasts. Keys are the action of the
621 * sticky Intent, values are an ArrayList of all broadcasted intents with
622 * that action (which should usually be one).
623 */
624 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
625 new HashMap<String, ArrayList<Intent>>();
626
627 /**
628 * All currently running services.
629 */
630 final HashMap<ComponentName, ServiceRecord> mServices =
631 new HashMap<ComponentName, ServiceRecord>();
632
633 /**
634 * All currently running services indexed by the Intent used to start them.
635 */
636 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
637 new HashMap<Intent.FilterComparison, ServiceRecord>();
638
639 /**
640 * All currently bound service connections. Keys are the IBinder of
641 * the client's IServiceConnection.
642 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700643 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
644 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645
646 /**
647 * List of services that we have been asked to start,
648 * but haven't yet been able to. It is used to hold start requests
649 * while waiting for their corresponding application thread to get
650 * going.
651 */
652 final ArrayList<ServiceRecord> mPendingServices
653 = new ArrayList<ServiceRecord>();
654
655 /**
656 * List of services that are scheduled to restart following a crash.
657 */
658 final ArrayList<ServiceRecord> mRestartingServices
659 = new ArrayList<ServiceRecord>();
660
661 /**
662 * List of services that are in the process of being stopped.
663 */
664 final ArrayList<ServiceRecord> mStoppingServices
665 = new ArrayList<ServiceRecord>();
666
667 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700668 * Backup/restore process management
669 */
670 String mBackupAppName = null;
671 BackupRecord mBackupTarget = null;
672
673 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 * List of PendingThumbnailsRecord objects of clients who are still
675 * waiting to receive all of the thumbnails for a task.
676 */
677 final ArrayList mPendingThumbnails = new ArrayList();
678
679 /**
680 * List of HistoryRecord objects that have been finished and must
681 * still report back to a pending thumbnail receiver.
682 */
683 final ArrayList mCancelledThumbnails = new ArrayList();
684
685 /**
686 * All of the currently running global content providers. Keys are a
687 * string containing the provider name and values are a
688 * ContentProviderRecord object containing the data about it. Note
689 * that a single provider may be published under multiple names, so
690 * there may be multiple entries here for a single one in mProvidersByClass.
691 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700692 final HashMap<String, ContentProviderRecord> mProvidersByName
693 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694
695 /**
696 * All of the currently running global content providers. Keys are a
697 * string containing the provider's implementation class and values are a
698 * ContentProviderRecord object containing the data about it.
699 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700700 final HashMap<String, ContentProviderRecord> mProvidersByClass
701 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702
703 /**
704 * List of content providers who have clients waiting for them. The
705 * application is currently being launched and the provider will be
706 * removed from this list once it is published.
707 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700708 final ArrayList<ContentProviderRecord> mLaunchingProviders
709 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 /**
712 * Global set of specific Uri permissions that have been granted.
713 */
714 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
715 = new SparseArray<HashMap<Uri, UriPermission>>();
716
717 /**
718 * Thread-local storage used to carry caller permissions over through
719 * indirect content-provider access.
720 * @see #ActivityManagerService.openContentUri()
721 */
722 private class Identity {
723 public int pid;
724 public int uid;
725
726 Identity(int _pid, int _uid) {
727 pid = _pid;
728 uid = _uid;
729 }
730 }
731 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
732
733 /**
734 * All information we have collected about the runtime performance of
735 * any user id that can impact battery performance.
736 */
737 final BatteryStatsService mBatteryStatsService;
738
739 /**
740 * information about component usage
741 */
742 final UsageStatsService mUsageStatsService;
743
744 /**
745 * Current configuration information. HistoryRecord objects are given
746 * a reference to this object to indicate which configuration they are
747 * currently running in, so this object must be kept immutable.
748 */
749 Configuration mConfiguration = new Configuration();
750
751 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800752 * Current sequencing integer of the configuration, for skipping old
753 * configurations.
754 */
755 int mConfigurationSeq = 0;
756
757 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700758 * Hardware-reported OpenGLES version.
759 */
760 final int GL_ES_VERSION;
761
762 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 * List of initialization arguments to pass to all processes when binding applications to them.
764 * For example, references to the commonly used services.
765 */
766 HashMap<String, IBinder> mAppBindArgs;
767
768 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700769 * Temporary to avoid allocations. Protected by main lock.
770 */
771 final StringBuilder mStringBuilder = new StringBuilder(256);
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * Used to control how we initialize the service.
775 */
776 boolean mStartRunning = false;
777 ComponentName mTopComponent;
778 String mTopAction;
779 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700780 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 boolean mSystemReady = false;
782 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700783 boolean mWaitingUpdate = false;
784 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700785 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700786 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 Context mContext;
789
790 int mFactoryTest;
791
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700792 boolean mCheckedForSetup;
793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700795 * The time at which we will allow normal application switches again,
796 * after a call to {@link #stopAppSwitches()}.
797 */
798 long mAppSwitchesAllowedTime;
799
800 /**
801 * This is set to true after the first switch after mAppSwitchesAllowedTime
802 * is set; any switches after that will clear the time.
803 */
804 boolean mDidAppSwitch;
805
806 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700807 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700808 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 long mLastPowerCheckRealtime;
810
811 /**
812 * Last time (in uptime) at which we checked for power usage.
813 */
814 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700815
816 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 * Set while we are wanting to sleep, to prevent any
818 * activities from being started/resumed.
819 */
820 boolean mSleeping = false;
821
822 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700823 * Set if we are shutting down the system, similar to sleeping.
824 */
825 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826
827 /**
828 * Task identifier that activities are currently being started
829 * in. Incremented each time a new task is created.
830 * todo: Replace this with a TokenSpace class that generates non-repeating
831 * integers that won't wrap.
832 */
833 int mCurTask = 1;
834
835 /**
836 * Current sequence id for oom_adj computation traversal.
837 */
838 int mAdjSeq = 0;
839
840 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700841 * Current sequence id for process LRU updating.
842 */
843 int mLruSeq = 0;
844
845 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
847 * is set, indicating the user wants processes started in such a way
848 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
849 * running in each process (thus no pre-initialized process, etc).
850 */
851 boolean mSimpleProcessManagement = false;
852
853 /**
854 * System monitoring: number of processes that died since the last
855 * N procs were started.
856 */
857 int[] mProcDeaths = new int[20];
858
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700859 /**
860 * This is set if we had to do a delayed dexopt of an app before launching
861 * it, to increasing the ANR timeouts in that case.
862 */
863 boolean mDidDexOpt;
864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 String mDebugApp = null;
866 boolean mWaitForDebugger = false;
867 boolean mDebugTransient = false;
868 String mOrigDebugApp = null;
869 boolean mOrigWaitForDebugger = false;
870 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700871 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 final RemoteCallbackList<IActivityWatcher> mWatchers
874 = new RemoteCallbackList<IActivityWatcher>();
875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 /**
877 * Callback of last caller to {@link #requestPss}.
878 */
879 Runnable mRequestPssCallback;
880
881 /**
882 * Remaining processes for which we are waiting results from the last
883 * call to {@link #requestPss}.
884 */
885 final ArrayList<ProcessRecord> mRequestPssList
886 = new ArrayList<ProcessRecord>();
887
888 /**
889 * Runtime statistics collection thread. This object's lock is used to
890 * protect all related state.
891 */
892 final Thread mProcessStatsThread;
893
894 /**
895 * Used to collect process stats when showing not responding dialog.
896 * Protected by mProcessStatsThread.
897 */
898 final ProcessStats mProcessStats = new ProcessStats(
899 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700900 final AtomicLong mLastCpuTime = new AtomicLong(0);
901 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 long mLastWriteTime = 0;
904
905 /**
906 * Set to true after the system has finished booting.
907 */
908 boolean mBooted = false;
909
910 int mProcessLimit = 0;
911
912 WindowManagerService mWindowManager;
913
914 static ActivityManagerService mSelf;
915 static ActivityThread mSystemThread;
916
917 private final class AppDeathRecipient implements IBinder.DeathRecipient {
918 final ProcessRecord mApp;
919 final int mPid;
920 final IApplicationThread mAppThread;
921
922 AppDeathRecipient(ProcessRecord app, int pid,
923 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800924 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 TAG, "New death recipient " + this
926 + " for thread " + thread.asBinder());
927 mApp = app;
928 mPid = pid;
929 mAppThread = thread;
930 }
931
932 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800933 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 TAG, "Death received in " + this
935 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 synchronized(ActivityManagerService.this) {
937 appDiedLocked(mApp, mPid, mAppThread);
938 }
939 }
940 }
941
942 static final int SHOW_ERROR_MSG = 1;
943 static final int SHOW_NOT_RESPONDING_MSG = 2;
944 static final int SHOW_FACTORY_ERROR_MSG = 3;
945 static final int UPDATE_CONFIGURATION_MSG = 4;
946 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
947 static final int WAIT_FOR_DEBUGGER_MSG = 6;
948 static final int BROADCAST_INTENT_MSG = 7;
949 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 static final int SERVICE_TIMEOUT_MSG = 12;
951 static final int UPDATE_TIME_ZONE = 13;
952 static final int SHOW_UID_ERROR_MSG = 14;
953 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700955 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700956 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800957 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700958 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
959 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700960 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700961 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962
963 AlertDialog mUidAlert;
964
965 final Handler mHandler = new Handler() {
966 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800967 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 //}
969
970 public void handleMessage(Message msg) {
971 switch (msg.what) {
972 case SHOW_ERROR_MSG: {
973 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 synchronized (ActivityManagerService.this) {
975 ProcessRecord proc = (ProcessRecord)data.get("app");
976 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 return;
979 }
980 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700981 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800982 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 d.show();
984 proc.crashDialog = d;
985 } else {
986 // The device is asleep, so just pretend that the user
987 // saw a crash dialog and hit "force quit".
988 res.set(0);
989 }
990 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700991
992 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } break;
994 case SHOW_NOT_RESPONDING_MSG: {
995 synchronized (ActivityManagerService.this) {
996 HashMap data = (HashMap) msg.obj;
997 ProcessRecord proc = (ProcessRecord)data.get("app");
998 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 return;
1001 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001002
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001003 Intent intent = new Intent("android.intent.action.ANR");
1004 if (!mProcessesReady) {
1005 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1006 }
1007 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001008 null, null, 0, null, null, null,
1009 false, false, MY_PID, Process.SYSTEM_UID);
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001012 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 d.show();
1014 proc.anrDialog = d;
1015 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001016
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001019 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1020 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1021 synchronized (ActivityManagerService.this) {
1022 ProcessRecord proc = (ProcessRecord) data.get("app");
1023 if (proc == null) {
1024 Slog.e(TAG, "App not found when showing strict mode dialog.");
1025 break;
1026 }
1027 if (proc.crashDialog != null) {
1028 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1029 return;
1030 }
1031 AppErrorResult res = (AppErrorResult) data.get("result");
1032 if (!mSleeping && !mShuttingDown) {
1033 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1034 d.show();
1035 proc.crashDialog = d;
1036 } else {
1037 // The device is asleep, so just pretend that the user
1038 // saw a crash dialog and hit "force quit".
1039 res.set(0);
1040 }
1041 }
1042 ensureBootCompleted();
1043 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 case SHOW_FACTORY_ERROR_MSG: {
1045 Dialog d = new FactoryErrorDialog(
1046 mContext, msg.getData().getCharSequence("msg"));
1047 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001048 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 } break;
1050 case UPDATE_CONFIGURATION_MSG: {
1051 final ContentResolver resolver = mContext.getContentResolver();
1052 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1053 } break;
1054 case GC_BACKGROUND_PROCESSES_MSG: {
1055 synchronized (ActivityManagerService.this) {
1056 performAppGcsIfAppropriateLocked();
1057 }
1058 } break;
1059 case WAIT_FOR_DEBUGGER_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 ProcessRecord app = (ProcessRecord)msg.obj;
1062 if (msg.arg1 != 0) {
1063 if (!app.waitedForDebugger) {
1064 Dialog d = new AppWaitingForDebuggerDialog(
1065 ActivityManagerService.this,
1066 mContext, app);
1067 app.waitDialog = d;
1068 app.waitedForDebugger = true;
1069 d.show();
1070 }
1071 } else {
1072 if (app.waitDialog != null) {
1073 app.waitDialog.dismiss();
1074 app.waitDialog = null;
1075 }
1076 }
1077 }
1078 } break;
1079 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 TAG, "Received BROADCAST_INTENT_MSG");
1082 processNextBroadcast(true);
1083 } break;
1084 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001085 synchronized (ActivityManagerService.this) {
1086 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001090 if (mDidDexOpt) {
1091 mDidDexOpt = false;
1092 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1093 nmsg.obj = msg.obj;
1094 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1095 return;
1096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 serviceTimeout((ProcessRecord)msg.obj);
1098 } break;
1099 case UPDATE_TIME_ZONE: {
1100 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001101 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1102 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (r.thread != null) {
1104 try {
1105 r.thread.updateTimeZone();
1106 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 }
1109 }
1110 }
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 case SHOW_UID_ERROR_MSG: {
1114 // XXX This is a temporary dialog, no need to localize.
1115 AlertDialog d = new BaseErrorDialog(mContext);
1116 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1117 d.setCancelable(false);
1118 d.setTitle("System UIDs Inconsistent");
1119 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 +02001120 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1122 mUidAlert = d;
1123 d.show();
1124 } break;
1125 case IM_FEELING_LUCKY_MSG: {
1126 if (mUidAlert != null) {
1127 mUidAlert.dismiss();
1128 mUidAlert = null;
1129 }
1130 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001132 if (mDidDexOpt) {
1133 mDidDexOpt = false;
1134 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1135 nmsg.obj = msg.obj;
1136 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1137 return;
1138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 ProcessRecord app = (ProcessRecord)msg.obj;
1140 synchronized (ActivityManagerService.this) {
1141 processStartTimedOutLocked(app);
1142 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001143 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001144 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1145 synchronized (ActivityManagerService.this) {
1146 doPendingActivityLaunchesLocked(true);
1147 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001148 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001149 case KILL_APPLICATION_MSG: {
1150 synchronized (ActivityManagerService.this) {
1151 int uid = msg.arg1;
1152 boolean restart = (msg.arg2 == 1);
1153 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001154 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001155 }
1156 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001157 case FINALIZE_PENDING_INTENT_MSG: {
1158 ((PendingIntentRecord)msg.obj).completeFinalize();
1159 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001160 case POST_HEAVY_NOTIFICATION_MSG: {
1161 INotificationManager inm = NotificationManager.getService();
1162 if (inm == null) {
1163 return;
1164 }
1165
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001166 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001167 ProcessRecord process = root.app;
1168 if (process == null) {
1169 return;
1170 }
1171
1172 try {
1173 Context context = mContext.createPackageContext(process.info.packageName, 0);
1174 String text = mContext.getString(R.string.heavy_weight_notification,
1175 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1176 Notification notification = new Notification();
1177 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1178 notification.when = 0;
1179 notification.flags = Notification.FLAG_ONGOING_EVENT;
1180 notification.tickerText = text;
1181 notification.defaults = 0; // please be quiet
1182 notification.sound = null;
1183 notification.vibrate = null;
1184 notification.setLatestEventInfo(context, text,
1185 mContext.getText(R.string.heavy_weight_notification_detail),
1186 PendingIntent.getActivity(mContext, 0, root.intent,
1187 PendingIntent.FLAG_CANCEL_CURRENT));
1188
1189 try {
1190 int[] outId = new int[1];
1191 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1192 notification, outId);
1193 } catch (RuntimeException e) {
1194 Slog.w(ActivityManagerService.TAG,
1195 "Error showing notification for heavy-weight app", e);
1196 } catch (RemoteException e) {
1197 }
1198 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001199 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001200 }
1201 } break;
1202 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1203 INotificationManager inm = NotificationManager.getService();
1204 if (inm == null) {
1205 return;
1206 }
1207 try {
1208 inm.cancelNotification("android",
1209 R.string.heavy_weight_notification);
1210 } catch (RuntimeException e) {
1211 Slog.w(ActivityManagerService.TAG,
1212 "Error canceling notification for service", e);
1213 } catch (RemoteException e) {
1214 }
1215 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001216 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1217 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001218 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001219 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001220 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1221 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001222 }
1223 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 }
1226 };
1227
1228 public static void setSystemProcess() {
1229 try {
1230 ActivityManagerService m = mSelf;
1231
1232 ServiceManager.addService("activity", m);
1233 ServiceManager.addService("meminfo", new MemBinder(m));
1234 if (MONITOR_CPU_USAGE) {
1235 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 ServiceManager.addService("permission", new PermissionController(m));
1238
1239 ApplicationInfo info =
1240 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001241 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001242 mSystemThread.installSystemApplicationInfo(info);
1243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 synchronized (mSelf) {
1245 ProcessRecord app = mSelf.newProcessRecordLocked(
1246 mSystemThread.getApplicationThread(), info,
1247 info.processName);
1248 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001249 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 app.maxAdj = SYSTEM_ADJ;
1251 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1252 synchronized (mSelf.mPidsSelfLocked) {
1253 mSelf.mPidsSelfLocked.put(app.pid, app);
1254 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001255 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 }
1257 } catch (PackageManager.NameNotFoundException e) {
1258 throw new RuntimeException(
1259 "Unable to find android system package", e);
1260 }
1261 }
1262
1263 public void setWindowManager(WindowManagerService wm) {
1264 mWindowManager = wm;
1265 }
1266
1267 public static final Context main(int factoryTest) {
1268 AThread thr = new AThread();
1269 thr.start();
1270
1271 synchronized (thr) {
1272 while (thr.mService == null) {
1273 try {
1274 thr.wait();
1275 } catch (InterruptedException e) {
1276 }
1277 }
1278 }
1279
1280 ActivityManagerService m = thr.mService;
1281 mSelf = m;
1282 ActivityThread at = ActivityThread.systemMain();
1283 mSystemThread = at;
1284 Context context = at.getSystemContext();
1285 m.mContext = context;
1286 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001287 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288
1289 m.mBatteryStatsService.publish(context);
1290 m.mUsageStatsService.publish(context);
1291
1292 synchronized (thr) {
1293 thr.mReady = true;
1294 thr.notifyAll();
1295 }
1296
1297 m.startRunning(null, null, null, null);
1298
1299 return context;
1300 }
1301
1302 public static ActivityManagerService self() {
1303 return mSelf;
1304 }
1305
1306 static class AThread extends Thread {
1307 ActivityManagerService mService;
1308 boolean mReady = false;
1309
1310 public AThread() {
1311 super("ActivityManager");
1312 }
1313
1314 public void run() {
1315 Looper.prepare();
1316
1317 android.os.Process.setThreadPriority(
1318 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001319 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320
1321 ActivityManagerService m = new ActivityManagerService();
1322
1323 synchronized (this) {
1324 mService = m;
1325 notifyAll();
1326 }
1327
1328 synchronized (this) {
1329 while (!mReady) {
1330 try {
1331 wait();
1332 } catch (InterruptedException e) {
1333 }
1334 }
1335 }
1336
1337 Looper.loop();
1338 }
1339 }
1340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 static class MemBinder extends Binder {
1342 ActivityManagerService mActivityManagerService;
1343 MemBinder(ActivityManagerService activityManagerService) {
1344 mActivityManagerService = activityManagerService;
1345 }
1346
1347 @Override
1348 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1349 ActivityManagerService service = mActivityManagerService;
1350 ArrayList<ProcessRecord> procs;
1351 synchronized (mActivityManagerService) {
1352 if (args != null && args.length > 0
1353 && args[0].charAt(0) != '-') {
1354 procs = new ArrayList<ProcessRecord>();
1355 int pid = -1;
1356 try {
1357 pid = Integer.parseInt(args[0]);
1358 } catch (NumberFormatException e) {
1359
1360 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001361 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1362 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 if (proc.pid == pid) {
1364 procs.add(proc);
1365 } else if (proc.processName.equals(args[0])) {
1366 procs.add(proc);
1367 }
1368 }
1369 if (procs.size() <= 0) {
1370 pw.println("No process found for: " + args[0]);
1371 return;
1372 }
1373 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001374 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376 }
1377 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1378 }
1379 }
1380
1381 static class CpuBinder extends Binder {
1382 ActivityManagerService mActivityManagerService;
1383 CpuBinder(ActivityManagerService activityManagerService) {
1384 mActivityManagerService = activityManagerService;
1385 }
1386
1387 @Override
1388 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1389 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001390 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1391 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1392 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 }
1395 }
1396
1397 private ActivityManagerService() {
1398 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1399 if (v != null && Integer.getInteger(v) != 0) {
1400 mSimpleProcessManagement = true;
1401 }
1402 v = System.getenv("ANDROID_DEBUG_APP");
1403 if (v != null) {
1404 mSimpleProcessManagement = true;
1405 }
1406
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 File dataDir = Environment.getDataDirectory();
1410 File systemDir = new File(dataDir, "system");
1411 systemDir.mkdirs();
1412 mBatteryStatsService = new BatteryStatsService(new File(
1413 systemDir, "batterystats.bin").toString());
1414 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001415 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001416 mOnBattery = DEBUG_POWER ? true
1417 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001418 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001420 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001421 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422
Jack Palevichb90d28c2009-07-22 15:35:24 -07001423 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1424 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1425
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001426 mConfiguration.setToDefaults();
1427 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 mProcessStats.init();
1429
1430 // Add ourself to the Watchdog monitors.
1431 Watchdog.getInstance().addMonitor(this);
1432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 mProcessStatsThread = new Thread("ProcessStats") {
1434 public void run() {
1435 while (true) {
1436 try {
1437 try {
1438 synchronized(this) {
1439 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001440 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001442 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 // + ", write delay=" + nextWriteDelay);
1444 if (nextWriteDelay < nextCpuDelay) {
1445 nextCpuDelay = nextWriteDelay;
1446 }
1447 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001448 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 this.wait(nextCpuDelay);
1450 }
1451 }
1452 } catch (InterruptedException e) {
1453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 updateCpuStatsNow();
1455 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001456 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 }
1458 }
1459 }
1460 };
1461 mProcessStatsThread.start();
1462 }
1463
1464 @Override
1465 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1466 throws RemoteException {
1467 try {
1468 return super.onTransact(code, data, reply, flags);
1469 } catch (RuntimeException e) {
1470 // The activity manager only throws security exceptions, so let's
1471 // log all others.
1472 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001473 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 }
1475 throw e;
1476 }
1477 }
1478
1479 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001480 final long now = SystemClock.uptimeMillis();
1481 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1482 return;
1483 }
1484 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1485 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 mProcessStatsThread.notify();
1487 }
1488 }
1489 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 void updateCpuStatsNow() {
1492 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001493 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 final long now = SystemClock.uptimeMillis();
1495 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001498 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1499 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 haveNewCpuStats = true;
1501 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001502 //Slog.i(TAG, mProcessStats.printCurrentState());
1503 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 // + mProcessStats.getTotalCpuPercent() + "%");
1505
Joe Onorato8a9b2202010-02-26 18:56:32 -08001506 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 if ("true".equals(SystemProperties.get("events.cpu"))) {
1508 int user = mProcessStats.getLastUserTime();
1509 int system = mProcessStats.getLastSystemTime();
1510 int iowait = mProcessStats.getLastIoWaitTime();
1511 int irq = mProcessStats.getLastIrqTime();
1512 int softIrq = mProcessStats.getLastSoftIrqTime();
1513 int idle = mProcessStats.getLastIdleTime();
1514
1515 int total = user + system + iowait + irq + softIrq + idle;
1516 if (total == 0) total = 1;
1517
Doug Zongker2bec3d42009-12-04 12:52:44 -08001518 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 ((user+system+iowait+irq+softIrq) * 100) / total,
1520 (user * 100) / total,
1521 (system * 100) / total,
1522 (iowait * 100) / total,
1523 (irq * 100) / total,
1524 (softIrq * 100) / total);
1525 }
1526 }
1527
Amith Yamasanie43530a2009-08-21 13:11:37 -07001528 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001529 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 synchronized(mPidsSelfLocked) {
1532 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001533 if (mOnBattery) {
1534 int perc = bstats.startAddingCpuLocked();
1535 int totalUTime = 0;
1536 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001537 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001539 ProcessStats.Stats st = mProcessStats.getStats(i);
1540 if (!st.working) {
1541 continue;
1542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001544 int otherUTime = (st.rel_utime*perc)/100;
1545 int otherSTime = (st.rel_stime*perc)/100;
1546 totalUTime += otherUTime;
1547 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (pr != null) {
1549 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001550 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1551 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001552 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001553 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001554 } else {
1555 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001556 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001557 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001558 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1559 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001560 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 }
1563 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001564 bstats.finishAddingCpuLocked(perc, totalUTime,
1565 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 }
1567 }
1568 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1571 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001572 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 }
1574 }
1575 }
1576 }
1577
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001578 @Override
1579 public void batteryNeedsCpuUpdate() {
1580 updateCpuStatsNow();
1581 }
1582
1583 @Override
1584 public void batteryPowerChanged(boolean onBattery) {
1585 // When plugging in, update the CPU stats first before changing
1586 // the plug state.
1587 updateCpuStatsNow();
1588 synchronized (this) {
1589 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001590 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001591 }
1592 }
1593 }
1594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 /**
1596 * Initialize the application bind args. These are passed to each
1597 * process when the bindApplication() IPC is sent to the process. They're
1598 * lazily setup to make sure the services are running when they're asked for.
1599 */
1600 private HashMap<String, IBinder> getCommonServicesLocked() {
1601 if (mAppBindArgs == null) {
1602 mAppBindArgs = new HashMap<String, IBinder>();
1603
1604 // Setup the application init args
1605 mAppBindArgs.put("package", ServiceManager.getService("package"));
1606 mAppBindArgs.put("window", ServiceManager.getService("window"));
1607 mAppBindArgs.put(Context.ALARM_SERVICE,
1608 ServiceManager.getService(Context.ALARM_SERVICE));
1609 }
1610 return mAppBindArgs;
1611 }
1612
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001613 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 if (mFocusedActivity != r) {
1615 mFocusedActivity = r;
1616 mWindowManager.setFocusedApp(r, true);
1617 }
1618 }
1619
Dianne Hackborn906497c2010-05-10 15:57:38 -07001620 private final void updateLruProcessInternalLocked(ProcessRecord app,
1621 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001623 int lrui = mLruProcesses.indexOf(app);
1624 if (lrui >= 0) mLruProcesses.remove(lrui);
1625
1626 int i = mLruProcesses.size()-1;
1627 int skipTop = 0;
1628
Dianne Hackborn906497c2010-05-10 15:57:38 -07001629 app.lruSeq = mLruSeq;
1630
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001631 // compute the new weight for this process.
1632 if (updateActivityTime) {
1633 app.lastActivityTime = SystemClock.uptimeMillis();
1634 }
1635 if (app.activities.size() > 0) {
1636 // If this process has activities, we more strongly want to keep
1637 // it around.
1638 app.lruWeight = app.lastActivityTime;
1639 } else if (app.pubProviders.size() > 0) {
1640 // If this process contains content providers, we want to keep
1641 // it a little more strongly.
1642 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1643 // Also don't let it kick out the first few "real" hidden processes.
1644 skipTop = MIN_HIDDEN_APPS;
1645 } else {
1646 // If this process doesn't have activities, we less strongly
1647 // want to keep it around, and generally want to avoid getting
1648 // in front of any very recently used activities.
1649 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1650 // Also don't let it kick out the first few "real" hidden processes.
1651 skipTop = MIN_HIDDEN_APPS;
1652 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001653
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001654 while (i >= 0) {
1655 ProcessRecord p = mLruProcesses.get(i);
1656 // If this app shouldn't be in front of the first N background
1657 // apps, then skip over that many that are currently hidden.
1658 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1659 skipTop--;
1660 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001661 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001662 mLruProcesses.add(i+1, app);
1663 break;
1664 }
1665 i--;
1666 }
1667 if (i < 0) {
1668 mLruProcesses.add(0, app);
1669 }
1670
Dianne Hackborn906497c2010-05-10 15:57:38 -07001671 // If the app is currently using a content provider or service,
1672 // bump those processes as well.
1673 if (app.connections.size() > 0) {
1674 for (ConnectionRecord cr : app.connections) {
1675 if (cr.binding != null && cr.binding.service != null
1676 && cr.binding.service.app != null
1677 && cr.binding.service.app.lruSeq != mLruSeq) {
1678 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1679 updateActivityTime, i+1);
1680 }
1681 }
1682 }
1683 if (app.conProviders.size() > 0) {
1684 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1685 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1686 updateLruProcessInternalLocked(cpr.app, oomAdj,
1687 updateActivityTime, i+1);
1688 }
1689 }
1690 }
1691
Joe Onorato8a9b2202010-02-26 18:56:32 -08001692 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 if (oomAdj) {
1694 updateOomAdjLocked();
1695 }
1696 }
1697
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001698 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001699 boolean oomAdj, boolean updateActivityTime) {
1700 mLruSeq++;
1701 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1702 }
1703
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001704 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 String processName, int uid) {
1706 if (uid == Process.SYSTEM_UID) {
1707 // The system gets to run in any process. If there are multiple
1708 // processes with the same uid, just pick the first (this
1709 // should never happen).
1710 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1711 processName);
1712 return procs != null ? procs.valueAt(0) : null;
1713 }
1714 ProcessRecord proc = mProcessNames.get(processName, uid);
1715 return proc;
1716 }
1717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001718 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001719 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001720 try {
1721 if (pm.performDexOpt(packageName)) {
1722 mDidDexOpt = true;
1723 }
1724 } catch (RemoteException e) {
1725 }
1726 }
1727
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001728 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 int transit = mWindowManager.getPendingAppTransition();
1730 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1731 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1732 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1733 }
1734
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001735 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001737 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1739 // We don't have to do anything more if:
1740 // (1) There is an existing application record; and
1741 // (2) The caller doesn't think it is dead, OR there is no thread
1742 // object attached to it so we know it couldn't have crashed; and
1743 // (3) There is a pid assigned to it, so it is either starting or
1744 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001745 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 + " app=" + app + " knownToBeDead=" + knownToBeDead
1747 + " thread=" + (app != null ? app.thread : null)
1748 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001749 if (app != null && app.pid > 0) {
1750 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001751 // We already have the app running, or are waiting for it to
1752 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001753 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001754 return app;
1755 } else {
1756 // An application record is attached to a previous process,
1757 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001758 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001759 handleAppDiedLocked(app, true);
1760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 String hostingNameStr = hostingName != null
1764 ? hostingName.flattenToShortString() : null;
1765
1766 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1767 // If we are in the background, then check to see if this process
1768 // is bad. If so, we will just silently fail.
1769 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001770 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1771 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 return null;
1773 }
1774 } else {
1775 // When the user is explicitly starting a process, then clear its
1776 // crash count so that we won't make it bad until they see at
1777 // least one crash dialog again, and make the process good again
1778 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001779 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1780 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 mProcessCrashTimes.remove(info.processName, info.uid);
1782 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001783 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 info.processName);
1785 mBadProcesses.remove(info.processName, info.uid);
1786 if (app != null) {
1787 app.bad = false;
1788 }
1789 }
1790 }
1791
1792 if (app == null) {
1793 app = newProcessRecordLocked(null, info, processName);
1794 mProcessNames.put(processName, info.uid, app);
1795 } else {
1796 // If this is a new package in the process, add the package to the list
1797 app.addPackage(info.packageName);
1798 }
1799
1800 // If the system is not ready yet, then hold off on starting this
1801 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001802 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001803 && !isAllowedWhileBooting(info)
1804 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 if (!mProcessesOnHold.contains(app)) {
1806 mProcessesOnHold.add(app);
1807 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001808 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 return app;
1810 }
1811
1812 startProcessLocked(app, hostingType, hostingNameStr);
1813 return (app.pid != 0) ? app : null;
1814 }
1815
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001816 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1817 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1818 }
1819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 private final void startProcessLocked(ProcessRecord app,
1821 String hostingType, String hostingNameStr) {
1822 if (app.pid > 0 && app.pid != MY_PID) {
1823 synchronized (mPidsSelfLocked) {
1824 mPidsSelfLocked.remove(app.pid);
1825 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1826 }
1827 app.pid = 0;
1828 }
1829
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001830 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1831 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 mProcessesOnHold.remove(app);
1833
1834 updateCpuStats();
1835
1836 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1837 mProcDeaths[0] = 0;
1838
1839 try {
1840 int uid = app.info.uid;
1841 int[] gids = null;
1842 try {
1843 gids = mContext.getPackageManager().getPackageGids(
1844 app.info.packageName);
1845 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001846 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 }
1848 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1849 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1850 && mTopComponent != null
1851 && app.processName.equals(mTopComponent.getPackageName())) {
1852 uid = 0;
1853 }
1854 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1855 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1856 uid = 0;
1857 }
1858 }
1859 int debugFlags = 0;
1860 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1861 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1862 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001863 // Run the app in safe mode if its manifest requests so or the
1864 // system is booted in safe mode.
1865 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1866 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001867 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1870 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1871 }
1872 if ("1".equals(SystemProperties.get("debug.assert"))) {
1873 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1874 }
1875 int pid = Process.start("android.app.ActivityThread",
1876 mSimpleProcessManagement ? app.processName : null, uid, uid,
1877 gids, debugFlags, null);
1878 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1879 synchronized (bs) {
1880 if (bs.isOnBattery()) {
1881 app.batteryStats.incStartsLocked();
1882 }
1883 }
1884
Doug Zongker2bec3d42009-12-04 12:52:44 -08001885 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 app.processName, hostingType,
1887 hostingNameStr != null ? hostingNameStr : "");
1888
1889 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001890 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 }
1892
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001893 StringBuilder buf = mStringBuilder;
1894 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 buf.append("Start proc ");
1896 buf.append(app.processName);
1897 buf.append(" for ");
1898 buf.append(hostingType);
1899 if (hostingNameStr != null) {
1900 buf.append(" ");
1901 buf.append(hostingNameStr);
1902 }
1903 buf.append(": pid=");
1904 buf.append(pid);
1905 buf.append(" uid=");
1906 buf.append(uid);
1907 buf.append(" gids={");
1908 if (gids != null) {
1909 for (int gi=0; gi<gids.length; gi++) {
1910 if (gi != 0) buf.append(", ");
1911 buf.append(gids[gi]);
1912
1913 }
1914 }
1915 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001916 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if (pid == 0 || pid == MY_PID) {
1918 // Processes are being emulated with threads.
1919 app.pid = MY_PID;
1920 app.removed = false;
1921 mStartingProcesses.add(app);
1922 } else if (pid > 0) {
1923 app.pid = pid;
1924 app.removed = false;
1925 synchronized (mPidsSelfLocked) {
1926 this.mPidsSelfLocked.put(pid, app);
1927 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1928 msg.obj = app;
1929 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1930 }
1931 } else {
1932 app.pid = 0;
1933 RuntimeException e = new RuntimeException(
1934 "Failure starting process " + app.processName
1935 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001936 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 }
1938 } catch (RuntimeException e) {
1939 // XXX do better error recovery.
1940 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001941 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 }
1943 }
1944
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001945 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 if (resumed) {
1947 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1948 } else {
1949 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1950 }
1951 }
1952
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001953 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001954 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1955 && mTopAction == null) {
1956 // We are running in factory test mode, but unable to find
1957 // the factory test app, so just sit around displaying the
1958 // error message and don't try to start anything.
1959 return false;
1960 }
1961 Intent intent = new Intent(
1962 mTopAction,
1963 mTopData != null ? Uri.parse(mTopData) : null);
1964 intent.setComponent(mTopComponent);
1965 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1966 intent.addCategory(Intent.CATEGORY_HOME);
1967 }
1968 ActivityInfo aInfo =
1969 intent.resolveActivityInfo(mContext.getPackageManager(),
1970 STOCK_PM_FLAGS);
1971 if (aInfo != null) {
1972 intent.setComponent(new ComponentName(
1973 aInfo.applicationInfo.packageName, aInfo.name));
1974 // Don't do this if the home app is currently being
1975 // instrumented.
1976 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1977 aInfo.applicationInfo.uid);
1978 if (app == null || app.instrumentationClass == null) {
1979 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001980 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001981 null, null, 0, 0, 0, false, false);
1982 }
1983 }
1984
1985
1986 return true;
1987 }
1988
1989 /**
1990 * Starts the "new version setup screen" if appropriate.
1991 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001992 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001993 // Only do this once per boot.
1994 if (mCheckedForSetup) {
1995 return;
1996 }
1997
1998 // We will show this screen if the current one is a different
1999 // version than the last one shown, and we are not running in
2000 // low-level factory test mode.
2001 final ContentResolver resolver = mContext.getContentResolver();
2002 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2003 Settings.Secure.getInt(resolver,
2004 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2005 mCheckedForSetup = true;
2006
2007 // See if we should be showing the platform update setup UI.
2008 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2009 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2010 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2011
2012 // We don't allow third party apps to replace this.
2013 ResolveInfo ri = null;
2014 for (int i=0; ris != null && i<ris.size(); i++) {
2015 if ((ris.get(i).activityInfo.applicationInfo.flags
2016 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2017 ri = ris.get(i);
2018 break;
2019 }
2020 }
2021
2022 if (ri != null) {
2023 String vers = ri.activityInfo.metaData != null
2024 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2025 : null;
2026 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2027 vers = ri.activityInfo.applicationInfo.metaData.getString(
2028 Intent.METADATA_SETUP_VERSION);
2029 }
2030 String lastVers = Settings.Secure.getString(
2031 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2032 if (vers != null && !vers.equals(lastVers)) {
2033 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2034 intent.setComponent(new ComponentName(
2035 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002037 null, null, 0, 0, 0, false, false);
2038 }
2039 }
2040 }
2041 }
2042
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002043 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002044 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002045
2046 final int identHash = System.identityHashCode(r);
2047 updateUsageStats(r, true);
2048
2049 int i = mWatchers.beginBroadcast();
2050 while (i > 0) {
2051 i--;
2052 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2053 if (w != null) {
2054 try {
2055 w.activityResuming(identHash);
2056 } catch (RemoteException e) {
2057 }
2058 }
2059 }
2060 mWatchers.finishBroadcast();
2061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002064 final int N = mPendingActivityLaunches.size();
2065 if (N <= 0) {
2066 return;
2067 }
2068 for (int i=0; i<N; i++) {
2069 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002071 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2072 doResume && i == (N-1));
2073 }
2074 mPendingActivityLaunches.clear();
2075 }
2076
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002077 public final int startActivity(IApplicationThread caller,
2078 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2079 int grantedMode, IBinder resultTo,
2080 String resultWho, int requestCode, boolean onlyIfNeeded,
2081 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002082 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002083 grantedUriPermissions, grantedMode, resultTo, resultWho,
2084 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002085 }
2086
2087 public final WaitResult startActivityAndWait(IApplicationThread caller,
2088 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2089 int grantedMode, IBinder resultTo,
2090 String resultWho, int requestCode, boolean onlyIfNeeded,
2091 boolean debug) {
2092 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002093 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002094 grantedUriPermissions, grantedMode, resultTo, resultWho,
2095 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002096 return res;
2097 }
2098
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002099 public final int startActivityWithConfig(IApplicationThread caller,
2100 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2101 int grantedMode, IBinder resultTo,
2102 String resultWho, int requestCode, boolean onlyIfNeeded,
2103 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002104 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002105 grantedUriPermissions, grantedMode, resultTo, resultWho,
2106 requestCode, onlyIfNeeded, debug, null, config);
2107 }
2108
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002109 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002110 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002111 IBinder resultTo, String resultWho, int requestCode,
2112 int flagsMask, int flagsValues) {
2113 // Refuse possible leaked file descriptors
2114 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2115 throw new IllegalArgumentException("File descriptors passed in Intent");
2116 }
2117
2118 IIntentSender sender = intent.getTarget();
2119 if (!(sender instanceof PendingIntentRecord)) {
2120 throw new IllegalArgumentException("Bad PendingIntent object");
2121 }
2122
2123 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002124
2125 synchronized (this) {
2126 // If this is coming from the currently resumed activity, it is
2127 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002128 if (mMainStack.mResumedActivity != null
2129 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002130 Binder.getCallingUid()) {
2131 mAppSwitchesAllowedTime = 0;
2132 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002133 }
2134
2135 return pir.sendInner(0, fillInIntent, resolvedType,
2136 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2137 }
2138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 public boolean startNextMatchingActivity(IBinder callingActivity,
2140 Intent intent) {
2141 // Refuse possible leaked file descriptors
2142 if (intent != null && intent.hasFileDescriptors() == true) {
2143 throw new IllegalArgumentException("File descriptors passed in Intent");
2144 }
2145
2146 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002147 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 if (index < 0) {
2149 return false;
2150 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002151 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 if (r.app == null || r.app.thread == null) {
2153 // The caller is not running... d'oh!
2154 return false;
2155 }
2156 intent = new Intent(intent);
2157 // The caller is not allowed to change the data.
2158 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2159 // And we are resetting to find the next component...
2160 intent.setComponent(null);
2161
2162 ActivityInfo aInfo = null;
2163 try {
2164 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002165 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002167 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168
2169 // Look for the original activity in the list...
2170 final int N = resolves != null ? resolves.size() : 0;
2171 for (int i=0; i<N; i++) {
2172 ResolveInfo rInfo = resolves.get(i);
2173 if (rInfo.activityInfo.packageName.equals(r.packageName)
2174 && rInfo.activityInfo.name.equals(r.info.name)) {
2175 // We found the current one... the next matching is
2176 // after it.
2177 i++;
2178 if (i<N) {
2179 aInfo = resolves.get(i).activityInfo;
2180 }
2181 break;
2182 }
2183 }
2184 } catch (RemoteException e) {
2185 }
2186
2187 if (aInfo == null) {
2188 // Nobody who is next!
2189 return false;
2190 }
2191
2192 intent.setComponent(new ComponentName(
2193 aInfo.applicationInfo.packageName, aInfo.name));
2194 intent.setFlags(intent.getFlags()&~(
2195 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2196 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2197 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2198 Intent.FLAG_ACTIVITY_NEW_TASK));
2199
2200 // Okay now we need to start the new activity, replacing the
2201 // currently running activity. This is a little tricky because
2202 // we want to start the new one as if the current one is finished,
2203 // but not finish the current one first so that there is no flicker.
2204 // And thus...
2205 final boolean wasFinishing = r.finishing;
2206 r.finishing = true;
2207
2208 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002209 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 final String resultWho = r.resultWho;
2211 final int requestCode = r.requestCode;
2212 r.resultTo = null;
2213 if (resultTo != null) {
2214 resultTo.removeResultsLocked(r, resultWho, requestCode);
2215 }
2216
2217 final long origId = Binder.clearCallingIdentity();
2218 // XXX we are not dealing with propagating grantedUriPermissions...
2219 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002220 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002222 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 Binder.restoreCallingIdentity(origId);
2224
2225 r.finishing = wasFinishing;
2226 if (res != START_SUCCESS) {
2227 return false;
2228 }
2229 return true;
2230 }
2231 }
2232
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002233 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 Intent intent, String resolvedType, IBinder resultTo,
2235 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002236
2237 // This is so super not safe, that only the system (or okay root)
2238 // can do it.
2239 final int callingUid = Binder.getCallingUid();
2240 if (callingUid != 0 && callingUid != Process.myUid()) {
2241 throw new SecurityException(
2242 "startActivityInPackage only available to the system");
2243 }
2244
The Android Open Source Project4df24232009-03-05 14:34:35 -08002245 final boolean componentSpecified = intent.getComponent() != null;
2246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 // Don't modify the client's object!
2248 intent = new Intent(intent);
2249
2250 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 ActivityInfo aInfo;
2252 try {
2253 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002254 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002256 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 aInfo = rInfo != null ? rInfo.activityInfo : null;
2258 } catch (RemoteException e) {
2259 aInfo = null;
2260 }
2261
2262 if (aInfo != null) {
2263 // Store the found target back into the intent, because now that
2264 // we have it we never want to do this again. For example, if the
2265 // user navigates back to this point in the history, we should
2266 // always restart the exact same activity.
2267 intent.setComponent(new ComponentName(
2268 aInfo.applicationInfo.packageName, aInfo.name));
2269 }
2270
2271 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002272 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002274 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 }
2276 }
2277
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002278 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 // Remove any existing entries that are the same kind of task.
2280 int N = mRecentTasks.size();
2281 for (int i=0; i<N; i++) {
2282 TaskRecord tr = mRecentTasks.get(i);
2283 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2284 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2285 mRecentTasks.remove(i);
2286 i--;
2287 N--;
2288 if (task.intent == null) {
2289 // If the new recent task we are adding is not fully
2290 // specified, then replace it with the existing recent task.
2291 task = tr;
2292 }
2293 }
2294 }
2295 if (N >= MAX_RECENT_TASKS) {
2296 mRecentTasks.remove(N-1);
2297 }
2298 mRecentTasks.add(0, task);
2299 }
2300
2301 public void setRequestedOrientation(IBinder token,
2302 int requestedOrientation) {
2303 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002304 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 if (index < 0) {
2306 return;
2307 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002308 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 final long origId = Binder.clearCallingIdentity();
2310 mWindowManager.setAppOrientation(r, requestedOrientation);
2311 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002312 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 r.mayFreezeScreenLocked(r.app) ? r : null);
2314 if (config != null) {
2315 r.frozenBeforeDestroy = true;
2316 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002317 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 }
2319 }
2320 Binder.restoreCallingIdentity(origId);
2321 }
2322 }
2323
2324 public int getRequestedOrientation(IBinder token) {
2325 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002326 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 if (index < 0) {
2328 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2329 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002330 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 return mWindowManager.getAppOrientation(r);
2332 }
2333 }
2334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 /**
2336 * This is the internal entry point for handling Activity.finish().
2337 *
2338 * @param token The Binder token referencing the Activity we want to finish.
2339 * @param resultCode Result code, if any, from this Activity.
2340 * @param resultData Result data (Intent), if any, from this Activity.
2341 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002342 * @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 -08002343 */
2344 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2345 // Refuse possible leaked file descriptors
2346 if (resultData != null && resultData.hasFileDescriptors() == true) {
2347 throw new IllegalArgumentException("File descriptors passed in Intent");
2348 }
2349
2350 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002351 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 if (next != null) {
2355 // ask watcher if this is allowed
2356 boolean resumeOK = true;
2357 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002358 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002360 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 }
2362
2363 if (!resumeOK) {
2364 return false;
2365 }
2366 }
2367 }
2368 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002369 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 resultData, "app-request");
2371 Binder.restoreCallingIdentity(origId);
2372 return res;
2373 }
2374 }
2375
Dianne Hackborn860755f2010-06-03 18:47:52 -07002376 public final void finishHeavyWeightApp() {
2377 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2378 != PackageManager.PERMISSION_GRANTED) {
2379 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2380 + Binder.getCallingPid()
2381 + ", uid=" + Binder.getCallingUid()
2382 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2383 Slog.w(TAG, msg);
2384 throw new SecurityException(msg);
2385 }
2386
2387 synchronized(this) {
2388 if (mHeavyWeightProcess == null) {
2389 return;
2390 }
2391
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002392 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002393 mHeavyWeightProcess.activities);
2394 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002395 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002396 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002397 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002398 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002399 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002400 null, "finish-heavy");
2401 }
2402 }
2403 }
2404
2405 mHeavyWeightProcess = null;
2406 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2407 }
2408 }
2409
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002410 public void crashApplication(int uid, int initialPid, String packageName,
2411 String message) {
2412 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2413 != PackageManager.PERMISSION_GRANTED) {
2414 String msg = "Permission Denial: crashApplication() from pid="
2415 + Binder.getCallingPid()
2416 + ", uid=" + Binder.getCallingUid()
2417 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2418 Slog.w(TAG, msg);
2419 throw new SecurityException(msg);
2420 }
2421
2422 synchronized(this) {
2423 ProcessRecord proc = null;
2424
2425 // Figure out which process to kill. We don't trust that initialPid
2426 // still has any relation to current pids, so must scan through the
2427 // list.
2428 synchronized (mPidsSelfLocked) {
2429 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2430 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2431 if (p.info.uid != uid) {
2432 continue;
2433 }
2434 if (p.pid == initialPid) {
2435 proc = p;
2436 break;
2437 }
2438 for (String str : p.pkgList) {
2439 if (str.equals(packageName)) {
2440 proc = p;
2441 }
2442 }
2443 }
2444 }
2445
2446 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002447 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002448 + " initialPid=" + initialPid
2449 + " packageName=" + packageName);
2450 return;
2451 }
2452
2453 if (proc.thread != null) {
2454 long ident = Binder.clearCallingIdentity();
2455 try {
2456 proc.thread.scheduleCrash(message);
2457 } catch (RemoteException e) {
2458 }
2459 Binder.restoreCallingIdentity(ident);
2460 }
2461 }
2462 }
2463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 public final void finishSubActivity(IBinder token, String resultWho,
2465 int requestCode) {
2466 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002467 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 if (index < 0) {
2469 return;
2470 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472
2473 final long origId = Binder.clearCallingIdentity();
2474
2475 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002476 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2477 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 if (r.resultTo == self && r.requestCode == requestCode) {
2479 if ((r.resultWho == null && resultWho == null) ||
2480 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002481 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 Activity.RESULT_CANCELED, null, "request-sub");
2483 }
2484 }
2485 }
2486
2487 Binder.restoreCallingIdentity(origId);
2488 }
2489 }
2490
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002491 public boolean willActivityBeVisible(IBinder token) {
2492 synchronized(this) {
2493 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002494 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2495 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002496 if (r == token) {
2497 return true;
2498 }
2499 if (r.fullscreen && !r.finishing) {
2500 return false;
2501 }
2502 }
2503 return true;
2504 }
2505 }
2506
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002507 public void overridePendingTransition(IBinder token, String packageName,
2508 int enterAnim, int exitAnim) {
2509 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002510 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002511 if (index < 0) {
2512 return;
2513 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002515
2516 final long origId = Binder.clearCallingIdentity();
2517
2518 if (self.state == ActivityState.RESUMED
2519 || self.state == ActivityState.PAUSING) {
2520 mWindowManager.overridePendingAppTransition(packageName,
2521 enterAnim, exitAnim);
2522 }
2523
2524 Binder.restoreCallingIdentity(origId);
2525 }
2526 }
2527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 * Main function for removing an existing process from the activity manager
2530 * as a result of that process going away. Clears out all connections
2531 * to the process.
2532 */
2533 private final void handleAppDiedLocked(ProcessRecord app,
2534 boolean restarting) {
2535 cleanUpApplicationRecordLocked(app, restarting, -1);
2536 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002537 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002538 }
2539
2540 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002541 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2542 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2543 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002545 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2546 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 }
2548
2549 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002550 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551
2552 boolean atTop = true;
2553 boolean hasVisibleActivities = false;
2554
2555 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002556 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002557 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 TAG, "Removing app " + app + " from history with " + i + " entries");
2559 while (i > 0) {
2560 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002561 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002562 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2564 if (r.app == app) {
2565 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002566 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 TAG, "Removing this entry! frozen=" + r.haveState
2568 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570
2571 r.inHistory = false;
2572 mWindowManager.removeAppToken(r);
2573 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002574 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002576 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577
2578 } else {
2579 // We have the current state for this activity, so
2580 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 TAG, "Keeping entry, setting app to null");
2583 if (r.visible) {
2584 hasVisibleActivities = true;
2585 }
2586 r.app = null;
2587 r.nowVisible = false;
2588 if (!r.haveState) {
2589 r.icicle = null;
2590 }
2591 }
2592
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 r.state = ActivityState.STOPPED;
2595 }
2596 atTop = false;
2597 }
2598
2599 app.activities.clear();
2600
2601 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002602 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 + " running instrumentation " + app.instrumentationClass);
2604 Bundle info = new Bundle();
2605 info.putString("shortMsg", "Process crashed.");
2606 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2607 }
2608
2609 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002610 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 // If there was nothing to resume, and we are not already
2612 // restarting this process, but there is a visible activity that
2613 // is hosted by the process... then make sure all visible
2614 // activities are running, taking care of restarting this
2615 // process.
2616 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002617 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 }
2619 }
2620 }
2621 }
2622
2623 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2624 IBinder threadBinder = thread.asBinder();
2625
2626 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002627 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2628 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2630 return i;
2631 }
2632 }
2633 return -1;
2634 }
2635
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002636 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 IApplicationThread thread) {
2638 if (thread == null) {
2639 return null;
2640 }
2641
2642 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002643 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 }
2645
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002646 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 IApplicationThread thread) {
2648
2649 mProcDeaths[0]++;
2650
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002651 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2652 synchronized (stats) {
2653 stats.noteProcessDiedLocked(app.info.uid, pid);
2654 }
2655
Magnus Edlund7bb25812010-02-24 15:45:06 +01002656 // Clean up already done if the process has been re-started.
2657 if (app.pid == pid && app.thread != null &&
2658 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002659 if (!app.killedBackground) {
2660 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2661 + ") has died.");
2662 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002663 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002664 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 TAG, "Dying app: " + app + ", pid: " + pid
2666 + ", thread: " + thread.asBinder());
2667 boolean doLowMem = app.instrumentationClass == null;
2668 handleAppDiedLocked(app, false);
2669
2670 if (doLowMem) {
2671 // If there are no longer any background processes running,
2672 // and the app that died was not running instrumentation,
2673 // then tell everyone we are now low on memory.
2674 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002675 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2676 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002677 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2678 haveBg = true;
2679 break;
2680 }
2681 }
2682
2683 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002684 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002685 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002686 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002687 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2688 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002689 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002690 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2691 // The low memory report is overriding any current
2692 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002693 // heavy/important/visible/foreground processes first.
2694 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002695 rec.lastRequestedGc = 0;
2696 } else {
2697 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002699 rec.reportLowMemory = true;
2700 rec.lastLowMemory = now;
2701 mProcessesToGc.remove(rec);
2702 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 }
2704 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002705 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 }
2707 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002708 } else if (app.pid != pid) {
2709 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002710 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002711 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002712 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002713 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002714 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 + thread.asBinder());
2716 }
2717 }
2718
Dan Egnor42471dd2010-01-07 17:25:22 -08002719 /**
2720 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002721 * @param clearTraces causes the dump file to be erased prior to the new
2722 * traces being written, if true; when false, the new traces will be
2723 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002724 * @param firstPids of dalvik VM processes to dump stack traces for first
2725 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002726 * @return file containing stack traces, or null if no dump file is configured
2727 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002728 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2729 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002730 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2731 if (tracesPath == null || tracesPath.length() == 0) {
2732 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002733 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002734
2735 File tracesFile = new File(tracesPath);
2736 try {
2737 File tracesDir = tracesFile.getParentFile();
2738 if (!tracesDir.exists()) tracesFile.mkdirs();
2739 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2740
Christopher Tate6ee412d2010-05-28 12:01:56 -07002741 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002742 tracesFile.createNewFile();
2743 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2744 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002745 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002746 return null;
2747 }
2748
2749 // Use a FileObserver to detect when traces finish writing.
2750 // The order of traces is considered important to maintain for legibility.
2751 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2752 public synchronized void onEvent(int event, String path) { notify(); }
2753 };
2754
2755 try {
2756 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002757
2758 // First collect all of the stacks of the most important pids.
2759 try {
2760 int num = firstPids.size();
2761 for (int i = 0; i < num; i++) {
2762 synchronized (observer) {
2763 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2764 observer.wait(200); // Wait for write-close, give up after 200msec
2765 }
2766 }
2767 } catch (InterruptedException e) {
2768 Log.wtf(TAG, e);
2769 }
2770
2771 // Next measure CPU usage.
2772 if (processStats != null) {
2773 processStats.init();
2774 System.gc();
2775 processStats.update();
2776 try {
2777 synchronized (processStats) {
2778 processStats.wait(500); // measure over 1/2 second.
2779 }
2780 } catch (InterruptedException e) {
2781 }
2782 processStats.update();
2783
2784 // We'll take the stack crawls of just the top apps using CPU.
2785 final int N = processStats.countWorkingStats();
2786 int numProcs = 0;
2787 for (int i=0; i<N && numProcs<5; i++) {
2788 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2789 if (lastPids.indexOfKey(stats.pid) >= 0) {
2790 numProcs++;
2791 try {
2792 synchronized (observer) {
2793 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2794 observer.wait(200); // Wait for write-close, give up after 200msec
2795 }
2796 } catch (InterruptedException e) {
2797 Log.wtf(TAG, e);
2798 }
2799
2800 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002801 }
2802 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002803
2804 return tracesFile;
2805
Dan Egnor42471dd2010-01-07 17:25:22 -08002806 } finally {
2807 observer.stopWatching();
2808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 }
2810
Jeff Brown4d94a762010-09-23 11:33:28 -07002811 private final class AppNotResponding implements Runnable {
2812 private final ProcessRecord mApp;
2813 private final String mAnnotation;
2814
2815 public AppNotResponding(ProcessRecord app, String annotation) {
2816 mApp = app;
2817 mAnnotation = annotation;
2818 }
2819
2820 @Override
2821 public void run() {
2822 appNotResponding(mApp, null, null, mAnnotation);
2823 }
2824 }
2825
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002826 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2827 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002828 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2829 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2830
Dianne Hackborn287952c2010-09-22 22:34:31 -07002831 if (mController != null) {
2832 try {
2833 // 0 == continue, -1 = kill process immediately
2834 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2835 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2836 } catch (RemoteException e) {
2837 mController = null;
2838 }
2839 }
2840
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002841 long anrTime = SystemClock.uptimeMillis();
2842 if (MONITOR_CPU_USAGE) {
2843 updateCpuStatsNow();
2844 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002845
2846 synchronized (this) {
2847 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2848 if (mShuttingDown) {
2849 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2850 return;
2851 } else if (app.notResponding) {
2852 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2853 return;
2854 } else if (app.crashing) {
2855 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2856 return;
2857 }
2858
2859 // In case we come through here for the same app before completing
2860 // this one, mark as anring now so we will bail out.
2861 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002862
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002863 // Log the ANR to the event log.
2864 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2865 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002866
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002867 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002868 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002869
2870 int parentPid = app.pid;
2871 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002872 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002873
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002874 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002875
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002876 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2877 ProcessRecord r = mLruProcesses.get(i);
2878 if (r != null && r.thread != null) {
2879 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002880 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2881 if (r.persistent) {
2882 firstPids.add(pid);
2883 } else {
2884 lastPids.put(pid, Boolean.TRUE);
2885 }
2886 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889 }
2890
Dan Egnor42471dd2010-01-07 17:25:22 -08002891 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002892 StringBuilder info = mStringBuilder;
2893 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002894 info.append("ANR in ").append(app.processName);
2895 if (activity != null && activity.shortComponentName != null) {
2896 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002897 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002898 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002900 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002902 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002903 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905
Dianne Hackborn287952c2010-09-22 22:34:31 -07002906 final ProcessStats processStats = new ProcessStats(true);
2907
2908 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2909
Dan Egnor42471dd2010-01-07 17:25:22 -08002910 String cpuInfo = null;
2911 if (MONITOR_CPU_USAGE) {
2912 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002913 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002914 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002915 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002916 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002917 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 }
2919
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002920 info.append(processStats.printCurrentState(anrTime));
2921
Joe Onorato8a9b2202010-02-26 18:56:32 -08002922 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002923 if (tracesFile == null) {
2924 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2925 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2926 }
2927
2928 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2929
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002930 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002932 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2933 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002935 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2936 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 }
2938 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002939 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
2941 }
2942
Dan Egnor42471dd2010-01-07 17:25:22 -08002943 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2944 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2945 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002946
2947 synchronized (this) {
2948 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2949 Process.killProcess(app.pid);
2950 return;
2951 }
2952
2953 // Set the app's notResponding state, and look up the errorReportReceiver
2954 makeAppNotRespondingLocked(app,
2955 activity != null ? activity.shortComponentName : null,
2956 annotation != null ? "ANR " + annotation : "ANR",
2957 info.toString());
2958
2959 // Bring up the infamous App Not Responding dialog
2960 Message msg = Message.obtain();
2961 HashMap map = new HashMap();
2962 msg.what = SHOW_NOT_RESPONDING_MSG;
2963 msg.obj = map;
2964 map.put("app", app);
2965 if (activity != null) {
2966 map.put("activity", activity);
2967 }
2968
2969 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 }
2972
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002973 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2974 if (!mLaunchWarningShown) {
2975 mLaunchWarningShown = true;
2976 mHandler.post(new Runnable() {
2977 @Override
2978 public void run() {
2979 synchronized (ActivityManagerService.this) {
2980 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2981 d.show();
2982 mHandler.postDelayed(new Runnable() {
2983 @Override
2984 public void run() {
2985 synchronized (ActivityManagerService.this) {
2986 d.dismiss();
2987 mLaunchWarningShown = false;
2988 }
2989 }
2990 }, 4000);
2991 }
2992 }
2993 });
2994 }
2995 }
2996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 public boolean clearApplicationUserData(final String packageName,
2998 final IPackageDataObserver observer) {
2999 int uid = Binder.getCallingUid();
3000 int pid = Binder.getCallingPid();
3001 long callingId = Binder.clearCallingIdentity();
3002 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003003 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 int pkgUid = -1;
3005 synchronized(this) {
3006 try {
3007 pkgUid = pm.getPackageUid(packageName);
3008 } catch (RemoteException e) {
3009 }
3010 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003011 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 return false;
3013 }
3014 if (uid == pkgUid || checkComponentPermission(
3015 android.Manifest.permission.CLEAR_APP_USER_DATA,
3016 pid, uid, -1)
3017 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003018 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 } else {
3020 throw new SecurityException(pid+" does not have permission:"+
3021 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3022 "for process:"+packageName);
3023 }
3024 }
3025
3026 try {
3027 //clear application user data
3028 pm.clearApplicationUserData(packageName, observer);
3029 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3030 Uri.fromParts("package", packageName, null));
3031 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003032 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3033 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 } catch (RemoteException e) {
3035 }
3036 } finally {
3037 Binder.restoreCallingIdentity(callingId);
3038 }
3039 return true;
3040 }
3041
Dianne Hackborn03abb812010-01-04 18:43:19 -08003042 public void killBackgroundProcesses(final String packageName) {
3043 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3044 != PackageManager.PERMISSION_GRANTED &&
3045 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3046 != PackageManager.PERMISSION_GRANTED) {
3047 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 + Binder.getCallingPid()
3049 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003050 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003051 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 throw new SecurityException(msg);
3053 }
3054
3055 long callingId = Binder.clearCallingIdentity();
3056 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003057 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 int pkgUid = -1;
3059 synchronized(this) {
3060 try {
3061 pkgUid = pm.getPackageUid(packageName);
3062 } catch (RemoteException e) {
3063 }
3064 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003065 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 return;
3067 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003068 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003069 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003070 }
3071 } finally {
3072 Binder.restoreCallingIdentity(callingId);
3073 }
3074 }
3075
3076 public void forceStopPackage(final String packageName) {
3077 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3078 != PackageManager.PERMISSION_GRANTED) {
3079 String msg = "Permission Denial: forceStopPackage() from pid="
3080 + Binder.getCallingPid()
3081 + ", uid=" + Binder.getCallingUid()
3082 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003083 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003084 throw new SecurityException(msg);
3085 }
3086
3087 long callingId = Binder.clearCallingIdentity();
3088 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003089 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003090 int pkgUid = -1;
3091 synchronized(this) {
3092 try {
3093 pkgUid = pm.getPackageUid(packageName);
3094 } catch (RemoteException e) {
3095 }
3096 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003097 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003098 return;
3099 }
3100 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 }
3102 } finally {
3103 Binder.restoreCallingIdentity(callingId);
3104 }
3105 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003106
3107 /*
3108 * The pkg name and uid have to be specified.
3109 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3110 */
3111 public void killApplicationWithUid(String pkg, int uid) {
3112 if (pkg == null) {
3113 return;
3114 }
3115 // Make sure the uid is valid.
3116 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003117 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003118 return;
3119 }
3120 int callerUid = Binder.getCallingUid();
3121 // Only the system server can kill an application
3122 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003123 // Post an aysnc message to kill the application
3124 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3125 msg.arg1 = uid;
3126 msg.arg2 = 0;
3127 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003128 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003129 } else {
3130 throw new SecurityException(callerUid + " cannot kill pkg: " +
3131 pkg);
3132 }
3133 }
3134
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003135 public void closeSystemDialogs(String reason) {
3136 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003137 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003138 if (reason != null) {
3139 intent.putExtra("reason", reason);
3140 }
3141
3142 final int uid = Binder.getCallingUid();
3143 final long origId = Binder.clearCallingIdentity();
3144 synchronized (this) {
3145 int i = mWatchers.beginBroadcast();
3146 while (i > 0) {
3147 i--;
3148 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3149 if (w != null) {
3150 try {
3151 w.closingSystemDialogs(reason);
3152 } catch (RemoteException e) {
3153 }
3154 }
3155 }
3156 mWatchers.finishBroadcast();
3157
Dianne Hackbornffa42482009-09-23 22:20:11 -07003158 mWindowManager.closeSystemDialogs(reason);
3159
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003160 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3161 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003162 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003163 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003164 Activity.RESULT_CANCELED, null, "close-sys");
3165 }
3166 }
3167
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003168 broadcastIntentLocked(null, null, intent, null,
3169 null, 0, null, null, null, false, false, -1, uid);
3170 }
3171 Binder.restoreCallingIdentity(origId);
3172 }
3173
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003174 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003175 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003176 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3177 for (int i=pids.length-1; i>=0; i--) {
3178 infos[i] = new Debug.MemoryInfo();
3179 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003180 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003181 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003182 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003183
3184 public void killApplicationProcess(String processName, int uid) {
3185 if (processName == null) {
3186 return;
3187 }
3188
3189 int callerUid = Binder.getCallingUid();
3190 // Only the system server can kill an application
3191 if (callerUid == Process.SYSTEM_UID) {
3192 synchronized (this) {
3193 ProcessRecord app = getProcessRecordLocked(processName, uid);
3194 if (app != null) {
3195 try {
3196 app.thread.scheduleSuicide();
3197 } catch (RemoteException e) {
3198 // If the other end already died, then our work here is done.
3199 }
3200 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003201 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003202 + processName + " / " + uid);
3203 }
3204 }
3205 } else {
3206 throw new SecurityException(callerUid + " cannot kill app process: " +
3207 processName);
3208 }
3209 }
3210
Dianne Hackborn03abb812010-01-04 18:43:19 -08003211 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003212 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3214 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003215 if (!mProcessesReady) {
3216 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 intent.putExtra(Intent.EXTRA_UID, uid);
3219 broadcastIntentLocked(null, null, intent,
3220 null, null, 0, null, null, null,
3221 false, false, MY_PID, Process.SYSTEM_UID);
3222 }
3223
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003224 private final boolean killPackageProcessesLocked(String packageName, int uid,
3225 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003226 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003227
Dianne Hackborn03abb812010-01-04 18:43:19 -08003228 // Remove all processes this package may have touched: all with the
3229 // same UID (except for the system or root user), and all whose name
3230 // matches the package name.
3231 final String procNamePrefix = packageName + ":";
3232 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3233 final int NA = apps.size();
3234 for (int ia=0; ia<NA; ia++) {
3235 ProcessRecord app = apps.valueAt(ia);
3236 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003237 if (doit) {
3238 procs.add(app);
3239 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003240 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3241 || app.processName.equals(packageName)
3242 || app.processName.startsWith(procNamePrefix)) {
3243 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003244 if (!doit) {
3245 return true;
3246 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003247 app.removed = true;
3248 procs.add(app);
3249 }
3250 }
3251 }
3252 }
3253
3254 int N = procs.size();
3255 for (int i=0; i<N; i++) {
3256 removeProcessLocked(procs.get(i), callerWillRestart);
3257 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003258 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003259 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003260
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003261 private final boolean forceStopPackageLocked(String name, int uid,
3262 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 int i, N;
3264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 if (uid < 0) {
3266 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003267 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003268 } catch (RemoteException e) {
3269 }
3270 }
3271
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003272 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003273 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003274
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003275 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3276 while (badApps.hasNext()) {
3277 SparseArray<Long> ba = badApps.next();
3278 if (ba.get(uid) != null) {
3279 badApps.remove();
3280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 }
3282 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003283
3284 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3285 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003287 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3288 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003290 if (!doit) {
3291 return true;
3292 }
3293 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003294 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 if (r.app != null) {
3296 r.app.removed = true;
3297 }
3298 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003299 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 }
3301 }
3302
3303 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3304 for (ServiceRecord service : mServices.values()) {
3305 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003306 if (!doit) {
3307 return true;
3308 }
3309 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003310 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 if (service.app != null) {
3312 service.app.removed = true;
3313 }
3314 service.app = null;
3315 services.add(service);
3316 }
3317 }
3318
3319 N = services.size();
3320 for (i=0; i<N; i++) {
3321 bringDownServiceLocked(services.get(i), true);
3322 }
3323
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003324 if (doit) {
3325 if (purgeCache) {
3326 AttributeCache ac = AttributeCache.instance();
3327 if (ac != null) {
3328 ac.removePackage(name);
3329 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003330 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003331 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003332 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003333
3334 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 }
3336
3337 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3338 final String name = app.processName;
3339 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003340 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 TAG, "Force removing process " + app + " (" + name
3342 + "/" + uid + ")");
3343
3344 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003345 if (mHeavyWeightProcess == app) {
3346 mHeavyWeightProcess = null;
3347 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 boolean needRestart = false;
3350 if (app.pid > 0 && app.pid != MY_PID) {
3351 int pid = app.pid;
3352 synchronized (mPidsSelfLocked) {
3353 mPidsSelfLocked.remove(pid);
3354 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3355 }
3356 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003357 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 Process.killProcess(pid);
3359
3360 if (app.persistent) {
3361 if (!callerWillRestart) {
3362 addAppLocked(app.info);
3363 } else {
3364 needRestart = true;
3365 }
3366 }
3367 } else {
3368 mRemovedProcesses.add(app);
3369 }
3370
3371 return needRestart;
3372 }
3373
3374 private final void processStartTimedOutLocked(ProcessRecord app) {
3375 final int pid = app.pid;
3376 boolean gone = false;
3377 synchronized (mPidsSelfLocked) {
3378 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3379 if (knownApp != null && knownApp.thread == null) {
3380 mPidsSelfLocked.remove(pid);
3381 gone = true;
3382 }
3383 }
3384
3385 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003386 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003387 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003388 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003390 if (mHeavyWeightProcess == app) {
3391 mHeavyWeightProcess = null;
3392 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3393 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003394 // Take care of any launching providers waiting for this process.
3395 checkAppInLaunchingProvidersLocked(app, true);
3396 // Take care of any services that are waiting for the process.
3397 for (int i=0; i<mPendingServices.size(); i++) {
3398 ServiceRecord sr = mPendingServices.get(i);
3399 if (app.info.uid == sr.appInfo.uid
3400 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003401 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003402 mPendingServices.remove(i);
3403 i--;
3404 bringDownServiceLocked(sr, true);
3405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003407 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003408 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003409 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003410 try {
3411 IBackupManager bm = IBackupManager.Stub.asInterface(
3412 ServiceManager.getService(Context.BACKUP_SERVICE));
3413 bm.agentDisconnected(app.info.packageName);
3414 } catch (RemoteException e) {
3415 // Can't happen; the backup manager is local
3416 }
3417 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003418 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003419 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003420 mPendingBroadcast.state = BroadcastRecord.IDLE;
3421 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003422 mPendingBroadcast = null;
3423 scheduleBroadcastsLocked();
3424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003426 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 }
3428 }
3429
3430 private final boolean attachApplicationLocked(IApplicationThread thread,
3431 int pid) {
3432
3433 // Find the application record that is being attached... either via
3434 // the pid if we are running in multiple processes, or just pull the
3435 // next app record if we are emulating process with anonymous threads.
3436 ProcessRecord app;
3437 if (pid != MY_PID && pid >= 0) {
3438 synchronized (mPidsSelfLocked) {
3439 app = mPidsSelfLocked.get(pid);
3440 }
3441 } else if (mStartingProcesses.size() > 0) {
3442 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003443 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 } else {
3445 app = null;
3446 }
3447
3448 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003449 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003451 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 if (pid > 0 && pid != MY_PID) {
3453 Process.killProcess(pid);
3454 } else {
3455 try {
3456 thread.scheduleExit();
3457 } catch (Exception e) {
3458 // Ignore exceptions.
3459 }
3460 }
3461 return false;
3462 }
3463
3464 // If this application record is still attached to a previous
3465 // process, clean it up now.
3466 if (app.thread != null) {
3467 handleAppDiedLocked(app, true);
3468 }
3469
3470 // Tell the process all about itself.
3471
Joe Onorato8a9b2202010-02-26 18:56:32 -08003472 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 TAG, "Binding process pid " + pid + " to record " + app);
3474
3475 String processName = app.processName;
3476 try {
3477 thread.asBinder().linkToDeath(new AppDeathRecipient(
3478 app, pid, thread), 0);
3479 } catch (RemoteException e) {
3480 app.resetPackageList();
3481 startProcessLocked(app, "link fail", processName);
3482 return false;
3483 }
3484
Doug Zongker2bec3d42009-12-04 12:52:44 -08003485 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486
3487 app.thread = thread;
3488 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003489 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3490 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 app.forcingToForeground = null;
3492 app.foregroundServices = false;
3493 app.debugging = false;
3494
3495 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3496
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003497 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003498 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003500 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003501 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003502 }
3503
Joe Onorato8a9b2202010-02-26 18:56:32 -08003504 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 TAG, "New app record " + app
3506 + " thread=" + thread.asBinder() + " pid=" + pid);
3507 try {
3508 int testMode = IApplicationThread.DEBUG_OFF;
3509 if (mDebugApp != null && mDebugApp.equals(processName)) {
3510 testMode = mWaitForDebugger
3511 ? IApplicationThread.DEBUG_WAIT
3512 : IApplicationThread.DEBUG_ON;
3513 app.debugging = true;
3514 if (mDebugTransient) {
3515 mDebugApp = mOrigDebugApp;
3516 mWaitForDebugger = mOrigWaitForDebugger;
3517 }
3518 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003519
Christopher Tate181fafa2009-05-14 11:12:14 -07003520 // If the app is being launched for restore or full backup, set it up specially
3521 boolean isRestrictedBackupMode = false;
3522 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3523 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3524 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3525 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003526
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003527 ensurePackageDexOpt(app.instrumentationInfo != null
3528 ? app.instrumentationInfo.packageName
3529 : app.info.packageName);
3530 if (app.instrumentationClass != null) {
3531 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003532 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003533 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003534 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003535 thread.bindApplication(processName, app.instrumentationInfo != null
3536 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 app.instrumentationClass, app.instrumentationProfileFile,
3538 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003539 isRestrictedBackupMode || !normalMode,
3540 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003541 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003542 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 } catch (Exception e) {
3544 // todo: Yikes! What should we do? For now we will try to
3545 // start another process, but that could easily get us in
3546 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003547 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548
3549 app.resetPackageList();
3550 startProcessLocked(app, "bind fail", processName);
3551 return false;
3552 }
3553
3554 // Remove this record from the list of starting applications.
3555 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003556 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3557 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 mProcessesOnHold.remove(app);
3559
3560 boolean badApp = false;
3561 boolean didSomething = false;
3562
3563 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003564 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003565 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3567 && processName.equals(hr.processName)) {
3568 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003569 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 didSomething = true;
3571 }
3572 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003573 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 + hr.intent.getComponent().flattenToShortString(), e);
3575 badApp = true;
3576 }
3577 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003578 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 }
3580 }
3581
3582 // Find any services that should be running in this process...
3583 if (!badApp && mPendingServices.size() > 0) {
3584 ServiceRecord sr = null;
3585 try {
3586 for (int i=0; i<mPendingServices.size(); i++) {
3587 sr = mPendingServices.get(i);
3588 if (app.info.uid != sr.appInfo.uid
3589 || !processName.equals(sr.processName)) {
3590 continue;
3591 }
3592
3593 mPendingServices.remove(i);
3594 i--;
3595 realStartServiceLocked(sr, app);
3596 didSomething = true;
3597 }
3598 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003599 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 + sr.shortName, e);
3601 badApp = true;
3602 }
3603 }
3604
3605 // Check if the next broadcast receiver is in this process...
3606 BroadcastRecord br = mPendingBroadcast;
3607 if (!badApp && br != null && br.curApp == app) {
3608 try {
3609 mPendingBroadcast = null;
3610 processCurBroadcastLocked(br, app);
3611 didSomething = true;
3612 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003613 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 + br.curComponent.flattenToShortString(), e);
3615 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003616 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3618 br.resultExtras, br.resultAbort, true);
3619 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003620 // We need to reset the state if we fails to start the receiver.
3621 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 }
3623 }
3624
Christopher Tate181fafa2009-05-14 11:12:14 -07003625 // Check whether the next backup agent is in this process...
3626 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003627 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003628 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003629 try {
3630 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3631 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003632 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003633 e.printStackTrace();
3634 }
3635 }
3636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 if (badApp) {
3638 // todo: Also need to kill application to deal with all
3639 // kinds of exceptions.
3640 handleAppDiedLocked(app, false);
3641 return false;
3642 }
3643
3644 if (!didSomething) {
3645 updateOomAdjLocked();
3646 }
3647
3648 return true;
3649 }
3650
3651 public final void attachApplication(IApplicationThread thread) {
3652 synchronized (this) {
3653 int callingPid = Binder.getCallingPid();
3654 final long origId = Binder.clearCallingIdentity();
3655 attachApplicationLocked(thread, callingPid);
3656 Binder.restoreCallingIdentity(origId);
3657 }
3658 }
3659
Dianne Hackborne88846e2009-09-30 21:34:25 -07003660 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003662 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 Binder.restoreCallingIdentity(origId);
3664 }
3665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003667 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003668 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 mWindowManager.enableScreenAfterBoot();
3670 }
3671
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003672 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003673 IntentFilter pkgFilter = new IntentFilter();
3674 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3675 pkgFilter.addDataScheme("package");
3676 mContext.registerReceiver(new BroadcastReceiver() {
3677 @Override
3678 public void onReceive(Context context, Intent intent) {
3679 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3680 if (pkgs != null) {
3681 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003682 synchronized (ActivityManagerService.this) {
3683 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3684 setResultCode(Activity.RESULT_OK);
3685 return;
3686 }
3687 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003688 }
3689 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003690 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003691 }, pkgFilter);
3692
3693 synchronized (this) {
3694 // Ensure that any processes we had put on hold are now started
3695 // up.
3696 final int NP = mProcessesOnHold.size();
3697 if (NP > 0) {
3698 ArrayList<ProcessRecord> procs =
3699 new ArrayList<ProcessRecord>(mProcessesOnHold);
3700 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003701 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3702 + procs.get(ip));
3703 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003704 }
3705 }
3706
3707 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003708 // Start looking for apps that are abusing wake locks.
3709 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003710 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003711 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003712 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003713 broadcastIntentLocked(null, null,
3714 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3715 null, null, 0, null, null,
3716 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3717 false, false, MY_PID, Process.SYSTEM_UID);
3718 }
3719 }
3720 }
3721
3722 final void ensureBootCompleted() {
3723 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003724 boolean enableScreen;
3725 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003726 booting = mBooting;
3727 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003728 enableScreen = !mBooted;
3729 mBooted = true;
3730 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003731
3732 if (booting) {
3733 finishBooting();
3734 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003735
3736 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003737 enableScreenAfterBoot();
3738 }
3739 }
3740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 public final void activityPaused(IBinder token, Bundle icicle) {
3742 // Refuse possible leaked file descriptors
3743 if (icicle != null && icicle.hasFileDescriptors()) {
3744 throw new IllegalArgumentException("File descriptors passed in Bundle");
3745 }
3746
3747 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003748 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 Binder.restoreCallingIdentity(origId);
3750 }
3751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 public final void activityStopped(IBinder token, Bitmap thumbnail,
3753 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003754 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 TAG, "Activity stopped: token=" + token);
3756
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003757 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758
3759 final long origId = Binder.clearCallingIdentity();
3760
3761 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003762 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003764 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 r.thumbnail = thumbnail;
3766 r.description = description;
3767 r.stopped = true;
3768 r.state = ActivityState.STOPPED;
3769 if (!r.finishing) {
3770 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003771 r.stack.destroyActivityLocked(r, true);
3772 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 }
3774 }
3775 }
3776 }
3777
3778 if (r != null) {
3779 sendPendingThumbnail(r, null, null, null, false);
3780 }
3781
3782 trimApplications();
3783
3784 Binder.restoreCallingIdentity(origId);
3785 }
3786
3787 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003788 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003789 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 }
3791
3792 public String getCallingPackage(IBinder token) {
3793 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003794 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003795 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 }
3797 }
3798
3799 public ComponentName getCallingActivity(IBinder token) {
3800 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003801 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 return r != null ? r.intent.getComponent() : null;
3803 }
3804 }
3805
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003806 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003807 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003809 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 if (r != null) {
3811 return r.resultTo;
3812 }
3813 }
3814 return null;
3815 }
3816
3817 public ComponentName getActivityClassForToken(IBinder token) {
3818 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003819 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003821 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 return r.intent.getComponent();
3823 }
3824 return null;
3825 }
3826 }
3827
3828 public String getPackageForToken(IBinder token) {
3829 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003830 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003832 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833 return r.packageName;
3834 }
3835 return null;
3836 }
3837 }
3838
3839 public IIntentSender getIntentSender(int type,
3840 String packageName, IBinder token, String resultWho,
3841 int requestCode, Intent intent, String resolvedType, int flags) {
3842 // Refuse possible leaked file descriptors
3843 if (intent != null && intent.hasFileDescriptors() == true) {
3844 throw new IllegalArgumentException("File descriptors passed in Intent");
3845 }
3846
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003847 if (type == INTENT_SENDER_BROADCAST) {
3848 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3849 throw new IllegalArgumentException(
3850 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3851 }
3852 }
3853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 synchronized(this) {
3855 int callingUid = Binder.getCallingUid();
3856 try {
3857 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3858 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003859 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 .getPackageUid(packageName);
3861 if (uid != Binder.getCallingUid()) {
3862 String msg = "Permission Denial: getIntentSender() from pid="
3863 + Binder.getCallingPid()
3864 + ", uid=" + Binder.getCallingUid()
3865 + ", (need uid=" + uid + ")"
3866 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003867 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 throw new SecurityException(msg);
3869 }
3870 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003871
3872 return getIntentSenderLocked(type, packageName, callingUid,
3873 token, resultWho, requestCode, intent, resolvedType, flags);
3874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003875 } catch (RemoteException e) {
3876 throw new SecurityException(e);
3877 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003878 }
3879 }
3880
3881 IIntentSender getIntentSenderLocked(int type,
3882 String packageName, int callingUid, IBinder token, String resultWho,
3883 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003884 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003885 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003886 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003887 if (index < 0) {
3888 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003890 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003891 if (activity.finishing) {
3892 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003894 }
3895
3896 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3897 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3898 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3899 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3900 |PendingIntent.FLAG_UPDATE_CURRENT);
3901
3902 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3903 type, packageName, activity, resultWho,
3904 requestCode, intent, resolvedType, flags);
3905 WeakReference<PendingIntentRecord> ref;
3906 ref = mIntentSenderRecords.get(key);
3907 PendingIntentRecord rec = ref != null ? ref.get() : null;
3908 if (rec != null) {
3909 if (!cancelCurrent) {
3910 if (updateCurrent) {
3911 rec.key.requestIntent.replaceExtras(intent);
3912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 return rec;
3914 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003915 rec.canceled = true;
3916 mIntentSenderRecords.remove(key);
3917 }
3918 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 return rec;
3920 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003921 rec = new PendingIntentRecord(this, key, callingUid);
3922 mIntentSenderRecords.put(key, rec.ref);
3923 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3924 if (activity.pendingResults == null) {
3925 activity.pendingResults
3926 = new HashSet<WeakReference<PendingIntentRecord>>();
3927 }
3928 activity.pendingResults.add(rec.ref);
3929 }
3930 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 }
3932
3933 public void cancelIntentSender(IIntentSender sender) {
3934 if (!(sender instanceof PendingIntentRecord)) {
3935 return;
3936 }
3937 synchronized(this) {
3938 PendingIntentRecord rec = (PendingIntentRecord)sender;
3939 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003940 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 .getPackageUid(rec.key.packageName);
3942 if (uid != Binder.getCallingUid()) {
3943 String msg = "Permission Denial: cancelIntentSender() from pid="
3944 + Binder.getCallingPid()
3945 + ", uid=" + Binder.getCallingUid()
3946 + " is not allowed to cancel packges "
3947 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003948 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 throw new SecurityException(msg);
3950 }
3951 } catch (RemoteException e) {
3952 throw new SecurityException(e);
3953 }
3954 cancelIntentSenderLocked(rec, true);
3955 }
3956 }
3957
3958 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3959 rec.canceled = true;
3960 mIntentSenderRecords.remove(rec.key);
3961 if (cleanActivity && rec.key.activity != null) {
3962 rec.key.activity.pendingResults.remove(rec.ref);
3963 }
3964 }
3965
3966 public String getPackageForIntentSender(IIntentSender pendingResult) {
3967 if (!(pendingResult instanceof PendingIntentRecord)) {
3968 return null;
3969 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003970 try {
3971 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3972 return res.key.packageName;
3973 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 }
3975 return null;
3976 }
3977
3978 public void setProcessLimit(int max) {
3979 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3980 "setProcessLimit()");
3981 mProcessLimit = max;
3982 }
3983
3984 public int getProcessLimit() {
3985 return mProcessLimit;
3986 }
3987
3988 void foregroundTokenDied(ForegroundToken token) {
3989 synchronized (ActivityManagerService.this) {
3990 synchronized (mPidsSelfLocked) {
3991 ForegroundToken cur
3992 = mForegroundProcesses.get(token.pid);
3993 if (cur != token) {
3994 return;
3995 }
3996 mForegroundProcesses.remove(token.pid);
3997 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3998 if (pr == null) {
3999 return;
4000 }
4001 pr.forcingToForeground = null;
4002 pr.foregroundServices = false;
4003 }
4004 updateOomAdjLocked();
4005 }
4006 }
4007
4008 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4009 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4010 "setProcessForeground()");
4011 synchronized(this) {
4012 boolean changed = false;
4013
4014 synchronized (mPidsSelfLocked) {
4015 ProcessRecord pr = mPidsSelfLocked.get(pid);
4016 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 return;
4019 }
4020 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4021 if (oldToken != null) {
4022 oldToken.token.unlinkToDeath(oldToken, 0);
4023 mForegroundProcesses.remove(pid);
4024 pr.forcingToForeground = null;
4025 changed = true;
4026 }
4027 if (isForeground && token != null) {
4028 ForegroundToken newToken = new ForegroundToken() {
4029 public void binderDied() {
4030 foregroundTokenDied(this);
4031 }
4032 };
4033 newToken.pid = pid;
4034 newToken.token = token;
4035 try {
4036 token.linkToDeath(newToken, 0);
4037 mForegroundProcesses.put(pid, newToken);
4038 pr.forcingToForeground = token;
4039 changed = true;
4040 } catch (RemoteException e) {
4041 // If the process died while doing this, we will later
4042 // do the cleanup with the process death link.
4043 }
4044 }
4045 }
4046
4047 if (changed) {
4048 updateOomAdjLocked();
4049 }
4050 }
4051 }
4052
4053 // =========================================================
4054 // PERMISSIONS
4055 // =========================================================
4056
4057 static class PermissionController extends IPermissionController.Stub {
4058 ActivityManagerService mActivityManagerService;
4059 PermissionController(ActivityManagerService activityManagerService) {
4060 mActivityManagerService = activityManagerService;
4061 }
4062
4063 public boolean checkPermission(String permission, int pid, int uid) {
4064 return mActivityManagerService.checkPermission(permission, pid,
4065 uid) == PackageManager.PERMISSION_GRANTED;
4066 }
4067 }
4068
4069 /**
4070 * This can be called with or without the global lock held.
4071 */
4072 int checkComponentPermission(String permission, int pid, int uid,
4073 int reqUid) {
4074 // We might be performing an operation on behalf of an indirect binder
4075 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4076 // client identity accordingly before proceeding.
4077 Identity tlsIdentity = sCallerIdentity.get();
4078 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004079 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004080 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4081 uid = tlsIdentity.uid;
4082 pid = tlsIdentity.pid;
4083 }
4084
4085 // Root, system server and our own process get to do everything.
4086 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4087 !Process.supportsProcesses()) {
4088 return PackageManager.PERMISSION_GRANTED;
4089 }
4090 // If the target requires a specific UID, always fail for others.
4091 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 return PackageManager.PERMISSION_DENIED;
4094 }
4095 if (permission == null) {
4096 return PackageManager.PERMISSION_GRANTED;
4097 }
4098 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004099 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 .checkUidPermission(permission, uid);
4101 } catch (RemoteException e) {
4102 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004103 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 }
4105 return PackageManager.PERMISSION_DENIED;
4106 }
4107
4108 /**
4109 * As the only public entry point for permissions checking, this method
4110 * can enforce the semantic that requesting a check on a null global
4111 * permission is automatically denied. (Internally a null permission
4112 * string is used when calling {@link #checkComponentPermission} in cases
4113 * when only uid-based security is needed.)
4114 *
4115 * This can be called with or without the global lock held.
4116 */
4117 public int checkPermission(String permission, int pid, int uid) {
4118 if (permission == null) {
4119 return PackageManager.PERMISSION_DENIED;
4120 }
4121 return checkComponentPermission(permission, pid, uid, -1);
4122 }
4123
4124 /**
4125 * Binder IPC calls go through the public entry point.
4126 * This can be called with or without the global lock held.
4127 */
4128 int checkCallingPermission(String permission) {
4129 return checkPermission(permission,
4130 Binder.getCallingPid(),
4131 Binder.getCallingUid());
4132 }
4133
4134 /**
4135 * This can be called with or without the global lock held.
4136 */
4137 void enforceCallingPermission(String permission, String func) {
4138 if (checkCallingPermission(permission)
4139 == PackageManager.PERMISSION_GRANTED) {
4140 return;
4141 }
4142
4143 String msg = "Permission Denial: " + func + " from pid="
4144 + Binder.getCallingPid()
4145 + ", uid=" + Binder.getCallingUid()
4146 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004147 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 throw new SecurityException(msg);
4149 }
4150
4151 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004152 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4153 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4154 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4155 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4156 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004158 // Is the component private from the target uid?
4159 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4160
4161 // Acceptable if the there is no read permission needed from the
4162 // target or the target is holding the read permission.
4163 if (!readPerm) {
4164 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004166 == PackageManager.PERMISSION_GRANTED)) {
4167 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 }
4169 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004170
4171 // Acceptable if the there is no write permission needed from the
4172 // target or the target is holding the read permission.
4173 if (!writePerm) {
4174 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004176 == PackageManager.PERMISSION_GRANTED)) {
4177 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 }
4179 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004180
4181 // Acceptable if there is a path permission matching the URI that
4182 // the target holds the permission on.
4183 PathPermission[] pps = pi.pathPermissions;
4184 if (pps != null && (!readPerm || !writePerm)) {
4185 final String path = uri.getPath();
4186 int i = pps.length;
4187 while (i > 0 && (!readPerm || !writePerm)) {
4188 i--;
4189 PathPermission pp = pps[i];
4190 if (!readPerm) {
4191 final String pprperm = pp.getReadPermission();
4192 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4193 + pprperm + " for " + pp.getPath()
4194 + ": match=" + pp.match(path)
4195 + " check=" + pm.checkUidPermission(pprperm, uid));
4196 if (pprperm != null && pp.match(path) &&
4197 (pm.checkUidPermission(pprperm, uid)
4198 == PackageManager.PERMISSION_GRANTED)) {
4199 readPerm = true;
4200 }
4201 }
4202 if (!writePerm) {
4203 final String ppwperm = pp.getWritePermission();
4204 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4205 + ppwperm + " for " + pp.getPath()
4206 + ": match=" + pp.match(path)
4207 + " check=" + pm.checkUidPermission(ppwperm, uid));
4208 if (ppwperm != null && pp.match(path) &&
4209 (pm.checkUidPermission(ppwperm, uid)
4210 == PackageManager.PERMISSION_GRANTED)) {
4211 writePerm = true;
4212 }
4213 }
4214 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 } catch (RemoteException e) {
4217 return false;
4218 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004219
4220 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 }
4222
4223 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4224 int modeFlags) {
4225 // Root gets to do everything.
4226 if (uid == 0 || !Process.supportsProcesses()) {
4227 return true;
4228 }
4229 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4230 if (perms == null) return false;
4231 UriPermission perm = perms.get(uri);
4232 if (perm == null) return false;
4233 return (modeFlags&perm.modeFlags) == modeFlags;
4234 }
4235
4236 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4237 // Another redirected-binder-call permissions check as in
4238 // {@link checkComponentPermission}.
4239 Identity tlsIdentity = sCallerIdentity.get();
4240 if (tlsIdentity != null) {
4241 uid = tlsIdentity.uid;
4242 pid = tlsIdentity.pid;
4243 }
4244
4245 // Our own process gets to do everything.
4246 if (pid == MY_PID) {
4247 return PackageManager.PERMISSION_GRANTED;
4248 }
4249 synchronized(this) {
4250 return checkUriPermissionLocked(uri, uid, modeFlags)
4251 ? PackageManager.PERMISSION_GRANTED
4252 : PackageManager.PERMISSION_DENIED;
4253 }
4254 }
4255
Dianne Hackborn39792d22010-08-19 18:01:52 -07004256 /**
4257 * Check if the targetPkg can be granted permission to access uri by
4258 * the callingUid using the given modeFlags. Throws a security exception
4259 * if callingUid is not allowed to do this. Returns the uid of the target
4260 * if the URI permission grant should be performed; returns -1 if it is not
4261 * needed (for example targetPkg already has permission to access the URI).
4262 */
4263 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4264 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4266 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4267 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004268 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 }
4270
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004272 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004273
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004274 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275
4276 // If this is not a content: uri, we can't do anything with it.
4277 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004278 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004279 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004280 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 }
4282
4283 String name = uri.getAuthority();
4284 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004285 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 if (cpr != null) {
4287 pi = cpr.info;
4288 } else {
4289 try {
4290 pi = pm.resolveContentProvider(name,
4291 PackageManager.GET_URI_PERMISSION_PATTERNS);
4292 } catch (RemoteException ex) {
4293 }
4294 }
4295 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004296 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004297 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 }
4299
4300 int targetUid;
4301 try {
4302 targetUid = pm.getPackageUid(targetPkg);
4303 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004304 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004305 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004306 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004309 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 }
4311
4312 // First... does the target actually need this permission?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004313 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004315 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004316 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004317 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 }
4319
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004320 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004321 if (!pi.grantUriPermissions) {
4322 throw new SecurityException("Provider " + pi.packageName
4323 + "/" + pi.name
4324 + " does not allow granting of Uri permissions (uri "
4325 + uri + ")");
4326 }
4327 if (pi.uriPermissionPatterns != null) {
4328 final int N = pi.uriPermissionPatterns.length;
4329 boolean allowed = false;
4330 for (int i=0; i<N; i++) {
4331 if (pi.uriPermissionPatterns[i] != null
4332 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4333 allowed = true;
4334 break;
4335 }
4336 }
4337 if (!allowed) {
4338 throw new SecurityException("Provider " + pi.packageName
4339 + "/" + pi.name
4340 + " does not allow granting of permission to path of Uri "
4341 + uri);
4342 }
4343 }
4344
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004345 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 // this uri?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004347 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4349 throw new SecurityException("Uid " + callingUid
4350 + " does not have permission to uri " + uri);
4351 }
4352 }
4353
Dianne Hackborn39792d22010-08-19 18:01:52 -07004354 return targetUid;
4355 }
4356
4357 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4358 Uri uri, int modeFlags, UriPermissionOwner owner) {
4359 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4360 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4361 if (modeFlags == 0) {
4362 return;
4363 }
4364
4365 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 // to the uri, and the target doesn't. Let's now give this to
4367 // the target.
4368
Joe Onorato8a9b2202010-02-26 18:56:32 -08004369 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004370 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 HashMap<Uri, UriPermission> targetUris
4373 = mGrantedUriPermissions.get(targetUid);
4374 if (targetUris == null) {
4375 targetUris = new HashMap<Uri, UriPermission>();
4376 mGrantedUriPermissions.put(targetUid, targetUris);
4377 }
4378
4379 UriPermission perm = targetUris.get(uri);
4380 if (perm == null) {
4381 perm = new UriPermission(targetUid, uri);
4382 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004386 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 perm.globalModeFlags |= modeFlags;
4388 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004389 perm.readOwners.add(owner);
4390 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004392 perm.writeOwners.add(owner);
4393 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 }
4395 }
4396
Dianne Hackborn39792d22010-08-19 18:01:52 -07004397 void grantUriPermissionLocked(int callingUid,
4398 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4399 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4400 if (targetUid < 0) {
4401 return;
4402 }
4403
4404 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4405 }
4406
4407 /**
4408 * Like checkGrantUriPermissionLocked, but takes an Intent.
4409 */
4410 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4411 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004412 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004413 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004414 + " from " + intent + "; flags=0x"
4415 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004418 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 }
4420 Uri data = intent.getData();
4421 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004422 return -1;
4423 }
4424 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4425 intent.getFlags());
4426 }
4427
4428 /**
4429 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4430 */
4431 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4432 String targetPkg, Intent intent, UriPermissionOwner owner) {
4433 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4434 intent.getFlags(), owner);
4435 }
4436
4437 void grantUriPermissionFromIntentLocked(int callingUid,
4438 String targetPkg, Intent intent, UriPermissionOwner owner) {
4439 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4440 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 return;
4442 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004443
4444 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 }
4446
4447 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4448 Uri uri, int modeFlags) {
4449 synchronized(this) {
4450 final ProcessRecord r = getRecordForAppLocked(caller);
4451 if (r == null) {
4452 throw new SecurityException("Unable to find app for caller "
4453 + caller
4454 + " when granting permission to uri " + uri);
4455 }
4456 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004457 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
4459 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004460 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 }
4462
4463 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4464 null);
4465 }
4466 }
4467
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004468 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4470 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4471 HashMap<Uri, UriPermission> perms
4472 = mGrantedUriPermissions.get(perm.uid);
4473 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004474 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004475 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 perms.remove(perm.uri);
4477 if (perms.size() == 0) {
4478 mGrantedUriPermissions.remove(perm.uid);
4479 }
4480 }
4481 }
4482 }
4483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4485 int modeFlags) {
4486 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4487 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4488 if (modeFlags == 0) {
4489 return;
4490 }
4491
Joe Onorato8a9b2202010-02-26 18:56:32 -08004492 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004493 "Revoking all granted permissions to " + uri);
4494
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004495 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496
4497 final String authority = uri.getAuthority();
4498 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004499 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 if (cpr != null) {
4501 pi = cpr.info;
4502 } else {
4503 try {
4504 pi = pm.resolveContentProvider(authority,
4505 PackageManager.GET_URI_PERMISSION_PATTERNS);
4506 } catch (RemoteException ex) {
4507 }
4508 }
4509 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004510 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 return;
4512 }
4513
4514 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004515 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 // Right now, if you are not the original owner of the permission,
4517 // you are not allowed to revoke it.
4518 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4519 throw new SecurityException("Uid " + callingUid
4520 + " does not have permission to uri " + uri);
4521 //}
4522 }
4523
4524 // Go through all of the permissions and remove any that match.
4525 final List<String> SEGMENTS = uri.getPathSegments();
4526 if (SEGMENTS != null) {
4527 final int NS = SEGMENTS.size();
4528 int N = mGrantedUriPermissions.size();
4529 for (int i=0; i<N; i++) {
4530 HashMap<Uri, UriPermission> perms
4531 = mGrantedUriPermissions.valueAt(i);
4532 Iterator<UriPermission> it = perms.values().iterator();
4533 toploop:
4534 while (it.hasNext()) {
4535 UriPermission perm = it.next();
4536 Uri targetUri = perm.uri;
4537 if (!authority.equals(targetUri.getAuthority())) {
4538 continue;
4539 }
4540 List<String> targetSegments = targetUri.getPathSegments();
4541 if (targetSegments == null) {
4542 continue;
4543 }
4544 if (targetSegments.size() < NS) {
4545 continue;
4546 }
4547 for (int j=0; j<NS; j++) {
4548 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4549 continue toploop;
4550 }
4551 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004552 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004553 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 perm.clearModes(modeFlags);
4555 if (perm.modeFlags == 0) {
4556 it.remove();
4557 }
4558 }
4559 if (perms.size() == 0) {
4560 mGrantedUriPermissions.remove(
4561 mGrantedUriPermissions.keyAt(i));
4562 N--;
4563 i--;
4564 }
4565 }
4566 }
4567 }
4568
4569 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4570 int modeFlags) {
4571 synchronized(this) {
4572 final ProcessRecord r = getRecordForAppLocked(caller);
4573 if (r == null) {
4574 throw new SecurityException("Unable to find app for caller "
4575 + caller
4576 + " when revoking permission to uri " + uri);
4577 }
4578 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004579 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 return;
4581 }
4582
4583 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4584 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4585 if (modeFlags == 0) {
4586 return;
4587 }
4588
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004589 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590
4591 final String authority = uri.getAuthority();
4592 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004593 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 if (cpr != null) {
4595 pi = cpr.info;
4596 } else {
4597 try {
4598 pi = pm.resolveContentProvider(authority,
4599 PackageManager.GET_URI_PERMISSION_PATTERNS);
4600 } catch (RemoteException ex) {
4601 }
4602 }
4603 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004604 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 return;
4606 }
4607
4608 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4609 }
4610 }
4611
Dianne Hackborn7e269642010-08-25 19:50:20 -07004612 @Override
4613 public IBinder newUriPermissionOwner(String name) {
4614 synchronized(this) {
4615 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4616 return owner.getExternalTokenLocked();
4617 }
4618 }
4619
4620 @Override
4621 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4622 Uri uri, int modeFlags) {
4623 synchronized(this) {
4624 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4625 if (owner == null) {
4626 throw new IllegalArgumentException("Unknown owner: " + token);
4627 }
4628 if (fromUid != Binder.getCallingUid()) {
4629 if (Binder.getCallingUid() != Process.myUid()) {
4630 // Only system code can grant URI permissions on behalf
4631 // of other users.
4632 throw new SecurityException("nice try");
4633 }
4634 }
4635 if (targetPkg == null) {
4636 throw new IllegalArgumentException("null target");
4637 }
4638 if (uri == null) {
4639 throw new IllegalArgumentException("null uri");
4640 }
4641
4642 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4643 }
4644 }
4645
4646 @Override
4647 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4648 synchronized(this) {
4649 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4650 if (owner == null) {
4651 throw new IllegalArgumentException("Unknown owner: " + token);
4652 }
4653
4654 if (uri == null) {
4655 owner.removeUriPermissionsLocked(mode);
4656 } else {
4657 owner.removeUriPermissionLocked(uri, mode);
4658 }
4659 }
4660 }
4661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4663 synchronized (this) {
4664 ProcessRecord app =
4665 who != null ? getRecordForAppLocked(who) : null;
4666 if (app == null) return;
4667
4668 Message msg = Message.obtain();
4669 msg.what = WAIT_FOR_DEBUGGER_MSG;
4670 msg.obj = app;
4671 msg.arg1 = waiting ? 1 : 0;
4672 mHandler.sendMessage(msg);
4673 }
4674 }
4675
4676 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4677 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004678 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004680 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 }
4682
4683 // =========================================================
4684 // TASK MANAGEMENT
4685 // =========================================================
4686
4687 public List getTasks(int maxNum, int flags,
4688 IThumbnailReceiver receiver) {
4689 ArrayList list = new ArrayList();
4690
4691 PendingThumbnailsRecord pending = null;
4692 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004693 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694
4695 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004696 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4698 + ", receiver=" + receiver);
4699
4700 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4701 != PackageManager.PERMISSION_GRANTED) {
4702 if (receiver != null) {
4703 // If the caller wants to wait for pending thumbnails,
4704 // it ain't gonna get them.
4705 try {
4706 receiver.finished();
4707 } catch (RemoteException ex) {
4708 }
4709 }
4710 String msg = "Permission Denial: getTasks() from pid="
4711 + Binder.getCallingPid()
4712 + ", uid=" + Binder.getCallingUid()
4713 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004714 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 throw new SecurityException(msg);
4716 }
4717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004718 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004719 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004720 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004721 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 CharSequence topDescription = null;
4723 TaskRecord curTask = null;
4724 int numActivities = 0;
4725 int numRunning = 0;
4726 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004727 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004729 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730
4731 // Initialize state for next task if needed.
4732 if (top == null ||
4733 (top.state == ActivityState.INITIALIZING
4734 && top.task == r.task)) {
4735 top = r;
4736 topDescription = r.description;
4737 curTask = r.task;
4738 numActivities = numRunning = 0;
4739 }
4740
4741 // Add 'r' into the current task.
4742 numActivities++;
4743 if (r.app != null && r.app.thread != null) {
4744 numRunning++;
4745 }
4746 if (topDescription == null) {
4747 topDescription = r.description;
4748 }
4749
Joe Onorato8a9b2202010-02-26 18:56:32 -08004750 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751 TAG, r.intent.getComponent().flattenToShortString()
4752 + ": task=" + r.task);
4753
4754 // If the next one is a different task, generate a new
4755 // TaskInfo entry for what we have.
4756 if (next == null || next.task != curTask) {
4757 ActivityManager.RunningTaskInfo ci
4758 = new ActivityManager.RunningTaskInfo();
4759 ci.id = curTask.taskId;
4760 ci.baseActivity = r.intent.getComponent();
4761 ci.topActivity = top.intent.getComponent();
4762 ci.thumbnail = top.thumbnail;
4763 ci.description = topDescription;
4764 ci.numActivities = numActivities;
4765 ci.numRunning = numRunning;
4766 //System.out.println(
4767 // "#" + maxNum + ": " + " descr=" + ci.description);
4768 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004769 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 TAG, "State=" + top.state + "Idle=" + top.idle
4771 + " app=" + top.app
4772 + " thr=" + (top.app != null ? top.app.thread : null));
4773 if (top.state == ActivityState.RESUMED
4774 || top.state == ActivityState.PAUSING) {
4775 if (top.idle && top.app != null
4776 && top.app.thread != null) {
4777 topRecord = top;
4778 topThumbnail = top.app.thread;
4779 } else {
4780 top.thumbnailNeeded = true;
4781 }
4782 }
4783 if (pending == null) {
4784 pending = new PendingThumbnailsRecord(receiver);
4785 }
4786 pending.pendingRecords.add(top);
4787 }
4788 list.add(ci);
4789 maxNum--;
4790 top = null;
4791 }
4792 }
4793
4794 if (pending != null) {
4795 mPendingThumbnails.add(pending);
4796 }
4797 }
4798
Joe Onorato8a9b2202010-02-26 18:56:32 -08004799 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800
4801 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004802 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 try {
4804 topThumbnail.requestThumbnail(topRecord);
4805 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004806 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004807 sendPendingThumbnail(null, topRecord, null, null, true);
4808 }
4809 }
4810
4811 if (pending == null && receiver != null) {
4812 // In this case all thumbnails were available and the client
4813 // is being asked to be told when the remaining ones come in...
4814 // which is unusually, since the top-most currently running
4815 // activity should never have a canned thumbnail! Oh well.
4816 try {
4817 receiver.finished();
4818 } catch (RemoteException ex) {
4819 }
4820 }
4821
4822 return list;
4823 }
4824
4825 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4826 int flags) {
4827 synchronized (this) {
4828 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4829 "getRecentTasks()");
4830
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004831 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 final int N = mRecentTasks.size();
4834 ArrayList<ActivityManager.RecentTaskInfo> res
4835 = new ArrayList<ActivityManager.RecentTaskInfo>(
4836 maxNum < N ? maxNum : N);
4837 for (int i=0; i<N && maxNum > 0; i++) {
4838 TaskRecord tr = mRecentTasks.get(i);
4839 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4840 || (tr.intent == null)
4841 || ((tr.intent.getFlags()
4842 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4843 ActivityManager.RecentTaskInfo rti
4844 = new ActivityManager.RecentTaskInfo();
4845 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4846 rti.baseIntent = new Intent(
4847 tr.intent != null ? tr.intent : tr.affinityIntent);
4848 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004849
4850 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4851 // Check whether this activity is currently available.
4852 try {
4853 if (rti.origActivity != null) {
4854 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4855 continue;
4856 }
4857 } else if (rti.baseIntent != null) {
4858 if (pm.queryIntentActivities(rti.baseIntent,
4859 null, 0) == null) {
4860 continue;
4861 }
4862 }
4863 } catch (RemoteException e) {
4864 // Will never happen.
4865 }
4866 }
4867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 res.add(rti);
4869 maxNum--;
4870 }
4871 }
4872 return res;
4873 }
4874 }
4875
4876 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4877 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004878 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 TaskRecord jt = startTask;
4880
4881 // First look backwards
4882 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004883 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 if (r.task != jt) {
4885 jt = r.task;
4886 if (affinity.equals(jt.affinity)) {
4887 return j;
4888 }
4889 }
4890 }
4891
4892 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004893 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 jt = startTask;
4895 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004896 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 if (r.task != jt) {
4898 if (affinity.equals(jt.affinity)) {
4899 return j;
4900 }
4901 jt = r.task;
4902 }
4903 }
4904
4905 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004906 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 return N-1;
4908 }
4909
4910 return -1;
4911 }
4912
4913 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004914 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 */
4916 public void moveTaskToFront(int task) {
4917 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4918 "moveTaskToFront()");
4919
4920 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004921 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4922 Binder.getCallingUid(), "Task to front")) {
4923 return;
4924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004925 final long origId = Binder.clearCallingIdentity();
4926 try {
4927 int N = mRecentTasks.size();
4928 for (int i=0; i<N; i++) {
4929 TaskRecord tr = mRecentTasks.get(i);
4930 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004931 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 return;
4933 }
4934 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004935 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4936 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004938 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 return;
4940 }
4941 }
4942 } finally {
4943 Binder.restoreCallingIdentity(origId);
4944 }
4945 }
4946 }
4947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 public void moveTaskToBack(int task) {
4949 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4950 "moveTaskToBack()");
4951
4952 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004953 if (mMainStack.mResumedActivity != null
4954 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004955 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4956 Binder.getCallingUid(), "Task to back")) {
4957 return;
4958 }
4959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004961 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 Binder.restoreCallingIdentity(origId);
4963 }
4964 }
4965
4966 /**
4967 * Moves an activity, and all of the other activities within the same task, to the bottom
4968 * of the history stack. The activity's order within the task is unchanged.
4969 *
4970 * @param token A reference to the activity we wish to move
4971 * @param nonRoot If false then this only works if the activity is the root
4972 * of a task; if true it will work for any activity in a task.
4973 * @return Returns true if the move completed, false if not.
4974 */
4975 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4976 synchronized(this) {
4977 final long origId = Binder.clearCallingIdentity();
4978 int taskId = getTaskForActivityLocked(token, !nonRoot);
4979 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004980 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 }
4982 Binder.restoreCallingIdentity(origId);
4983 }
4984 return false;
4985 }
4986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 public void moveTaskBackwards(int task) {
4988 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4989 "moveTaskBackwards()");
4990
4991 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004992 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4993 Binder.getCallingUid(), "Task backwards")) {
4994 return;
4995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 final long origId = Binder.clearCallingIdentity();
4997 moveTaskBackwardsLocked(task);
4998 Binder.restoreCallingIdentity(origId);
4999 }
5000 }
5001
5002 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005003 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 }
5005
5006 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5007 synchronized(this) {
5008 return getTaskForActivityLocked(token, onlyRoot);
5009 }
5010 }
5011
5012 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005013 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 TaskRecord lastTask = null;
5015 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005016 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 if (r == token) {
5018 if (!onlyRoot || lastTask != r.task) {
5019 return r.task.taskId;
5020 }
5021 return -1;
5022 }
5023 lastTask = r.task;
5024 }
5025
5026 return -1;
5027 }
5028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 public void finishOtherInstances(IBinder token, ComponentName className) {
5030 synchronized(this) {
5031 final long origId = Binder.clearCallingIdentity();
5032
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005033 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 TaskRecord lastTask = null;
5035 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005036 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 if (r.realActivity.equals(className)
5038 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005039 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 null, "others")) {
5041 i--;
5042 N--;
5043 }
5044 }
5045 lastTask = r.task;
5046 }
5047
5048 Binder.restoreCallingIdentity(origId);
5049 }
5050 }
5051
5052 // =========================================================
5053 // THUMBNAILS
5054 // =========================================================
5055
5056 public void reportThumbnail(IBinder token,
5057 Bitmap thumbnail, CharSequence description) {
5058 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5059 final long origId = Binder.clearCallingIdentity();
5060 sendPendingThumbnail(null, token, thumbnail, description, true);
5061 Binder.restoreCallingIdentity(origId);
5062 }
5063
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005064 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 Bitmap thumbnail, CharSequence description, boolean always) {
5066 TaskRecord task = null;
5067 ArrayList receivers = null;
5068
5069 //System.out.println("Send pending thumbnail: " + r);
5070
5071 synchronized(this) {
5072 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005073 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 if (index < 0) {
5075 return;
5076 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005077 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005078 }
5079 if (thumbnail == null) {
5080 thumbnail = r.thumbnail;
5081 description = r.description;
5082 }
5083 if (thumbnail == null && !always) {
5084 // If there is no thumbnail, and this entry is not actually
5085 // going away, then abort for now and pick up the next
5086 // thumbnail we get.
5087 return;
5088 }
5089 task = r.task;
5090
5091 int N = mPendingThumbnails.size();
5092 int i=0;
5093 while (i<N) {
5094 PendingThumbnailsRecord pr =
5095 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5096 //System.out.println("Looking in " + pr.pendingRecords);
5097 if (pr.pendingRecords.remove(r)) {
5098 if (receivers == null) {
5099 receivers = new ArrayList();
5100 }
5101 receivers.add(pr);
5102 if (pr.pendingRecords.size() == 0) {
5103 pr.finished = true;
5104 mPendingThumbnails.remove(i);
5105 N--;
5106 continue;
5107 }
5108 }
5109 i++;
5110 }
5111 }
5112
5113 if (receivers != null) {
5114 final int N = receivers.size();
5115 for (int i=0; i<N; i++) {
5116 try {
5117 PendingThumbnailsRecord pr =
5118 (PendingThumbnailsRecord)receivers.get(i);
5119 pr.receiver.newThumbnail(
5120 task != null ? task.taskId : -1, thumbnail, description);
5121 if (pr.finished) {
5122 pr.receiver.finished();
5123 }
5124 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005125 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005126 }
5127 }
5128 }
5129 }
5130
5131 // =========================================================
5132 // CONTENT PROVIDERS
5133 // =========================================================
5134
5135 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5136 List providers = null;
5137 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005138 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005140 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141 } catch (RemoteException ex) {
5142 }
5143 if (providers != null) {
5144 final int N = providers.size();
5145 for (int i=0; i<N; i++) {
5146 ProviderInfo cpi =
5147 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005148 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 if (cpr == null) {
5150 cpr = new ContentProviderRecord(cpi, app.info);
5151 mProvidersByClass.put(cpi.name, cpr);
5152 }
5153 app.pubProviders.put(cpi.name, cpr);
5154 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005155 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 }
5157 }
5158 return providers;
5159 }
5160
5161 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005162 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5164 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5165 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5166 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005167 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 return null;
5169 }
5170 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5171 cpi.exported ? -1 : cpi.applicationInfo.uid)
5172 == PackageManager.PERMISSION_GRANTED) {
5173 return null;
5174 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005175
5176 PathPermission[] pps = cpi.pathPermissions;
5177 if (pps != null) {
5178 int i = pps.length;
5179 while (i > 0) {
5180 i--;
5181 PathPermission pp = pps[i];
5182 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5183 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005184 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005185 return null;
5186 }
5187 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5188 cpi.exported ? -1 : cpi.applicationInfo.uid)
5189 == PackageManager.PERMISSION_GRANTED) {
5190 return null;
5191 }
5192 }
5193 }
5194
Dianne Hackbornb424b632010-08-18 15:59:05 -07005195 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5196 if (perms != null) {
5197 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5198 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5199 return null;
5200 }
5201 }
5202 }
5203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 String msg = "Permission Denial: opening provider " + cpi.name
5205 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5206 + ", uid=" + callingUid + ") requires "
5207 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005208 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 return msg;
5210 }
5211
5212 private final ContentProviderHolder getContentProviderImpl(
5213 IApplicationThread caller, String name) {
5214 ContentProviderRecord cpr;
5215 ProviderInfo cpi = null;
5216
5217 synchronized(this) {
5218 ProcessRecord r = null;
5219 if (caller != null) {
5220 r = getRecordForAppLocked(caller);
5221 if (r == null) {
5222 throw new SecurityException(
5223 "Unable to find app for caller " + caller
5224 + " (pid=" + Binder.getCallingPid()
5225 + ") when getting content provider " + name);
5226 }
5227 }
5228
5229 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005230 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 if (cpr != null) {
5232 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005233 String msg;
5234 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5235 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 }
5237
5238 if (r != null && cpr.canRunHere(r)) {
5239 // This provider has been published or is in the process
5240 // of being published... but it is also allowed to run
5241 // in the caller's process, so don't make a connection
5242 // and just let the caller instantiate its own instance.
5243 if (cpr.provider != null) {
5244 // don't give caller the provider object, it needs
5245 // to make its own.
5246 cpr = new ContentProviderRecord(cpr);
5247 }
5248 return cpr;
5249 }
5250
5251 final long origId = Binder.clearCallingIdentity();
5252
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005253 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 // return it right away.
5255 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005256 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005257 "Adding provider requested by "
5258 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005259 + cpr.info.processName);
5260 Integer cnt = r.conProviders.get(cpr);
5261 if (cnt == null) {
5262 r.conProviders.put(cpr, new Integer(1));
5263 } else {
5264 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005267 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5268 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005269 // make sure to count it as being accessed and thus
5270 // back up on the LRU list. This is good because
5271 // content providers are often expensive to start.
5272 updateLruProcessLocked(cpr.app, false, true);
5273 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005274 } else {
5275 cpr.externals++;
5276 }
5277
5278 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 updateOomAdjLocked(cpr.app);
5280 }
5281
5282 Binder.restoreCallingIdentity(origId);
5283
5284 } else {
5285 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005286 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005287 resolveContentProvider(name,
5288 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 } catch (RemoteException ex) {
5290 }
5291 if (cpi == null) {
5292 return null;
5293 }
5294
Dianne Hackbornb424b632010-08-18 15:59:05 -07005295 String msg;
5296 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5297 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 }
5299
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005300 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005301 && !cpi.processName.equals("system")) {
5302 // If this content provider does not run in the system
5303 // process, and the system is not yet ready to run other
5304 // processes, then fail fast instead of hanging.
5305 throw new IllegalArgumentException(
5306 "Attempt to launch content provider before system ready");
5307 }
5308
Dianne Hackborn860755f2010-06-03 18:47:52 -07005309 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 final boolean firstClass = cpr == null;
5311 if (firstClass) {
5312 try {
5313 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005314 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 getApplicationInfo(
5316 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005317 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005319 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 + cpi.name);
5321 return null;
5322 }
5323 cpr = new ContentProviderRecord(cpi, ai);
5324 } catch (RemoteException ex) {
5325 // pm is in same process, this will never happen.
5326 }
5327 }
5328
5329 if (r != null && cpr.canRunHere(r)) {
5330 // If this is a multiprocess provider, then just return its
5331 // info and allow the caller to instantiate it. Only do
5332 // this if the provider is the same user as the caller's
5333 // process, or can run as root (so can be in any process).
5334 return cpr;
5335 }
5336
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005337 if (DEBUG_PROVIDER) {
5338 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005339 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005340 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 }
5342
5343 // This is single process, and our app is now connecting to it.
5344 // See if we are already in the process of launching this
5345 // provider.
5346 final int N = mLaunchingProviders.size();
5347 int i;
5348 for (i=0; i<N; i++) {
5349 if (mLaunchingProviders.get(i) == cpr) {
5350 break;
5351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 }
5353
5354 // If the provider is not already being launched, then get it
5355 // started.
5356 if (i >= N) {
5357 final long origId = Binder.clearCallingIdentity();
5358 ProcessRecord proc = startProcessLocked(cpi.processName,
5359 cpr.appInfo, false, 0, "content provider",
5360 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005361 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005363 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 + cpi.applicationInfo.packageName + "/"
5365 + cpi.applicationInfo.uid + " for provider "
5366 + name + ": process is bad");
5367 return null;
5368 }
5369 cpr.launchingApp = proc;
5370 mLaunchingProviders.add(cpr);
5371 Binder.restoreCallingIdentity(origId);
5372 }
5373
5374 // Make sure the provider is published (the same provider class
5375 // may be published under multiple names).
5376 if (firstClass) {
5377 mProvidersByClass.put(cpi.name, cpr);
5378 }
5379 mProvidersByName.put(name, cpr);
5380
5381 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005382 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005383 "Adding provider requested by "
5384 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005385 + cpr.info.processName);
5386 Integer cnt = r.conProviders.get(cpr);
5387 if (cnt == null) {
5388 r.conProviders.put(cpr, new Integer(1));
5389 } else {
5390 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 cpr.clients.add(r);
5393 } else {
5394 cpr.externals++;
5395 }
5396 }
5397 }
5398
5399 // Wait for the provider to be published...
5400 synchronized (cpr) {
5401 while (cpr.provider == null) {
5402 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005403 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 + cpi.applicationInfo.packageName + "/"
5405 + cpi.applicationInfo.uid + " for provider "
5406 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005407 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 cpi.applicationInfo.packageName,
5409 cpi.applicationInfo.uid, name);
5410 return null;
5411 }
5412 try {
5413 cpr.wait();
5414 } catch (InterruptedException ex) {
5415 }
5416 }
5417 }
5418 return cpr;
5419 }
5420
5421 public final ContentProviderHolder getContentProvider(
5422 IApplicationThread caller, String name) {
5423 if (caller == null) {
5424 String msg = "null IApplicationThread when getting content provider "
5425 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 throw new SecurityException(msg);
5428 }
5429
5430 return getContentProviderImpl(caller, name);
5431 }
5432
5433 private ContentProviderHolder getContentProviderExternal(String name) {
5434 return getContentProviderImpl(null, name);
5435 }
5436
5437 /**
5438 * Drop a content provider from a ProcessRecord's bookkeeping
5439 * @param cpr
5440 */
5441 public void removeContentProvider(IApplicationThread caller, String name) {
5442 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005443 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005444 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005445 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005446 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005447 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 return;
5449 }
5450 final ProcessRecord r = getRecordForAppLocked(caller);
5451 if (r == null) {
5452 throw new SecurityException(
5453 "Unable to find app for caller " + caller +
5454 " when removing content provider " + name);
5455 }
5456 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005457 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005458 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005459 + r.info.processName + " from process "
5460 + localCpr.appInfo.processName);
5461 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005463 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005464 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 return;
5466 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005467 Integer cnt = r.conProviders.get(localCpr);
5468 if (cnt == null || cnt.intValue() <= 1) {
5469 localCpr.clients.remove(r);
5470 r.conProviders.remove(localCpr);
5471 } else {
5472 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 }
5475 updateOomAdjLocked();
5476 }
5477 }
5478
5479 private void removeContentProviderExternal(String name) {
5480 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005481 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 if(cpr == null) {
5483 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005484 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005485 return;
5486 }
5487
5488 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005489 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 localCpr.externals--;
5491 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005492 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 }
5494 updateOomAdjLocked();
5495 }
5496 }
5497
5498 public final void publishContentProviders(IApplicationThread caller,
5499 List<ContentProviderHolder> providers) {
5500 if (providers == null) {
5501 return;
5502 }
5503
5504 synchronized(this) {
5505 final ProcessRecord r = getRecordForAppLocked(caller);
5506 if (r == null) {
5507 throw new SecurityException(
5508 "Unable to find app for caller " + caller
5509 + " (pid=" + Binder.getCallingPid()
5510 + ") when publishing content providers");
5511 }
5512
5513 final long origId = Binder.clearCallingIdentity();
5514
5515 final int N = providers.size();
5516 for (int i=0; i<N; i++) {
5517 ContentProviderHolder src = providers.get(i);
5518 if (src == null || src.info == null || src.provider == null) {
5519 continue;
5520 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005521 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 if (dst != null) {
5523 mProvidersByClass.put(dst.info.name, dst);
5524 String names[] = dst.info.authority.split(";");
5525 for (int j = 0; j < names.length; j++) {
5526 mProvidersByName.put(names[j], dst);
5527 }
5528
5529 int NL = mLaunchingProviders.size();
5530 int j;
5531 for (j=0; j<NL; j++) {
5532 if (mLaunchingProviders.get(j) == dst) {
5533 mLaunchingProviders.remove(j);
5534 j--;
5535 NL--;
5536 }
5537 }
5538 synchronized (dst) {
5539 dst.provider = src.provider;
5540 dst.app = r;
5541 dst.notifyAll();
5542 }
5543 updateOomAdjLocked(r);
5544 }
5545 }
5546
5547 Binder.restoreCallingIdentity(origId);
5548 }
5549 }
5550
5551 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005552 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005553 synchronized (mSelf) {
5554 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5555 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005556 if (providers != null) {
5557 for (int i=providers.size()-1; i>=0; i--) {
5558 ProviderInfo pi = (ProviderInfo)providers.get(i);
5559 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5560 Slog.w(TAG, "Not installing system proc provider " + pi.name
5561 + ": not system .apk");
5562 providers.remove(i);
5563 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005564 }
5565 }
5566 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005567 if (providers != null) {
5568 mSystemThread.installSystemProviders(providers);
5569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 }
5571
Dianne Hackborn8313fc72010-09-26 18:34:53 -07005572 /**
5573 * Allows app to retrieve the MIME type of a URI without having permission
5574 * to access its content provider.
5575 *
5576 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5577 *
5578 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5579 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5580 */
5581 public String getProviderMimeType(Uri uri) {
5582 final String name = uri.getAuthority();
5583 final long ident = Binder.clearCallingIdentity();
5584 ContentProviderHolder holder = null;
5585
5586 try {
5587 holder = getContentProviderExternal(name);
5588 if (holder != null) {
5589 return holder.provider.getType(uri);
5590 }
5591 } catch (RemoteException e) {
5592 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5593 return null;
5594 } finally {
5595 if (holder != null) {
5596 removeContentProviderExternal(name);
5597 }
5598 Binder.restoreCallingIdentity(ident);
5599 }
5600
5601 return null;
5602 }
5603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005604 // =========================================================
5605 // GLOBAL MANAGEMENT
5606 // =========================================================
5607
5608 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5609 ApplicationInfo info, String customProcess) {
5610 String proc = customProcess != null ? customProcess : info.processName;
5611 BatteryStatsImpl.Uid.Proc ps = null;
5612 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5613 synchronized (stats) {
5614 ps = stats.getProcessStatsLocked(info.uid, proc);
5615 }
5616 return new ProcessRecord(ps, thread, info, proc);
5617 }
5618
5619 final ProcessRecord addAppLocked(ApplicationInfo info) {
5620 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5621
5622 if (app == null) {
5623 app = newProcessRecordLocked(null, info, null);
5624 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005625 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 }
5627
5628 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5629 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5630 app.persistent = true;
5631 app.maxAdj = CORE_SERVER_ADJ;
5632 }
5633 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5634 mPersistentStartingProcesses.add(app);
5635 startProcessLocked(app, "added application", app.processName);
5636 }
5637
5638 return app;
5639 }
5640
5641 public void unhandledBack() {
5642 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5643 "unhandledBack()");
5644
5645 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005646 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005647 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 TAG, "Performing unhandledBack(): stack size = " + count);
5649 if (count > 1) {
5650 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005651 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5653 Binder.restoreCallingIdentity(origId);
5654 }
5655 }
5656 }
5657
5658 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5659 String name = uri.getAuthority();
5660 ContentProviderHolder cph = getContentProviderExternal(name);
5661 ParcelFileDescriptor pfd = null;
5662 if (cph != null) {
5663 // We record the binder invoker's uid in thread-local storage before
5664 // going to the content provider to open the file. Later, in the code
5665 // that handles all permissions checks, we look for this uid and use
5666 // that rather than the Activity Manager's own uid. The effect is that
5667 // we do the check against the caller's permissions even though it looks
5668 // to the content provider like the Activity Manager itself is making
5669 // the request.
5670 sCallerIdentity.set(new Identity(
5671 Binder.getCallingPid(), Binder.getCallingUid()));
5672 try {
5673 pfd = cph.provider.openFile(uri, "r");
5674 } catch (FileNotFoundException e) {
5675 // do nothing; pfd will be returned null
5676 } finally {
5677 // Ensure that whatever happens, we clean up the identity state
5678 sCallerIdentity.remove();
5679 }
5680
5681 // We've got the fd now, so we're done with the provider.
5682 removeContentProviderExternal(name);
5683 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005684 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 }
5686 return pfd;
5687 }
5688
5689 public void goingToSleep() {
5690 synchronized(this) {
5691 mSleeping = true;
5692 mWindowManager.setEventDispatching(false);
5693
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005694 if (mMainStack.mResumedActivity != null) {
5695 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005697 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005699
5700 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005701 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005702 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5703 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005704 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005705 }
5706 }
5707
Dianne Hackborn55280a92009-05-07 15:53:46 -07005708 public boolean shutdown(int timeout) {
5709 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5710 != PackageManager.PERMISSION_GRANTED) {
5711 throw new SecurityException("Requires permission "
5712 + android.Manifest.permission.SHUTDOWN);
5713 }
5714
5715 boolean timedout = false;
5716
5717 synchronized(this) {
5718 mShuttingDown = true;
5719 mWindowManager.setEventDispatching(false);
5720
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005721 if (mMainStack.mResumedActivity != null) {
5722 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005723 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005724 while (mMainStack.mResumedActivity != null
5725 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005726 long delay = endTime - System.currentTimeMillis();
5727 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005728 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005729 timedout = true;
5730 break;
5731 }
5732 try {
5733 this.wait();
5734 } catch (InterruptedException e) {
5735 }
5736 }
5737 }
5738 }
5739
5740 mUsageStatsService.shutdown();
5741 mBatteryStatsService.shutdown();
5742
5743 return timedout;
5744 }
5745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 public void wakingUp() {
5747 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005748 if (mMainStack.mGoingToSleep.isHeld()) {
5749 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 }
5751 mWindowManager.setEventDispatching(true);
5752 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005753 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 }
5755 }
5756
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005757 public void stopAppSwitches() {
5758 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5759 != PackageManager.PERMISSION_GRANTED) {
5760 throw new SecurityException("Requires permission "
5761 + android.Manifest.permission.STOP_APP_SWITCHES);
5762 }
5763
5764 synchronized(this) {
5765 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5766 + APP_SWITCH_DELAY_TIME;
5767 mDidAppSwitch = false;
5768 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5769 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5770 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5771 }
5772 }
5773
5774 public void resumeAppSwitches() {
5775 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5776 != PackageManager.PERMISSION_GRANTED) {
5777 throw new SecurityException("Requires permission "
5778 + android.Manifest.permission.STOP_APP_SWITCHES);
5779 }
5780
5781 synchronized(this) {
5782 // Note that we don't execute any pending app switches... we will
5783 // let those wait until either the timeout, or the next start
5784 // activity request.
5785 mAppSwitchesAllowedTime = 0;
5786 }
5787 }
5788
5789 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5790 String name) {
5791 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5792 return true;
5793 }
5794
5795 final int perm = checkComponentPermission(
5796 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5797 callingUid, -1);
5798 if (perm == PackageManager.PERMISSION_GRANTED) {
5799 return true;
5800 }
5801
Joe Onorato8a9b2202010-02-26 18:56:32 -08005802 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005803 return false;
5804 }
5805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 public void setDebugApp(String packageName, boolean waitForDebugger,
5807 boolean persistent) {
5808 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5809 "setDebugApp()");
5810
5811 // Note that this is not really thread safe if there are multiple
5812 // callers into it at the same time, but that's not a situation we
5813 // care about.
5814 if (persistent) {
5815 final ContentResolver resolver = mContext.getContentResolver();
5816 Settings.System.putString(
5817 resolver, Settings.System.DEBUG_APP,
5818 packageName);
5819 Settings.System.putInt(
5820 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5821 waitForDebugger ? 1 : 0);
5822 }
5823
5824 synchronized (this) {
5825 if (!persistent) {
5826 mOrigDebugApp = mDebugApp;
5827 mOrigWaitForDebugger = mWaitForDebugger;
5828 }
5829 mDebugApp = packageName;
5830 mWaitForDebugger = waitForDebugger;
5831 mDebugTransient = !persistent;
5832 if (packageName != null) {
5833 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005834 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005835 Binder.restoreCallingIdentity(origId);
5836 }
5837 }
5838 }
5839
5840 public void setAlwaysFinish(boolean enabled) {
5841 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5842 "setAlwaysFinish()");
5843
5844 Settings.System.putInt(
5845 mContext.getContentResolver(),
5846 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5847
5848 synchronized (this) {
5849 mAlwaysFinishActivities = enabled;
5850 }
5851 }
5852
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005853 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005855 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005857 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 }
5859 }
5860
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005861 public boolean isUserAMonkey() {
5862 // For now the fact that there is a controller implies
5863 // we have a monkey.
5864 synchronized (this) {
5865 return mController != null;
5866 }
5867 }
5868
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005869 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005870 synchronized (this) {
5871 mWatchers.register(watcher);
5872 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005873 }
5874
5875 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005876 synchronized (this) {
5877 mWatchers.unregister(watcher);
5878 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005879 }
5880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 public final void enterSafeMode() {
5882 synchronized(this) {
5883 // It only makes sense to do this before the system is ready
5884 // and started launching other packages.
5885 if (!mSystemReady) {
5886 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005887 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 } catch (RemoteException e) {
5889 }
5890
5891 View v = LayoutInflater.from(mContext).inflate(
5892 com.android.internal.R.layout.safe_mode, null);
5893 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown2d3f1592010-10-15 00:54:27 -07005894 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5896 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5897 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5898 lp.format = v.getBackground().getOpacity();
5899 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5900 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5901 ((WindowManager)mContext.getSystemService(
5902 Context.WINDOW_SERVICE)).addView(v, lp);
5903 }
5904 }
5905 }
5906
5907 public void noteWakeupAlarm(IIntentSender sender) {
5908 if (!(sender instanceof PendingIntentRecord)) {
5909 return;
5910 }
5911 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5912 synchronized (stats) {
5913 if (mBatteryStatsService.isOnBattery()) {
5914 mBatteryStatsService.enforceCallingPermission();
5915 PendingIntentRecord rec = (PendingIntentRecord)sender;
5916 int MY_UID = Binder.getCallingUid();
5917 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5918 BatteryStatsImpl.Uid.Pkg pkg =
5919 stats.getPackageStatsLocked(uid, rec.key.packageName);
5920 pkg.incWakeupsLocked();
5921 }
5922 }
5923 }
5924
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005925 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005927 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005928 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005929 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 // XXX Note: don't acquire main activity lock here, because the window
5931 // manager calls in with its locks held.
5932
5933 boolean killed = false;
5934 synchronized (mPidsSelfLocked) {
5935 int[] types = new int[pids.length];
5936 int worstType = 0;
5937 for (int i=0; i<pids.length; i++) {
5938 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5939 if (proc != null) {
5940 int type = proc.setAdj;
5941 types[i] = type;
5942 if (type > worstType) {
5943 worstType = type;
5944 }
5945 }
5946 }
5947
5948 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5949 // then constrain it so we will kill all hidden procs.
5950 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5951 worstType = HIDDEN_APP_MIN_ADJ;
5952 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005953 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 for (int i=0; i<pids.length; i++) {
5955 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5956 if (proc == null) {
5957 continue;
5958 }
5959 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005960 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005961 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005962 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5963 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005965 proc.killedBackground = true;
5966 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005967 }
5968 }
5969 }
5970 return killed;
5971 }
5972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005973 public final void startRunning(String pkg, String cls, String action,
5974 String data) {
5975 synchronized(this) {
5976 if (mStartRunning) {
5977 return;
5978 }
5979 mStartRunning = true;
5980 mTopComponent = pkg != null && cls != null
5981 ? new ComponentName(pkg, cls) : null;
5982 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5983 mTopData = data;
5984 if (!mSystemReady) {
5985 return;
5986 }
5987 }
5988
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005989 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 }
5991
5992 private void retrieveSettings() {
5993 final ContentResolver resolver = mContext.getContentResolver();
5994 String debugApp = Settings.System.getString(
5995 resolver, Settings.System.DEBUG_APP);
5996 boolean waitForDebugger = Settings.System.getInt(
5997 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5998 boolean alwaysFinishActivities = Settings.System.getInt(
5999 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6000
6001 Configuration configuration = new Configuration();
6002 Settings.System.getConfiguration(resolver, configuration);
6003
6004 synchronized (this) {
6005 mDebugApp = mOrigDebugApp = debugApp;
6006 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6007 mAlwaysFinishActivities = alwaysFinishActivities;
6008 // This happens before any activities are started, so we can
6009 // change mConfiguration in-place.
6010 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006011 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006012 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 }
6014 }
6015
6016 public boolean testIsSystemReady() {
6017 // no need to synchronize(this) just to read & return the value
6018 return mSystemReady;
6019 }
6020
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006021 private static File getCalledPreBootReceiversFile() {
6022 File dataDir = Environment.getDataDirectory();
6023 File systemDir = new File(dataDir, "system");
6024 File fname = new File(systemDir, "called_pre_boots.dat");
6025 return fname;
6026 }
6027
6028 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6029 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6030 File file = getCalledPreBootReceiversFile();
6031 FileInputStream fis = null;
6032 try {
6033 fis = new FileInputStream(file);
6034 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6035 int vers = dis.readInt();
6036 String codename = dis.readUTF();
6037 if (vers == android.os.Build.VERSION.SDK_INT
6038 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6039 int num = dis.readInt();
6040 while (num > 0) {
6041 num--;
6042 String pkg = dis.readUTF();
6043 String cls = dis.readUTF();
6044 lastDoneReceivers.add(new ComponentName(pkg, cls));
6045 }
6046 }
6047 } catch (FileNotFoundException e) {
6048 } catch (IOException e) {
6049 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6050 } finally {
6051 if (fis != null) {
6052 try {
6053 fis.close();
6054 } catch (IOException e) {
6055 }
6056 }
6057 }
6058 return lastDoneReceivers;
6059 }
6060
6061 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6062 File file = getCalledPreBootReceiversFile();
6063 FileOutputStream fos = null;
6064 DataOutputStream dos = null;
6065 try {
6066 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6067 fos = new FileOutputStream(file);
6068 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6069 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6070 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6071 dos.writeInt(list.size());
6072 for (int i=0; i<list.size(); i++) {
6073 dos.writeUTF(list.get(i).getPackageName());
6074 dos.writeUTF(list.get(i).getClassName());
6075 }
6076 } catch (IOException e) {
6077 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6078 file.delete();
6079 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006080 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006081 if (dos != null) {
6082 try {
6083 dos.close();
6084 } catch (IOException e) {
6085 // TODO Auto-generated catch block
6086 e.printStackTrace();
6087 }
6088 }
6089 }
6090 }
6091
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006092 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 // In the simulator, startRunning will never have been called, which
6094 // normally sets a few crucial variables. Do it here instead.
6095 if (!Process.supportsProcesses()) {
6096 mStartRunning = true;
6097 mTopAction = Intent.ACTION_MAIN;
6098 }
6099
6100 synchronized(this) {
6101 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006102 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006103 return;
6104 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006105
6106 // Check to see if there are any update receivers to run.
6107 if (!mDidUpdate) {
6108 if (mWaitingUpdate) {
6109 return;
6110 }
6111 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6112 List<ResolveInfo> ris = null;
6113 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006114 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006115 intent, null, 0);
6116 } catch (RemoteException e) {
6117 }
6118 if (ris != null) {
6119 for (int i=ris.size()-1; i>=0; i--) {
6120 if ((ris.get(i).activityInfo.applicationInfo.flags
6121 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6122 ris.remove(i);
6123 }
6124 }
6125 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006126
6127 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6128
6129 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006130 for (int i=0; i<ris.size(); i++) {
6131 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006132 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6133 if (lastDoneReceivers.contains(comp)) {
6134 ris.remove(i);
6135 i--;
6136 }
6137 }
6138
6139 for (int i=0; i<ris.size(); i++) {
6140 ActivityInfo ai = ris.get(i).activityInfo;
6141 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6142 doneReceivers.add(comp);
6143 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006144 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006145 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006146 finisher = new IIntentReceiver.Stub() {
6147 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006148 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006149 boolean sticky) {
6150 // The raw IIntentReceiver interface is called
6151 // with the AM lock held, so redispatch to
6152 // execute our code without the lock.
6153 mHandler.post(new Runnable() {
6154 public void run() {
6155 synchronized (ActivityManagerService.this) {
6156 mDidUpdate = true;
6157 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006158 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006159 systemReady(goingCallback);
6160 }
6161 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006162 }
6163 };
6164 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006165 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006166 broadcastIntentLocked(null, null, intent, null, finisher,
6167 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006168 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006169 mWaitingUpdate = true;
6170 }
6171 }
6172 }
6173 if (mWaitingUpdate) {
6174 return;
6175 }
6176 mDidUpdate = true;
6177 }
6178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 mSystemReady = true;
6180 if (!mStartRunning) {
6181 return;
6182 }
6183 }
6184
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006185 ArrayList<ProcessRecord> procsToKill = null;
6186 synchronized(mPidsSelfLocked) {
6187 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6188 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6189 if (!isAllowedWhileBooting(proc.info)){
6190 if (procsToKill == null) {
6191 procsToKill = new ArrayList<ProcessRecord>();
6192 }
6193 procsToKill.add(proc);
6194 }
6195 }
6196 }
6197
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006198 synchronized(this) {
6199 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006200 for (int i=procsToKill.size()-1; i>=0; i--) {
6201 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006202 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006203 removeProcessLocked(proc, true);
6204 }
6205 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006206
6207 // Now that we have cleaned up any update processes, we
6208 // are ready to start launching real processes and know that
6209 // we won't trample on them any more.
6210 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006211 }
6212
Joe Onorato8a9b2202010-02-26 18:56:32 -08006213 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006214 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 SystemClock.uptimeMillis());
6216
6217 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006218 // Make sure we have no pre-ready processes sitting around.
6219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6221 ResolveInfo ri = mContext.getPackageManager()
6222 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006223 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 CharSequence errorMsg = null;
6225 if (ri != null) {
6226 ActivityInfo ai = ri.activityInfo;
6227 ApplicationInfo app = ai.applicationInfo;
6228 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6229 mTopAction = Intent.ACTION_FACTORY_TEST;
6230 mTopData = null;
6231 mTopComponent = new ComponentName(app.packageName,
6232 ai.name);
6233 } else {
6234 errorMsg = mContext.getResources().getText(
6235 com.android.internal.R.string.factorytest_not_system);
6236 }
6237 } else {
6238 errorMsg = mContext.getResources().getText(
6239 com.android.internal.R.string.factorytest_no_action);
6240 }
6241 if (errorMsg != null) {
6242 mTopAction = null;
6243 mTopData = null;
6244 mTopComponent = null;
6245 Message msg = Message.obtain();
6246 msg.what = SHOW_FACTORY_ERROR_MSG;
6247 msg.getData().putCharSequence("msg", errorMsg);
6248 mHandler.sendMessage(msg);
6249 }
6250 }
6251 }
6252
6253 retrieveSettings();
6254
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006255 if (goingCallback != null) goingCallback.run();
6256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 synchronized (this) {
6258 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6259 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006260 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006261 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262 if (apps != null) {
6263 int N = apps.size();
6264 int i;
6265 for (i=0; i<N; i++) {
6266 ApplicationInfo info
6267 = (ApplicationInfo)apps.get(i);
6268 if (info != null &&
6269 !info.packageName.equals("android")) {
6270 addAppLocked(info);
6271 }
6272 }
6273 }
6274 } catch (RemoteException ex) {
6275 // pm is in same process, this will never happen.
6276 }
6277 }
6278
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006279 // Start up initial activity.
6280 mBooting = true;
6281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006283 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006284 Message msg = Message.obtain();
6285 msg.what = SHOW_UID_ERROR_MSG;
6286 mHandler.sendMessage(msg);
6287 }
6288 } catch (RemoteException e) {
6289 }
6290
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006291 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 }
6293 }
6294
Dan Egnorb7f03672009-12-09 16:22:32 -08006295 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006296 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006298 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006299 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 startAppProblemLocked(app);
6301 app.stopFreezingAllLocked();
6302 return handleAppCrashLocked(app);
6303 }
6304
Dan Egnorb7f03672009-12-09 16:22:32 -08006305 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006306 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006307 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006308 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006309 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6310 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006311 startAppProblemLocked(app);
6312 app.stopFreezingAllLocked();
6313 }
6314
6315 /**
6316 * Generate a process error record, suitable for attachment to a ProcessRecord.
6317 *
6318 * @param app The ProcessRecord in which the error occurred.
6319 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6320 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006321 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 * @param shortMsg Short message describing the crash.
6323 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006324 * @param stackTrace Full crash stack trace, may be null.
6325 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006326 * @return Returns a fully-formed AppErrorStateInfo record.
6327 */
6328 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006329 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 report.condition = condition;
6333 report.processName = app.processName;
6334 report.pid = app.pid;
6335 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006336 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337 report.shortMsg = shortMsg;
6338 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006339 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006340
6341 return report;
6342 }
6343
Dan Egnor42471dd2010-01-07 17:25:22 -08006344 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006345 synchronized (this) {
6346 app.crashing = false;
6347 app.crashingReport = null;
6348 app.notResponding = false;
6349 app.notRespondingReport = null;
6350 if (app.anrDialog == fromDialog) {
6351 app.anrDialog = null;
6352 }
6353 if (app.waitDialog == fromDialog) {
6354 app.waitDialog = null;
6355 }
6356 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006357 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006358 Slog.i(ActivityManagerService.TAG, "Killing "
6359 + app.processName + " (pid=" + app.pid + "): user's request");
6360 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6361 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 Process.killProcess(app.pid);
6363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 }
6365 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006366
Dan Egnorb7f03672009-12-09 16:22:32 -08006367 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368 long now = SystemClock.uptimeMillis();
6369
6370 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6371 app.info.uid);
6372 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6373 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006374 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006376 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 app.info.processName, app.info.uid);
6378 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006379 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6380 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006382 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006384 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 }
6386 }
6387 if (!app.persistent) {
6388 // We don't want to start this process again until the user
6389 // explicitly does so... but for persistent process, we really
6390 // need to keep it running. If a persistent process is actually
6391 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006392 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 app.info.processName);
6394 mBadProcesses.put(app.info.processName, app.info.uid, now);
6395 app.bad = true;
6396 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6397 app.removed = true;
6398 removeProcessLocked(app, false);
6399 return false;
6400 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006401 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006402 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006403 if (r.app == app) {
6404 // If the top running activity is from this crashing
6405 // process, then terminate it to avoid getting in a loop.
6406 Slog.w(TAG, " Force finishing activity "
6407 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006408 int index = mMainStack.indexOfTokenLocked(r);
6409 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006410 Activity.RESULT_CANCELED, null, "crashed");
6411 // Also terminate an activities below it that aren't yet
6412 // stopped, to avoid a situation where one will get
6413 // re-start our crashing activity once it gets resumed again.
6414 index--;
6415 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006416 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006417 if (r.state == ActivityState.RESUMED
6418 || r.state == ActivityState.PAUSING
6419 || r.state == ActivityState.PAUSED) {
6420 if (!r.isHomeActivity) {
6421 Slog.w(TAG, " Force finishing activity "
6422 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006423 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006424 Activity.RESULT_CANCELED, null, "crashed");
6425 }
6426 }
6427 }
6428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 }
6430
6431 // Bump up the crash count of any services currently running in the proc.
6432 if (app.services.size() != 0) {
6433 // Any services running in the application need to be placed
6434 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006435 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006437 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 sr.crashCount++;
6439 }
6440 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006441
6442 // If the crashing process is what we consider to be the "home process" and it has been
6443 // replaced by a third-party app, clear the package preferred activities from packages
6444 // with a home activity running in the process to prevent a repeatedly crashing app
6445 // from blocking the user to manually clear the list.
6446 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6447 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6448 Iterator it = mHomeProcess.activities.iterator();
6449 while (it.hasNext()) {
Jean-Baptiste Queru1ca94792010-07-30 09:30:31 -07006450 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006451 if (r.isHomeActivity) {
6452 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6453 try {
6454 ActivityThread.getPackageManager()
6455 .clearPackagePreferredActivities(r.packageName);
6456 } catch (RemoteException c) {
6457 // pm is in same process, this will never happen.
6458 }
6459 }
6460 }
6461 }
6462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6464 return true;
6465 }
6466
6467 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006468 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6469 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 skipCurrentReceiverLocked(app);
6471 }
6472
6473 void skipCurrentReceiverLocked(ProcessRecord app) {
6474 boolean reschedule = false;
6475 BroadcastRecord r = app.curReceiver;
6476 if (r != null) {
6477 // The current broadcast is waiting for this app's receiver
6478 // to be finished. Looks like that's not going to happen, so
6479 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006480 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6482 r.resultExtras, r.resultAbort, true);
6483 reschedule = true;
6484 }
6485 r = mPendingBroadcast;
6486 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006487 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006489 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6491 r.resultExtras, r.resultAbort, true);
6492 reschedule = true;
6493 }
6494 if (reschedule) {
6495 scheduleBroadcastsLocked();
6496 }
6497 }
6498
Dan Egnor60d87622009-12-16 16:32:58 -08006499 /**
6500 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6501 * The application process will exit immediately after this call returns.
6502 * @param app object of the crashing app, null for the system server
6503 * @param crashInfo describing the exception
6504 */
6505 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6506 ProcessRecord r = findAppProcess(app);
6507
6508 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6509 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006510 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006511 crashInfo.exceptionClassName,
6512 crashInfo.exceptionMessage,
6513 crashInfo.throwFileName,
6514 crashInfo.throwLineNumber);
6515
Dan Egnor42471dd2010-01-07 17:25:22 -08006516 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006517
6518 crashApplication(r, crashInfo);
6519 }
6520
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006521 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006522 IBinder app,
6523 int violationMask,
6524 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006525 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006526
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006527 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006528 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006529 boolean logIt = true;
6530 synchronized (mAlreadyLoggedViolatedStacks) {
6531 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6532 logIt = false;
6533 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006534 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006535 // the relative pain numbers, without logging all
6536 // the stack traces repeatedly. We'd want to do
6537 // likewise in the client code, which also does
6538 // dup suppression, before the Binder call.
6539 } else {
6540 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6541 mAlreadyLoggedViolatedStacks.clear();
6542 }
6543 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6544 }
6545 }
6546 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006547 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006548 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006549 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006550
6551 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6552 AppErrorResult result = new AppErrorResult();
6553 synchronized (this) {
6554 final long origId = Binder.clearCallingIdentity();
6555
6556 Message msg = Message.obtain();
6557 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6558 HashMap<String, Object> data = new HashMap<String, Object>();
6559 data.put("result", result);
6560 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006561 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006562 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006563 msg.obj = data;
6564 mHandler.sendMessage(msg);
6565
6566 Binder.restoreCallingIdentity(origId);
6567 }
6568 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006569 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006570 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006571 }
6572
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006573 // Depending on the policy in effect, there could be a bunch of
6574 // these in quick succession so we try to batch these together to
6575 // minimize disk writes, number of dropbox entries, and maximize
6576 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006577 private void logStrictModeViolationToDropBox(
6578 ProcessRecord process,
6579 StrictMode.ViolationInfo info) {
6580 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006581 return;
6582 }
6583 final boolean isSystemApp = process == null ||
6584 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6585 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6586 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6587 final DropBoxManager dbox = (DropBoxManager)
6588 mContext.getSystemService(Context.DROPBOX_SERVICE);
6589
6590 // Exit early if the dropbox isn't configured to accept this report type.
6591 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6592
6593 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006594 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006595 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6596 synchronized (sb) {
6597 bufferWasEmpty = sb.length() == 0;
6598 appendDropBoxProcessHeaders(process, sb);
6599 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6600 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006601 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6602 if (info.violationNumThisLoop != 0) {
6603 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6604 }
6605 if (info != null && info.durationMillis != -1) {
6606 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006607 }
6608 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006609 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6610 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006611 }
6612 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006613
6614 // Only buffer up to ~64k. Various logging bits truncate
6615 // things at 128k.
6616 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006617 }
6618
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006619 // Flush immediately if the buffer's grown too large, or this
6620 // is a non-system app. Non-system apps are isolated with a
6621 // different tag & policy and not batched.
6622 //
6623 // Batching is useful during internal testing with
6624 // StrictMode settings turned up high. Without batching,
6625 // thousands of separate files could be created on boot.
6626 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006627 new Thread("Error dump: " + dropboxTag) {
6628 @Override
6629 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006630 String report;
6631 synchronized (sb) {
6632 report = sb.toString();
6633 sb.delete(0, sb.length());
6634 sb.trimToSize();
6635 }
6636 if (report.length() != 0) {
6637 dbox.addText(dropboxTag, report);
6638 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006639 }
6640 }.start();
6641 return;
6642 }
6643
6644 // System app batching:
6645 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006646 // An existing dropbox-writing thread is outstanding, so
6647 // we don't need to start it up. The existing thread will
6648 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006649 return;
6650 }
6651
6652 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6653 // (After this point, we shouldn't access AMS internal data structures.)
6654 new Thread("Error dump: " + dropboxTag) {
6655 @Override
6656 public void run() {
6657 // 5 second sleep to let stacks arrive and be batched together
6658 try {
6659 Thread.sleep(5000); // 5 seconds
6660 } catch (InterruptedException e) {}
6661
6662 String errorReport;
6663 synchronized (mStrictModeBuffer) {
6664 errorReport = mStrictModeBuffer.toString();
6665 if (errorReport.length() == 0) {
6666 return;
6667 }
6668 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6669 mStrictModeBuffer.trimToSize();
6670 }
6671 dbox.addText(dropboxTag, errorReport);
6672 }
6673 }.start();
6674 }
6675
Dan Egnor60d87622009-12-16 16:32:58 -08006676 /**
6677 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6678 * @param app object of the crashing app, null for the system server
6679 * @param tag reported by the caller
6680 * @param crashInfo describing the context of the error
6681 * @return true if the process should exit immediately (WTF is fatal)
6682 */
6683 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006684 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006685 ProcessRecord r = findAppProcess(app);
6686
6687 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6688 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006689 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006690 tag, crashInfo.exceptionMessage);
6691
Dan Egnor42471dd2010-01-07 17:25:22 -08006692 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006693
Doug Zongker43866e02010-01-07 12:09:54 -08006694 if (Settings.Secure.getInt(mContext.getContentResolver(),
6695 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006696 crashApplication(r, crashInfo);
6697 return true;
6698 } else {
6699 return false;
6700 }
6701 }
6702
6703 /**
6704 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6705 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6706 */
6707 private ProcessRecord findAppProcess(IBinder app) {
6708 if (app == null) {
6709 return null;
6710 }
6711
6712 synchronized (this) {
6713 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6714 final int NA = apps.size();
6715 for (int ia=0; ia<NA; ia++) {
6716 ProcessRecord p = apps.valueAt(ia);
6717 if (p.thread != null && p.thread.asBinder() == app) {
6718 return p;
6719 }
6720 }
6721 }
6722
Joe Onorato8a9b2202010-02-26 18:56:32 -08006723 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006724 return null;
6725 }
6726 }
6727
6728 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006729 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6730 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006731 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006732 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08006733 // Watchdog thread ends up invoking this function (with
6734 // a null ProcessRecord) to add the stack file to dropbox.
6735 // Do not acquire a lock on this (am) in such cases, as it
6736 // could cause a potential deadlock, if and when watchdog
6737 // is invoked due to unavailability of lock on am and it
6738 // would prevent watchdog from killing system_server.
6739 if (process == null) {
6740 sb.append("Process: system_server\n");
6741 return;
6742 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006743 // Note: ProcessRecord 'process' is guarded by the service
6744 // instance. (notably process.pkgList, which could otherwise change
6745 // concurrently during execution of this method)
6746 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08006747 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006748 sb.append("Process: system_server\n");
6749 } else {
6750 sb.append("Process: ").append(process.processName).append("\n");
6751 }
Dan Egnora455d192010-03-12 08:52:28 -08006752 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006753 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006754 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6755 for (String pkg : process.pkgList) {
6756 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006757 try {
Dan Egnora455d192010-03-12 08:52:28 -08006758 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6759 if (pi != null) {
6760 sb.append(" v").append(pi.versionCode);
6761 if (pi.versionName != null) {
6762 sb.append(" (").append(pi.versionName).append(")");
6763 }
6764 }
6765 } catch (RemoteException e) {
6766 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006767 }
Dan Egnora455d192010-03-12 08:52:28 -08006768 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006769 }
Dan Egnora455d192010-03-12 08:52:28 -08006770 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006771 }
6772
6773 private static String processClass(ProcessRecord process) {
6774 if (process == null || process.pid == MY_PID) {
6775 return "system_server";
6776 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6777 return "system_app";
6778 } else {
6779 return "data_app";
6780 }
6781 }
6782
6783 /**
6784 * Write a description of an error (crash, WTF, ANR) to the drop box.
6785 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6786 * @param process which caused the error, null means the system server
6787 * @param activity which triggered the error, null if unknown
6788 * @param parent activity related to the error, null if unknown
6789 * @param subject line related to the error, null if absent
6790 * @param report in long form describing the error, null if absent
6791 * @param logFile to include in the report, null if none
6792 * @param crashInfo giving an application stack trace, null if absent
6793 */
6794 public void addErrorToDropBox(String eventType,
6795 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6796 final String report, final File logFile,
6797 final ApplicationErrorReport.CrashInfo crashInfo) {
6798 // NOTE -- this must never acquire the ActivityManagerService lock,
6799 // otherwise the watchdog may be prevented from resetting the system.
6800
6801 final String dropboxTag = processClass(process) + "_" + eventType;
6802 final DropBoxManager dbox = (DropBoxManager)
6803 mContext.getSystemService(Context.DROPBOX_SERVICE);
6804
6805 // Exit early if the dropbox isn't configured to accept this report type.
6806 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6807
6808 final StringBuilder sb = new StringBuilder(1024);
6809 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006810 if (activity != null) {
6811 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6812 }
6813 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6814 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6815 }
6816 if (parent != null && parent != activity) {
6817 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6818 }
6819 if (subject != null) {
6820 sb.append("Subject: ").append(subject).append("\n");
6821 }
6822 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006823 if (Debug.isDebuggerConnected()) {
6824 sb.append("Debugger: Connected\n");
6825 }
Dan Egnora455d192010-03-12 08:52:28 -08006826 sb.append("\n");
6827
6828 // Do the rest in a worker thread to avoid blocking the caller on I/O
6829 // (After this point, we shouldn't access AMS internal data structures.)
6830 Thread worker = new Thread("Error dump: " + dropboxTag) {
6831 @Override
6832 public void run() {
6833 if (report != null) {
6834 sb.append(report);
6835 }
6836 if (logFile != null) {
6837 try {
6838 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6839 } catch (IOException e) {
6840 Slog.e(TAG, "Error reading " + logFile, e);
6841 }
6842 }
6843 if (crashInfo != null && crashInfo.stackTrace != null) {
6844 sb.append(crashInfo.stackTrace);
6845 }
6846
6847 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6848 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6849 if (lines > 0) {
6850 sb.append("\n");
6851
6852 // Merge several logcat streams, and take the last N lines
6853 InputStreamReader input = null;
6854 try {
6855 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6856 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6857 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6858
6859 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6860 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6861 input = new InputStreamReader(logcat.getInputStream());
6862
6863 int num;
6864 char[] buf = new char[8192];
6865 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6866 } catch (IOException e) {
6867 Slog.e(TAG, "Error running logcat", e);
6868 } finally {
6869 if (input != null) try { input.close(); } catch (IOException e) {}
6870 }
6871 }
6872
6873 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006874 }
Dan Egnora455d192010-03-12 08:52:28 -08006875 };
6876
6877 if (process == null || process.pid == MY_PID) {
6878 worker.run(); // We may be about to die -- need to run this synchronously
6879 } else {
6880 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006881 }
6882 }
6883
6884 /**
6885 * Bring up the "unexpected error" dialog box for a crashing app.
6886 * Deal with edge cases (intercepts from instrumented applications,
6887 * ActivityController, error intent receivers, that sort of thing).
6888 * @param r the application crashing
6889 * @param crashInfo describing the failure
6890 */
6891 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006892 long timeMillis = System.currentTimeMillis();
6893 String shortMsg = crashInfo.exceptionClassName;
6894 String longMsg = crashInfo.exceptionMessage;
6895 String stackTrace = crashInfo.stackTrace;
6896 if (shortMsg != null && longMsg != null) {
6897 longMsg = shortMsg + ": " + longMsg;
6898 } else if (shortMsg != null) {
6899 longMsg = shortMsg;
6900 }
6901
Dan Egnor60d87622009-12-16 16:32:58 -08006902 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006904 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 try {
6906 String name = r != null ? r.processName : null;
6907 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006908 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006909 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006910 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 + " at watcher's request");
6912 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006913 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 }
6915 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006916 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006917 }
6918 }
6919
6920 final long origId = Binder.clearCallingIdentity();
6921
6922 // If this process is running instrumentation, finish it.
6923 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006924 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006925 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006926 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6927 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 Bundle info = new Bundle();
6929 info.putString("shortMsg", shortMsg);
6930 info.putString("longMsg", longMsg);
6931 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6932 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006933 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 }
6935
Dan Egnor60d87622009-12-16 16:32:58 -08006936 // If we can't identify the process or it's already exceeded its crash quota,
6937 // quit right away without showing a crash dialog.
6938 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006939 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006940 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 }
6942
6943 Message msg = Message.obtain();
6944 msg.what = SHOW_ERROR_MSG;
6945 HashMap data = new HashMap();
6946 data.put("result", result);
6947 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006948 msg.obj = data;
6949 mHandler.sendMessage(msg);
6950
6951 Binder.restoreCallingIdentity(origId);
6952 }
6953
6954 int res = result.get();
6955
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006956 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006957 synchronized (this) {
6958 if (r != null) {
6959 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6960 SystemClock.uptimeMillis());
6961 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006962 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006963 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006964 }
6965 }
6966
6967 if (appErrorIntent != null) {
6968 try {
6969 mContext.startActivity(appErrorIntent);
6970 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006971 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006975
6976 Intent createAppErrorIntentLocked(ProcessRecord r,
6977 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6978 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006979 if (report == null) {
6980 return null;
6981 }
6982 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6983 result.setComponent(r.errorReportReceiver);
6984 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6985 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6986 return result;
6987 }
6988
Dan Egnorb7f03672009-12-09 16:22:32 -08006989 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6990 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006991 if (r.errorReportReceiver == null) {
6992 return null;
6993 }
6994
6995 if (!r.crashing && !r.notResponding) {
6996 return null;
6997 }
6998
Dan Egnorb7f03672009-12-09 16:22:32 -08006999 ApplicationErrorReport report = new ApplicationErrorReport();
7000 report.packageName = r.info.packageName;
7001 report.installerPackageName = r.errorReportReceiver.getPackageName();
7002 report.processName = r.processName;
7003 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007004 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007005
Dan Egnorb7f03672009-12-09 16:22:32 -08007006 if (r.crashing) {
7007 report.type = ApplicationErrorReport.TYPE_CRASH;
7008 report.crashInfo = crashInfo;
7009 } else if (r.notResponding) {
7010 report.type = ApplicationErrorReport.TYPE_ANR;
7011 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007012
Dan Egnorb7f03672009-12-09 16:22:32 -08007013 report.anrInfo.activity = r.notRespondingReport.tag;
7014 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7015 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007016 }
7017
Dan Egnorb7f03672009-12-09 16:22:32 -08007018 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007019 }
7020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7022 // assume our apps are happy - lazy create the list
7023 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7024
7025 synchronized (this) {
7026
7027 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007028 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7029 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7031 // This one's in trouble, so we'll generate a report for it
7032 // crashes are higher priority (in case there's a crash *and* an anr)
7033 ActivityManager.ProcessErrorStateInfo report = null;
7034 if (app.crashing) {
7035 report = app.crashingReport;
7036 } else if (app.notResponding) {
7037 report = app.notRespondingReport;
7038 }
7039
7040 if (report != null) {
7041 if (errList == null) {
7042 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7043 }
7044 errList.add(report);
7045 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007046 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 " crashing = " + app.crashing +
7048 " notResponding = " + app.notResponding);
7049 }
7050 }
7051 }
7052 }
7053
7054 return errList;
7055 }
7056
7057 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7058 // Lazy instantiation of list
7059 List<ActivityManager.RunningAppProcessInfo> runList = null;
7060 synchronized (this) {
7061 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007062 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7063 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7065 // Generate process state info for running application
7066 ActivityManager.RunningAppProcessInfo currApp =
7067 new ActivityManager.RunningAppProcessInfo(app.processName,
7068 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007069 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007070 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007071 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007072 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007073 if (app.persistent) {
7074 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007076 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007077 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7079 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7080 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007081 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7082 } else if (adj >= HOME_APP_ADJ) {
7083 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7084 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 } else if (adj >= SECONDARY_SERVER_ADJ) {
7086 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007087 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007088 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007089 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7090 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 } else if (adj >= VISIBLE_APP_ADJ) {
7092 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7093 } else {
7094 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7095 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007096 currApp.importanceReasonCode = app.adjTypeCode;
7097 if (app.adjSource instanceof ProcessRecord) {
7098 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007099 } else if (app.adjSource instanceof ActivityRecord) {
7100 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007101 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7102 }
7103 if (app.adjTarget instanceof ComponentName) {
7104 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7105 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007106 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 // + " lru=" + currApp.lru);
7108 if (runList == null) {
7109 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7110 }
7111 runList.add(currApp);
7112 }
7113 }
7114 }
7115 return runList;
7116 }
7117
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007118 public List<ApplicationInfo> getRunningExternalApplications() {
7119 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7120 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7121 if (runningApps != null && runningApps.size() > 0) {
7122 Set<String> extList = new HashSet<String>();
7123 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7124 if (app.pkgList != null) {
7125 for (String pkg : app.pkgList) {
7126 extList.add(pkg);
7127 }
7128 }
7129 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007130 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007131 for (String pkg : extList) {
7132 try {
7133 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7134 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7135 retList.add(info);
7136 }
7137 } catch (RemoteException e) {
7138 }
7139 }
7140 }
7141 return retList;
7142 }
7143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144 @Override
7145 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007146 if (checkCallingPermission(android.Manifest.permission.DUMP)
7147 != PackageManager.PERMISSION_GRANTED) {
7148 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7149 + Binder.getCallingPid()
7150 + ", uid=" + Binder.getCallingUid()
7151 + " without permission "
7152 + android.Manifest.permission.DUMP);
7153 return;
7154 }
7155
7156 boolean dumpAll = false;
7157
7158 int opti = 0;
7159 while (opti < args.length) {
7160 String opt = args[opti];
7161 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7162 break;
7163 }
7164 opti++;
7165 if ("-a".equals(opt)) {
7166 dumpAll = true;
7167 } else if ("-h".equals(opt)) {
7168 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007169 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007170 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007171 pw.println(" a[ctivities]: activity stack state");
7172 pw.println(" b[roadcasts]: broadcast state");
7173 pw.println(" i[ntents]: pending intent state");
7174 pw.println(" p[rocesses]: process state");
7175 pw.println(" o[om]: out of memory management");
7176 pw.println(" prov[iders]: content provider state");
7177 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007178 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007179 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007180 } else {
7181 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007183 }
7184
7185 // Is the caller requesting to dump a particular piece of data?
7186 if (opti < args.length) {
7187 String cmd = args[opti];
7188 opti++;
7189 if ("activities".equals(cmd) || "a".equals(cmd)) {
7190 synchronized (this) {
7191 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007193 return;
7194 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7195 synchronized (this) {
7196 dumpBroadcastsLocked(fd, pw, args, opti, true);
7197 }
7198 return;
7199 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7200 synchronized (this) {
7201 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7202 }
7203 return;
7204 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7205 synchronized (this) {
7206 dumpProcessesLocked(fd, pw, args, opti, true);
7207 }
7208 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007209 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7210 synchronized (this) {
7211 dumpOomLocked(fd, pw, args, opti, true);
7212 }
7213 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007214 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7215 synchronized (this) {
7216 dumpProvidersLocked(fd, pw, args, opti, true);
7217 }
7218 return;
7219 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007220 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007221 return;
7222 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7223 synchronized (this) {
7224 dumpServicesLocked(fd, pw, args, opti, true);
7225 }
7226 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007228 }
7229
7230 // No piece of data specified, dump everything.
7231 synchronized (this) {
7232 boolean needSep;
7233 if (dumpAll) {
7234 pw.println("Providers in Current Activity Manager State:");
7235 }
7236 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7237 if (needSep) {
7238 pw.println(" ");
7239 }
7240 if (dumpAll) {
7241 pw.println("-------------------------------------------------------------------------------");
7242 pw.println("Broadcasts in Current Activity Manager State:");
7243 }
7244 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7245 if (needSep) {
7246 pw.println(" ");
7247 }
7248 if (dumpAll) {
7249 pw.println("-------------------------------------------------------------------------------");
7250 pw.println("Services in Current Activity Manager State:");
7251 }
7252 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7253 if (needSep) {
7254 pw.println(" ");
7255 }
7256 if (dumpAll) {
7257 pw.println("-------------------------------------------------------------------------------");
7258 pw.println("PendingIntents in Current Activity Manager State:");
7259 }
7260 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7261 if (needSep) {
7262 pw.println(" ");
7263 }
7264 if (dumpAll) {
7265 pw.println("-------------------------------------------------------------------------------");
7266 pw.println("Activities in Current Activity Manager State:");
7267 }
7268 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7269 if (needSep) {
7270 pw.println(" ");
7271 }
7272 if (dumpAll) {
7273 pw.println("-------------------------------------------------------------------------------");
7274 pw.println("Processes in Current Activity Manager State:");
7275 }
7276 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7277 }
7278 }
7279
7280 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7281 int opti, boolean dumpAll, boolean needHeader) {
7282 if (needHeader) {
7283 pw.println(" Activity stack:");
7284 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007285 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007286 pw.println(" ");
7287 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007288 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7289 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007291 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007292 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007293 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007294 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007297 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007298 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007299 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007300 pw.println(" ");
7301 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007302 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007304
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007305 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007306 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7307 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007308 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007309 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007311 if (dumpAll && mRecentTasks.size() > 0) {
7312 pw.println(" ");
7313 pw.println("Recent tasks in Current Activity Manager State:");
7314
7315 final int N = mRecentTasks.size();
7316 for (int i=0; i<N; i++) {
7317 TaskRecord tr = mRecentTasks.get(i);
7318 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7319 pw.println(tr);
7320 mRecentTasks.get(i).dump(pw, " ");
7321 }
7322 }
7323
7324 pw.println(" ");
7325 pw.println(" mCurTask: " + mCurTask);
7326
7327 return true;
7328 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007329
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007330 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7331 int opti, boolean dumpAll) {
7332 boolean needSep = false;
7333 int numPers = 0;
7334
7335 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7337 final int NA = procs.size();
7338 for (int ia=0; ia<NA; ia++) {
7339 if (!needSep) {
7340 pw.println(" All known processes:");
7341 needSep = true;
7342 }
7343 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007344 pw.print(r.persistent ? " *PERS*" : " *APP*");
7345 pw.print(" UID "); pw.print(procs.keyAt(ia));
7346 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 r.dump(pw, " ");
7348 if (r.persistent) {
7349 numPers++;
7350 }
7351 }
7352 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007353 }
7354
7355 if (mLruProcesses.size() > 0) {
7356 if (needSep) pw.println(" ");
7357 needSep = true;
7358 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007359 dumpProcessOomList(pw, this, mLruProcesses, " ",
7360 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007361 needSep = true;
7362 }
7363
7364 synchronized (mPidsSelfLocked) {
7365 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 if (needSep) pw.println(" ");
7367 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007368 pw.println(" PID mappings:");
7369 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7370 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7371 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 }
7373 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007374 }
7375
7376 if (mForegroundProcesses.size() > 0) {
7377 if (needSep) pw.println(" ");
7378 needSep = true;
7379 pw.println(" Foreground Processes:");
7380 for (int i=0; i<mForegroundProcesses.size(); i++) {
7381 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7382 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007384 }
7385
7386 if (mPersistentStartingProcesses.size() > 0) {
7387 if (needSep) pw.println(" ");
7388 needSep = true;
7389 pw.println(" Persisent processes that are starting:");
7390 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007391 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007394 if (mStartingProcesses.size() > 0) {
7395 if (needSep) pw.println(" ");
7396 needSep = true;
7397 pw.println(" Processes that are starting:");
7398 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007399 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 if (mRemovedProcesses.size() > 0) {
7403 if (needSep) pw.println(" ");
7404 needSep = true;
7405 pw.println(" Processes that are being removed:");
7406 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007407 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007408 }
7409
7410 if (mProcessesOnHold.size() > 0) {
7411 if (needSep) pw.println(" ");
7412 needSep = true;
7413 pw.println(" Processes that are on old until the system is ready:");
7414 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007415 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417
Dianne Hackborn287952c2010-09-22 22:34:31 -07007418 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007419
7420 if (mProcessCrashTimes.getMap().size() > 0) {
7421 if (needSep) pw.println(" ");
7422 needSep = true;
7423 pw.println(" Time since processes crashed:");
7424 long now = SystemClock.uptimeMillis();
7425 for (Map.Entry<String, SparseArray<Long>> procs
7426 : mProcessCrashTimes.getMap().entrySet()) {
7427 SparseArray<Long> uids = procs.getValue();
7428 final int N = uids.size();
7429 for (int i=0; i<N; i++) {
7430 pw.print(" Process "); pw.print(procs.getKey());
7431 pw.print(" uid "); pw.print(uids.keyAt(i));
7432 pw.print(": last crashed ");
7433 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007434 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007435 }
7436 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007439 if (mBadProcesses.getMap().size() > 0) {
7440 if (needSep) pw.println(" ");
7441 needSep = true;
7442 pw.println(" Bad processes:");
7443 for (Map.Entry<String, SparseArray<Long>> procs
7444 : mBadProcesses.getMap().entrySet()) {
7445 SparseArray<Long> uids = procs.getValue();
7446 final int N = uids.size();
7447 for (int i=0; i<N; i++) {
7448 pw.print(" Bad process "); pw.print(procs.getKey());
7449 pw.print(" uid "); pw.print(uids.keyAt(i));
7450 pw.print(": crashed at time ");
7451 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 }
7453 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007456 pw.println(" ");
7457 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007458 if (mHeavyWeightProcess != null) {
7459 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7460 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007461 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007462 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007463 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7464 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7465 || mOrigWaitForDebugger) {
7466 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7467 + " mDebugTransient=" + mDebugTransient
7468 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7469 }
7470 if (mAlwaysFinishActivities || mController != null) {
7471 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7472 + " mController=" + mController);
7473 }
7474 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007477 + " mProcessesReady=" + mProcessesReady
7478 + " mSystemReady=" + mSystemReady);
7479 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007480 + " mBooted=" + mBooted
7481 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007482 pw.print(" mLastPowerCheckRealtime=");
7483 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7484 pw.println("");
7485 pw.print(" mLastPowerCheckUptime=");
7486 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7487 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007488 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7489 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007490 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007491 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007492
7493 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 }
7495
Dianne Hackborn287952c2010-09-22 22:34:31 -07007496 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7497 int opti, boolean needSep, boolean dumpAll) {
7498 if (mProcessesToGc.size() > 0) {
7499 if (needSep) pw.println(" ");
7500 needSep = true;
7501 pw.println(" Processes that are waiting to GC:");
7502 long now = SystemClock.uptimeMillis();
7503 for (int i=0; i<mProcessesToGc.size(); i++) {
7504 ProcessRecord proc = mProcessesToGc.get(i);
7505 pw.print(" Process "); pw.println(proc);
7506 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7507 pw.print(", last gced=");
7508 pw.print(now-proc.lastRequestedGc);
7509 pw.print(" ms ago, last lowMem=");
7510 pw.print(now-proc.lastLowMemory);
7511 pw.println(" ms ago");
7512
7513 }
7514 }
7515 return needSep;
7516 }
7517
7518 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7519 int opti, boolean dumpAll) {
7520 boolean needSep = false;
7521
7522 if (mLruProcesses.size() > 0) {
7523 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7524
7525 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7526 @Override
7527 public int compare(ProcessRecord object1, ProcessRecord object2) {
7528 if (object1.setAdj != object2.setAdj) {
7529 return object1.setAdj > object2.setAdj ? -1 : 1;
7530 }
7531 if (object1.setSchedGroup != object2.setSchedGroup) {
7532 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7533 }
7534 if (object1.keeping != object2.keeping) {
7535 return object1.keeping ? -1 : 1;
7536 }
7537 if (object1.pid != object2.pid) {
7538 return object1.pid > object2.pid ? -1 : 1;
7539 }
7540 return 0;
7541 }
7542 };
7543
7544 Collections.sort(procs, comparator);
7545
7546 if (needSep) pw.println(" ");
7547 needSep = true;
7548 pw.println(" Process OOM control:");
7549 dumpProcessOomList(pw, this, procs, " ",
7550 "Proc", "PERS", true);
7551 needSep = true;
7552 }
7553
7554 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7555
7556 pw.println(" ");
7557 pw.println(" mHomeProcess: " + mHomeProcess);
7558 if (mHeavyWeightProcess != null) {
7559 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7560 }
7561
7562 return true;
7563 }
7564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 /**
7566 * There are three ways to call this:
7567 * - no service specified: dump all the services
7568 * - a flattened component name that matched an existing service was specified as the
7569 * first arg: dump that one service
7570 * - the first arg isn't the flattened component name of an existing service:
7571 * dump all services whose component contains the first arg as a substring
7572 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007573 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7574 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 String[] newArgs;
7576 String componentNameString;
7577 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007578 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 componentNameString = null;
7580 newArgs = EMPTY_STRING_ARRAY;
7581 r = null;
7582 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007583 componentNameString = args[opti];
7584 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007586 synchronized (this) {
7587 r = componentName != null ? mServices.get(componentName) : null;
7588 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007589 newArgs = new String[args.length - opti];
7590 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 }
7592
7593 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007594 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007596 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7597 synchronized (this) {
7598 for (ServiceRecord r1 : mServices.values()) {
7599 if (componentNameString == null
7600 || r1.name.flattenToString().contains(componentNameString)) {
7601 services.add(r1);
7602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 }
7604 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007605 for (int i=0; i<services.size(); i++) {
7606 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 }
7609 }
7610
7611 /**
7612 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7613 * there is a thread associated with the service.
7614 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007615 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7616 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007618 if (dumpAll) {
7619 synchronized (this) {
7620 pw.print(" * "); pw.println(r);
7621 r.dump(pw, " ");
7622 }
7623 pw.println("");
7624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 if (r.app != null && r.app.thread != null) {
7626 try {
7627 // flush anything that is already in the PrintWriter since the thread is going
7628 // to write to the file descriptor directly
7629 pw.flush();
7630 r.app.thread.dumpService(fd, r, args);
7631 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007632 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 } catch (RemoteException e) {
7634 pw.println("got a RemoteException while dumping the service");
7635 }
7636 }
7637 }
7638
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007639 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7640 int opti, boolean dumpAll) {
7641 boolean needSep = false;
7642
7643 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 if (mRegisteredReceivers.size() > 0) {
7645 pw.println(" ");
7646 pw.println(" Registered Receivers:");
7647 Iterator it = mRegisteredReceivers.values().iterator();
7648 while (it.hasNext()) {
7649 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007650 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007651 r.dump(pw, " ");
7652 }
7653 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 pw.println(" ");
7656 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007657 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007658 needSep = true;
7659 }
7660
7661 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7662 || mPendingBroadcast != null) {
7663 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007664 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007665 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7668 pw.println(" Broadcast #" + i + ":");
7669 mParallelBroadcasts.get(i).dump(pw, " ");
7670 }
7671 if (mOrderedBroadcasts.size() > 0) {
7672 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007673 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007674 }
7675 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7676 pw.println(" Serialized Broadcast #" + i + ":");
7677 mOrderedBroadcasts.get(i).dump(pw, " ");
7678 }
7679 pw.println(" ");
7680 pw.println(" Pending broadcast:");
7681 if (mPendingBroadcast != null) {
7682 mPendingBroadcast.dump(pw, " ");
7683 } else {
7684 pw.println(" (null)");
7685 }
7686 needSep = true;
7687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007689 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007691 pw.println(" Historical broadcasts:");
7692 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7693 BroadcastRecord r = mBroadcastHistory[i];
7694 if (r == null) {
7695 break;
7696 }
7697 pw.println(" Historical Broadcast #" + i + ":");
7698 r.dump(pw, " ");
7699 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007700 needSep = true;
7701 }
7702
7703 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007704 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007705 pw.println(" Sticky broadcasts:");
7706 StringBuilder sb = new StringBuilder(128);
7707 for (Map.Entry<String, ArrayList<Intent>> ent
7708 : mStickyBroadcasts.entrySet()) {
7709 pw.print(" * Sticky action "); pw.print(ent.getKey());
7710 pw.println(":");
7711 ArrayList<Intent> intents = ent.getValue();
7712 final int N = intents.size();
7713 for (int i=0; i<N; i++) {
7714 sb.setLength(0);
7715 sb.append(" Intent: ");
7716 intents.get(i).toShortString(sb, true, false);
7717 pw.println(sb.toString());
7718 Bundle bundle = intents.get(i).getExtras();
7719 if (bundle != null) {
7720 pw.print(" ");
7721 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 }
7723 }
7724 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007725 needSep = true;
7726 }
7727
7728 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007730 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 pw.println(" mHandler:");
7732 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007735
7736 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007737 }
7738
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007739 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7740 int opti, boolean dumpAll) {
7741 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007743 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 if (mServices.size() > 0) {
7745 pw.println(" Active services:");
7746 Iterator<ServiceRecord> it = mServices.values().iterator();
7747 while (it.hasNext()) {
7748 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007749 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 r.dump(pw, " ");
7751 }
7752 needSep = true;
7753 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007756 if (mPendingServices.size() > 0) {
7757 if (needSep) pw.println(" ");
7758 pw.println(" Pending services:");
7759 for (int i=0; i<mPendingServices.size(); i++) {
7760 ServiceRecord r = mPendingServices.get(i);
7761 pw.print(" * Pending "); pw.println(r);
7762 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007764 needSep = true;
7765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007766
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007767 if (mRestartingServices.size() > 0) {
7768 if (needSep) pw.println(" ");
7769 pw.println(" Restarting services:");
7770 for (int i=0; i<mRestartingServices.size(); i++) {
7771 ServiceRecord r = mRestartingServices.get(i);
7772 pw.print(" * Restarting "); pw.println(r);
7773 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775 needSep = true;
7776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007778 if (mStoppingServices.size() > 0) {
7779 if (needSep) pw.println(" ");
7780 pw.println(" Stopping services:");
7781 for (int i=0; i<mStoppingServices.size(); i++) {
7782 ServiceRecord r = mStoppingServices.get(i);
7783 pw.print(" * Stopping "); pw.println(r);
7784 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007786 needSep = true;
7787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007788
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007789 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 if (mServiceConnections.size() > 0) {
7791 if (needSep) pw.println(" ");
7792 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007793 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 = mServiceConnections.values().iterator();
7795 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007796 ArrayList<ConnectionRecord> r = it.next();
7797 for (int i=0; i<r.size(); i++) {
7798 pw.print(" * "); pw.println(r.get(i));
7799 r.get(i).dump(pw, " ");
7800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007801 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007802 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 }
7804 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007805
7806 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 }
7808
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007809 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7810 int opti, boolean dumpAll) {
7811 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007813 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 if (mProvidersByClass.size() > 0) {
7815 if (needSep) pw.println(" ");
7816 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007817 Iterator<Map.Entry<String, ContentProviderRecord>> it
7818 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007820 Map.Entry<String, ContentProviderRecord> e = it.next();
7821 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007822 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 r.dump(pw, " ");
7824 }
7825 needSep = true;
7826 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007827
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007828 if (mProvidersByName.size() > 0) {
7829 pw.println(" ");
7830 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007831 Iterator<Map.Entry<String, ContentProviderRecord>> it
7832 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007833 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007834 Map.Entry<String, ContentProviderRecord> e = it.next();
7835 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007836 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7837 pw.println(r);
7838 }
7839 needSep = true;
7840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007842
7843 if (mLaunchingProviders.size() > 0) {
7844 if (needSep) pw.println(" ");
7845 pw.println(" Launching content providers:");
7846 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7847 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7848 pw.println(mLaunchingProviders.get(i));
7849 }
7850 needSep = true;
7851 }
7852
7853 if (mGrantedUriPermissions.size() > 0) {
7854 pw.println();
7855 pw.println("Granted Uri Permissions:");
7856 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7857 int uid = mGrantedUriPermissions.keyAt(i);
7858 HashMap<Uri, UriPermission> perms
7859 = mGrantedUriPermissions.valueAt(i);
7860 pw.print(" * UID "); pw.print(uid);
7861 pw.println(" holds:");
7862 for (UriPermission perm : perms.values()) {
7863 pw.print(" "); pw.println(perm);
7864 perm.dump(pw, " ");
7865 }
7866 }
7867 needSep = true;
7868 }
7869
7870 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 }
7872
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007873 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7874 int opti, boolean dumpAll) {
7875 boolean needSep = false;
7876
7877 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 if (this.mIntentSenderRecords.size() > 0) {
7879 Iterator<WeakReference<PendingIntentRecord>> it
7880 = mIntentSenderRecords.values().iterator();
7881 while (it.hasNext()) {
7882 WeakReference<PendingIntentRecord> ref = it.next();
7883 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007884 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007885 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007886 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 rec.dump(pw, " ");
7888 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007889 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 }
7891 }
7892 }
7893 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007894
7895 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 }
7897
7898 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007899 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 TaskRecord lastTask = null;
7901 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007902 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007903 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 if (lastTask != r.task) {
7905 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007906 pw.print(prefix);
7907 pw.print(full ? "* " : " ");
7908 pw.println(lastTask);
7909 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007910 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007913 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7914 pw.print(" #"); pw.print(i); pw.print(": ");
7915 pw.println(r);
7916 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007917 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 }
7920 }
7921
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007922 private static String buildOomTag(String prefix, String space, int val, int base) {
7923 if (val == base) {
7924 if (space == null) return prefix;
7925 return prefix + " ";
7926 }
7927 return prefix + "+" + Integer.toString(val-base);
7928 }
7929
7930 private static final int dumpProcessList(PrintWriter pw,
7931 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007932 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007934 final int N = list.size()-1;
7935 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007937 pw.println(String.format("%s%s #%2d: %s",
7938 prefix, (r.persistent ? persistentLabel : normalLabel),
7939 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 if (r.persistent) {
7941 numPers++;
7942 }
7943 }
7944 return numPers;
7945 }
7946
Dianne Hackborn287952c2010-09-22 22:34:31 -07007947 private static final void dumpProcessOomList(PrintWriter pw,
7948 ActivityManagerService service, List<ProcessRecord> list,
7949 String prefix, String normalLabel, String persistentLabel,
7950 boolean inclDetails) {
7951
7952 final long curRealtime = SystemClock.elapsedRealtime();
7953 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7954 final long curUptime = SystemClock.uptimeMillis();
7955 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7956
7957 final int N = list.size()-1;
7958 for (int i=N; i>=0; i--) {
7959 ProcessRecord r = list.get(i);
7960 String oomAdj;
7961 if (r.setAdj >= EMPTY_APP_ADJ) {
7962 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7963 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7964 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7965 } else if (r.setAdj >= HOME_APP_ADJ) {
7966 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7967 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7968 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7969 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7970 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7971 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7972 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7973 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7974 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7975 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7976 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7977 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7978 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7979 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7980 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7981 } else if (r.setAdj >= SYSTEM_ADJ) {
7982 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7983 } else {
7984 oomAdj = Integer.toString(r.setAdj);
7985 }
7986 String schedGroup;
7987 switch (r.setSchedGroup) {
7988 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7989 schedGroup = "B";
7990 break;
7991 case Process.THREAD_GROUP_DEFAULT:
7992 schedGroup = "F";
7993 break;
7994 default:
7995 schedGroup = Integer.toString(r.setSchedGroup);
7996 break;
7997 }
7998 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7999 prefix, (r.persistent ? persistentLabel : normalLabel),
8000 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8001 if (r.adjSource != null || r.adjTarget != null) {
8002 pw.print(prefix);
8003 pw.print(" ");
8004 if (r.adjTarget instanceof ComponentName) {
8005 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8006 } else if (r.adjTarget != null) {
8007 pw.print(r.adjTarget.toString());
8008 } else {
8009 pw.print("{null}");
8010 }
8011 pw.print("<=");
8012 if (r.adjSource instanceof ProcessRecord) {
8013 pw.print("Proc{");
8014 pw.print(((ProcessRecord)r.adjSource).toShortString());
8015 pw.println("}");
8016 } else if (r.adjSource != null) {
8017 pw.println(r.adjSource.toString());
8018 } else {
8019 pw.println("{null}");
8020 }
8021 }
8022 if (inclDetails) {
8023 pw.print(prefix);
8024 pw.print(" ");
8025 pw.print("oom: max="); pw.print(r.maxAdj);
8026 pw.print(" hidden="); pw.print(r.hiddenAdj);
8027 pw.print(" curRaw="); pw.print(r.curRawAdj);
8028 pw.print(" setRaw="); pw.print(r.setRawAdj);
8029 pw.print(" cur="); pw.print(r.curAdj);
8030 pw.print(" set="); pw.println(r.setAdj);
8031 pw.print(prefix);
8032 pw.print(" ");
8033 pw.print("keeping="); pw.print(r.keeping);
8034 pw.print(" hidden="); pw.print(r.hidden);
8035 pw.print(" empty="); pw.println(r.empty);
8036
8037 if (!r.keeping) {
8038 if (r.lastWakeTime != 0) {
8039 long wtime;
8040 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8041 synchronized (stats) {
8042 wtime = stats.getProcessWakeTime(r.info.uid,
8043 r.pid, curRealtime);
8044 }
8045 long timeUsed = wtime - r.lastWakeTime;
8046 pw.print(prefix);
8047 pw.print(" ");
8048 pw.print("keep awake over ");
8049 TimeUtils.formatDuration(realtimeSince, pw);
8050 pw.print(" used ");
8051 TimeUtils.formatDuration(timeUsed, pw);
8052 pw.print(" (");
8053 pw.print((timeUsed*100)/realtimeSince);
8054 pw.println("%)");
8055 }
8056 if (r.lastCpuTime != 0) {
8057 long timeUsed = r.curCpuTime - r.lastCpuTime;
8058 pw.print(prefix);
8059 pw.print(" ");
8060 pw.print("run cpu over ");
8061 TimeUtils.formatDuration(uptimeSince, pw);
8062 pw.print(" used ");
8063 TimeUtils.formatDuration(timeUsed, pw);
8064 pw.print(" (");
8065 pw.print((timeUsed*100)/uptimeSince);
8066 pw.println("%)");
8067 }
8068 }
8069 }
8070 }
8071 }
8072
Dianne Hackborn472ad872010-04-07 17:31:48 -07008073 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008074 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008075 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 long uptime = SystemClock.uptimeMillis();
8077 long realtime = SystemClock.elapsedRealtime();
8078
8079 if (isCheckinRequest) {
8080 // short checkin version
8081 pw.println(uptime + "," + realtime);
8082 pw.flush();
8083 } else {
8084 pw.println("Applications Memory Usage (kB):");
8085 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8086 }
8087 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8088 ProcessRecord r = (ProcessRecord)list.get(i);
8089 if (r.thread != null) {
8090 if (!isCheckinRequest) {
8091 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8092 pw.flush();
8093 }
8094 try {
8095 r.thread.asBinder().dump(fd, args);
8096 } catch (RemoteException e) {
8097 if (!isCheckinRequest) {
8098 pw.println("Got RemoteException!");
8099 pw.flush();
8100 }
8101 }
8102 }
8103 }
8104 }
8105
8106 /**
8107 * Searches array of arguments for the specified string
8108 * @param args array of argument strings
8109 * @param value value to search for
8110 * @return true if the value is contained in the array
8111 */
8112 private static boolean scanArgs(String[] args, String value) {
8113 if (args != null) {
8114 for (String arg : args) {
8115 if (value.equals(arg)) {
8116 return true;
8117 }
8118 }
8119 }
8120 return false;
8121 }
8122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 private final void killServicesLocked(ProcessRecord app,
8124 boolean allowRestart) {
8125 // Report disconnected services.
8126 if (false) {
8127 // XXX we are letting the client link to the service for
8128 // death notifications.
8129 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008130 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008132 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008134 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 = r.connections.values().iterator();
8136 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008137 ArrayList<ConnectionRecord> cl = jt.next();
8138 for (int i=0; i<cl.size(); i++) {
8139 ConnectionRecord c = cl.get(i);
8140 if (c.binding.client != app) {
8141 try {
8142 //c.conn.connected(r.className, null);
8143 } catch (Exception e) {
8144 // todo: this should be asynchronous!
8145 Slog.w(TAG, "Exception thrown disconnected servce "
8146 + r.shortName
8147 + " from app " + app.processName, e);
8148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 }
8150 }
8151 }
8152 }
8153 }
8154 }
8155 }
8156
8157 // Clean up any connections this application has to other services.
8158 if (app.connections.size() > 0) {
8159 Iterator<ConnectionRecord> it = app.connections.iterator();
8160 while (it.hasNext()) {
8161 ConnectionRecord r = it.next();
8162 removeConnectionLocked(r, app, null);
8163 }
8164 }
8165 app.connections.clear();
8166
8167 if (app.services.size() != 0) {
8168 // Any services running in the application need to be placed
8169 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008170 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008172 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 synchronized (sr.stats.getBatteryStats()) {
8174 sr.stats.stopLaunchedLocked();
8175 }
8176 sr.app = null;
8177 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008178 if (mStoppingServices.remove(sr)) {
8179 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8180 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008181
8182 boolean hasClients = sr.bindings.size() > 0;
8183 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 Iterator<IntentBindRecord> bindings
8185 = sr.bindings.values().iterator();
8186 while (bindings.hasNext()) {
8187 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008188 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 + ": shouldUnbind=" + b.hasBound);
8190 b.binder = null;
8191 b.requested = b.received = b.hasBound = false;
8192 }
8193 }
8194
8195 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008196 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008197 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008198 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008199 sr.crashCount, sr.shortName, app.pid);
8200 bringDownServiceLocked(sr, true);
8201 } else if (!allowRestart) {
8202 bringDownServiceLocked(sr, true);
8203 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008204 boolean canceled = scheduleServiceRestartLocked(sr, true);
8205
8206 // Should the service remain running? Note that in the
8207 // extreme case of so many attempts to deliver a command
8208 // that it failed, that we also will stop it here.
8209 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8210 if (sr.pendingStarts.size() == 0) {
8211 sr.startRequested = false;
8212 if (!hasClients) {
8213 // Whoops, no reason to restart!
8214 bringDownServiceLocked(sr, true);
8215 }
8216 }
8217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 }
8219 }
8220
8221 if (!allowRestart) {
8222 app.services.clear();
8223 }
8224 }
8225
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008226 // Make sure we have no more records on the stopping list.
8227 int i = mStoppingServices.size();
8228 while (i > 0) {
8229 i--;
8230 ServiceRecord sr = mStoppingServices.get(i);
8231 if (sr.app == app) {
8232 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008233 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008234 }
8235 }
8236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008237 app.executingServices.clear();
8238 }
8239
8240 private final void removeDyingProviderLocked(ProcessRecord proc,
8241 ContentProviderRecord cpr) {
8242 synchronized (cpr) {
8243 cpr.launchingApp = null;
8244 cpr.notifyAll();
8245 }
8246
8247 mProvidersByClass.remove(cpr.info.name);
8248 String names[] = cpr.info.authority.split(";");
8249 for (int j = 0; j < names.length; j++) {
8250 mProvidersByName.remove(names[j]);
8251 }
8252
8253 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8254 while (cit.hasNext()) {
8255 ProcessRecord capp = cit.next();
8256 if (!capp.persistent && capp.thread != null
8257 && capp.pid != 0
8258 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008259 Slog.i(TAG, "Kill " + capp.processName
8260 + " (pid " + capp.pid + "): provider " + cpr.info.name
8261 + " in dying process " + proc.processName);
8262 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8263 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 Process.killProcess(capp.pid);
8265 }
8266 }
8267
8268 mLaunchingProviders.remove(cpr);
8269 }
8270
8271 /**
8272 * Main code for cleaning up a process when it has gone away. This is
8273 * called both as a result of the process dying, or directly when stopping
8274 * a process when running in single process mode.
8275 */
8276 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8277 boolean restarting, int index) {
8278 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008279 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 }
8281
Dianne Hackborn36124872009-10-08 16:22:03 -07008282 mProcessesToGc.remove(app);
8283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 // Dismiss any open dialogs.
8285 if (app.crashDialog != null) {
8286 app.crashDialog.dismiss();
8287 app.crashDialog = null;
8288 }
8289 if (app.anrDialog != null) {
8290 app.anrDialog.dismiss();
8291 app.anrDialog = null;
8292 }
8293 if (app.waitDialog != null) {
8294 app.waitDialog.dismiss();
8295 app.waitDialog = null;
8296 }
8297
8298 app.crashing = false;
8299 app.notResponding = false;
8300
8301 app.resetPackageList();
8302 app.thread = null;
8303 app.forcingToForeground = null;
8304 app.foregroundServices = false;
8305
8306 killServicesLocked(app, true);
8307
8308 boolean restart = false;
8309
8310 int NL = mLaunchingProviders.size();
8311
8312 // Remove published content providers.
8313 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008314 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008315 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008316 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 cpr.provider = null;
8318 cpr.app = null;
8319
8320 // See if someone is waiting for this provider... in which
8321 // case we don't remove it, but just let it restart.
8322 int i = 0;
8323 if (!app.bad) {
8324 for (; i<NL; i++) {
8325 if (mLaunchingProviders.get(i) == cpr) {
8326 restart = true;
8327 break;
8328 }
8329 }
8330 } else {
8331 i = NL;
8332 }
8333
8334 if (i >= NL) {
8335 removeDyingProviderLocked(app, cpr);
8336 NL = mLaunchingProviders.size();
8337 }
8338 }
8339 app.pubProviders.clear();
8340 }
8341
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008342 // Take care of any launching providers waiting for this process.
8343 if (checkAppInLaunchingProvidersLocked(app, false)) {
8344 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 // Unregister from connected content providers.
8348 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008349 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 while (it.hasNext()) {
8351 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8352 cpr.clients.remove(app);
8353 }
8354 app.conProviders.clear();
8355 }
8356
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008357 // At this point there may be remaining entries in mLaunchingProviders
8358 // where we were the only one waiting, so they are no longer of use.
8359 // Look for these and clean up if found.
8360 // XXX Commented out for now. Trying to figure out a way to reproduce
8361 // the actual situation to identify what is actually going on.
8362 if (false) {
8363 for (int i=0; i<NL; i++) {
8364 ContentProviderRecord cpr = (ContentProviderRecord)
8365 mLaunchingProviders.get(i);
8366 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8367 synchronized (cpr) {
8368 cpr.launchingApp = null;
8369 cpr.notifyAll();
8370 }
8371 }
8372 }
8373 }
8374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008375 skipCurrentReceiverLocked(app);
8376
8377 // Unregister any receivers.
8378 if (app.receivers.size() > 0) {
8379 Iterator<ReceiverList> it = app.receivers.iterator();
8380 while (it.hasNext()) {
8381 removeReceiverLocked(it.next());
8382 }
8383 app.receivers.clear();
8384 }
8385
Christopher Tate181fafa2009-05-14 11:12:14 -07008386 // If the app is undergoing backup, tell the backup manager about it
8387 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008388 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008389 try {
8390 IBackupManager bm = IBackupManager.Stub.asInterface(
8391 ServiceManager.getService(Context.BACKUP_SERVICE));
8392 bm.agentDisconnected(app.info.packageName);
8393 } catch (RemoteException e) {
8394 // can't happen; backup manager is local
8395 }
8396 }
8397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 // If the caller is restarting this app, then leave it in its
8399 // current lists and let the caller take care of it.
8400 if (restarting) {
8401 return;
8402 }
8403
8404 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008405 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008406 "Removing non-persistent process during cleanup: " + app);
8407 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008408 if (mHeavyWeightProcess == app) {
8409 mHeavyWeightProcess = null;
8410 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 } else if (!app.removed) {
8413 // This app is persistent, so we need to keep its record around.
8414 // If it is not already on the pending app list, add it there
8415 // and start a new process for it.
8416 app.thread = null;
8417 app.forcingToForeground = null;
8418 app.foregroundServices = false;
8419 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8420 mPersistentStartingProcesses.add(app);
8421 restart = true;
8422 }
8423 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008424 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8425 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426 mProcessesOnHold.remove(app);
8427
The Android Open Source Project4df24232009-03-05 14:34:35 -08008428 if (app == mHomeProcess) {
8429 mHomeProcess = null;
8430 }
8431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 if (restart) {
8433 // We have components that still need to be running in the
8434 // process, so re-launch it.
8435 mProcessNames.put(app.processName, app.info.uid, app);
8436 startProcessLocked(app, "restart", app.processName);
8437 } else if (app.pid > 0 && app.pid != MY_PID) {
8438 // Goodbye!
8439 synchronized (mPidsSelfLocked) {
8440 mPidsSelfLocked.remove(app.pid);
8441 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8442 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008443 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008444 }
8445 }
8446
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008447 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8448 // Look through the content providers we are waiting to have launched,
8449 // and if any run in this process then either schedule a restart of
8450 // the process or kill the client waiting for it if this process has
8451 // gone bad.
8452 int NL = mLaunchingProviders.size();
8453 boolean restart = false;
8454 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008455 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008456 if (cpr.launchingApp == app) {
8457 if (!alwaysBad && !app.bad) {
8458 restart = true;
8459 } else {
8460 removeDyingProviderLocked(app, cpr);
8461 NL = mLaunchingProviders.size();
8462 }
8463 }
8464 }
8465 return restart;
8466 }
8467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 // =========================================================
8469 // SERVICES
8470 // =========================================================
8471
8472 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8473 ActivityManager.RunningServiceInfo info =
8474 new ActivityManager.RunningServiceInfo();
8475 info.service = r.name;
8476 if (r.app != null) {
8477 info.pid = r.app.pid;
8478 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008479 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 info.process = r.processName;
8481 info.foreground = r.isForeground;
8482 info.activeSince = r.createTime;
8483 info.started = r.startRequested;
8484 info.clientCount = r.connections.size();
8485 info.crashCount = r.crashCount;
8486 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008487 if (r.isForeground) {
8488 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8489 }
8490 if (r.startRequested) {
8491 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8492 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008493 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008494 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8495 }
8496 if (r.app != null && r.app.persistent) {
8497 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8498 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008499
8500 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8501 for (int i=0; i<connl.size(); i++) {
8502 ConnectionRecord conn = connl.get(i);
8503 if (conn.clientLabel != 0) {
8504 info.clientPackage = conn.binding.client.info.packageName;
8505 info.clientLabel = conn.clientLabel;
8506 return info;
8507 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008508 }
8509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 return info;
8511 }
8512
8513 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8514 int flags) {
8515 synchronized (this) {
8516 ArrayList<ActivityManager.RunningServiceInfo> res
8517 = new ArrayList<ActivityManager.RunningServiceInfo>();
8518
8519 if (mServices.size() > 0) {
8520 Iterator<ServiceRecord> it = mServices.values().iterator();
8521 while (it.hasNext() && res.size() < maxNum) {
8522 res.add(makeRunningServiceInfoLocked(it.next()));
8523 }
8524 }
8525
8526 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8527 ServiceRecord r = mRestartingServices.get(i);
8528 ActivityManager.RunningServiceInfo info =
8529 makeRunningServiceInfoLocked(r);
8530 info.restarting = r.nextRestartTime;
8531 res.add(info);
8532 }
8533
8534 return res;
8535 }
8536 }
8537
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008538 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8539 synchronized (this) {
8540 ServiceRecord r = mServices.get(name);
8541 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008542 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8543 for (int i=0; i<conn.size(); i++) {
8544 if (conn.get(i).clientIntent != null) {
8545 return conn.get(i).clientIntent;
8546 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008547 }
8548 }
8549 }
8550 }
8551 return null;
8552 }
8553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 private final ServiceRecord findServiceLocked(ComponentName name,
8555 IBinder token) {
8556 ServiceRecord r = mServices.get(name);
8557 return r == token ? r : null;
8558 }
8559
8560 private final class ServiceLookupResult {
8561 final ServiceRecord record;
8562 final String permission;
8563
8564 ServiceLookupResult(ServiceRecord _record, String _permission) {
8565 record = _record;
8566 permission = _permission;
8567 }
8568 };
8569
8570 private ServiceLookupResult findServiceLocked(Intent service,
8571 String resolvedType) {
8572 ServiceRecord r = null;
8573 if (service.getComponent() != null) {
8574 r = mServices.get(service.getComponent());
8575 }
8576 if (r == null) {
8577 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8578 r = mServicesByIntent.get(filter);
8579 }
8580
8581 if (r == null) {
8582 try {
8583 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008584 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 service, resolvedType, 0);
8586 ServiceInfo sInfo =
8587 rInfo != null ? rInfo.serviceInfo : null;
8588 if (sInfo == null) {
8589 return null;
8590 }
8591
8592 ComponentName name = new ComponentName(
8593 sInfo.applicationInfo.packageName, sInfo.name);
8594 r = mServices.get(name);
8595 } catch (RemoteException ex) {
8596 // pm is in same process, this will never happen.
8597 }
8598 }
8599 if (r != null) {
8600 int callingPid = Binder.getCallingPid();
8601 int callingUid = Binder.getCallingUid();
8602 if (checkComponentPermission(r.permission,
8603 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8604 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008605 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 + " from pid=" + callingPid
8607 + ", uid=" + callingUid
8608 + " requires " + r.permission);
8609 return new ServiceLookupResult(null, r.permission);
8610 }
8611 return new ServiceLookupResult(r, null);
8612 }
8613 return null;
8614 }
8615
8616 private class ServiceRestarter implements Runnable {
8617 private ServiceRecord mService;
8618
8619 void setService(ServiceRecord service) {
8620 mService = service;
8621 }
8622
8623 public void run() {
8624 synchronized(ActivityManagerService.this) {
8625 performServiceRestartLocked(mService);
8626 }
8627 }
8628 }
8629
8630 private ServiceLookupResult retrieveServiceLocked(Intent service,
8631 String resolvedType, int callingPid, int callingUid) {
8632 ServiceRecord r = null;
8633 if (service.getComponent() != null) {
8634 r = mServices.get(service.getComponent());
8635 }
8636 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8637 r = mServicesByIntent.get(filter);
8638 if (r == null) {
8639 try {
8640 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008641 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008642 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 ServiceInfo sInfo =
8644 rInfo != null ? rInfo.serviceInfo : null;
8645 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008646 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 ": not found");
8648 return null;
8649 }
8650
8651 ComponentName name = new ComponentName(
8652 sInfo.applicationInfo.packageName, sInfo.name);
8653 r = mServices.get(name);
8654 if (r == null) {
8655 filter = new Intent.FilterComparison(service.cloneFilter());
8656 ServiceRestarter res = new ServiceRestarter();
8657 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8658 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8659 synchronized (stats) {
8660 ss = stats.getServiceStatsLocked(
8661 sInfo.applicationInfo.uid, sInfo.packageName,
8662 sInfo.name);
8663 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008664 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008665 res.setService(r);
8666 mServices.put(name, r);
8667 mServicesByIntent.put(filter, r);
8668
8669 // Make sure this component isn't in the pending list.
8670 int N = mPendingServices.size();
8671 for (int i=0; i<N; i++) {
8672 ServiceRecord pr = mPendingServices.get(i);
8673 if (pr.name.equals(name)) {
8674 mPendingServices.remove(i);
8675 i--;
8676 N--;
8677 }
8678 }
8679 }
8680 } catch (RemoteException ex) {
8681 // pm is in same process, this will never happen.
8682 }
8683 }
8684 if (r != null) {
8685 if (checkComponentPermission(r.permission,
8686 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8687 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008688 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 + " from pid=" + Binder.getCallingPid()
8690 + ", uid=" + Binder.getCallingUid()
8691 + " requires " + r.permission);
8692 return new ServiceLookupResult(null, r.permission);
8693 }
8694 return new ServiceLookupResult(r, null);
8695 }
8696 return null;
8697 }
8698
Dianne Hackborn287952c2010-09-22 22:34:31 -07008699 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8700 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8701 + why + " of " + r + " in app " + r.app);
8702 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8703 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008704 long now = SystemClock.uptimeMillis();
8705 if (r.executeNesting == 0 && r.app != null) {
8706 if (r.app.executingServices.size() == 0) {
8707 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8708 msg.obj = r.app;
8709 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8710 }
8711 r.app.executingServices.add(r);
8712 }
8713 r.executeNesting++;
8714 r.executingStart = now;
8715 }
8716
8717 private final void sendServiceArgsLocked(ServiceRecord r,
8718 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008719 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008720 if (N == 0) {
8721 return;
8722 }
8723
Dianne Hackborn39792d22010-08-19 18:01:52 -07008724 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008726 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008727 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8728 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008729 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008730 // If somehow we got a dummy start at the front, then
8731 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008732 continue;
8733 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008734 si.deliveredTime = SystemClock.uptimeMillis();
8735 r.deliveredStarts.add(si);
8736 si.deliveryCount++;
8737 if (si.targetPermissionUid >= 0) {
8738 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008739 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008740 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008741 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 if (!oomAdjusted) {
8743 oomAdjusted = true;
8744 updateOomAdjLocked(r.app);
8745 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008746 int flags = 0;
8747 if (si.deliveryCount > 0) {
8748 flags |= Service.START_FLAG_RETRY;
8749 }
8750 if (si.doneExecutingCount > 0) {
8751 flags |= Service.START_FLAG_REDELIVERY;
8752 }
8753 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008754 } catch (RemoteException e) {
8755 // Remote process gone... we'll let the normal cleanup take
8756 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008757 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008758 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008760 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 break;
8762 }
8763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764 }
8765
8766 private final boolean requestServiceBindingLocked(ServiceRecord r,
8767 IntentBindRecord i, boolean rebind) {
8768 if (r.app == null || r.app.thread == null) {
8769 // If service is not currently running, can't yet bind.
8770 return false;
8771 }
8772 if ((!i.requested || rebind) && i.apps.size() > 0) {
8773 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008774 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008775 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8776 if (!rebind) {
8777 i.requested = true;
8778 }
8779 i.hasBound = true;
8780 i.doRebind = false;
8781 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008782 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008783 return false;
8784 }
8785 }
8786 return true;
8787 }
8788
8789 private final void requestServiceBindingsLocked(ServiceRecord r) {
8790 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8791 while (bindings.hasNext()) {
8792 IntentBindRecord i = bindings.next();
8793 if (!requestServiceBindingLocked(r, i, false)) {
8794 break;
8795 }
8796 }
8797 }
8798
8799 private final void realStartServiceLocked(ServiceRecord r,
8800 ProcessRecord app) throws RemoteException {
8801 if (app.thread == null) {
8802 throw new RemoteException();
8803 }
8804
8805 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008806 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807
8808 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008809 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008810 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811
8812 boolean created = false;
8813 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008814 mStringBuilder.setLength(0);
8815 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008816 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008817 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008818 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 synchronized (r.stats.getBatteryStats()) {
8820 r.stats.startLaunchedLocked();
8821 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008822 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008823 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008824 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008825 created = true;
8826 } finally {
8827 if (!created) {
8828 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008829 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 }
8831 }
8832
8833 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008834
8835 // If the service is in the started state, and there are no
8836 // pending arguments, then fake up one so its onStartCommand() will
8837 // be called.
8838 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8839 r.lastStartId++;
8840 if (r.lastStartId < 1) {
8841 r.lastStartId = 1;
8842 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008843 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008844 }
8845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 sendServiceArgsLocked(r, true);
8847 }
8848
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008849 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8850 boolean allowCancel) {
8851 boolean canceled = false;
8852
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008853 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008854 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008855 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008856
8857 // Any delivered but not yet finished starts should be put back
8858 // on the pending list.
8859 final int N = r.deliveredStarts.size();
8860 if (N > 0) {
8861 for (int i=N-1; i>=0; i--) {
8862 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008863 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008864 if (si.intent == null) {
8865 // We'll generate this again if needed.
8866 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8867 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8868 r.pendingStarts.add(0, si);
8869 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8870 dur *= 2;
8871 if (minDuration < dur) minDuration = dur;
8872 if (resetTime < dur) resetTime = dur;
8873 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008874 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008875 + r.name);
8876 canceled = true;
8877 }
8878 }
8879 r.deliveredStarts.clear();
8880 }
8881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008882 r.totalRestartCount++;
8883 if (r.restartDelay == 0) {
8884 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008885 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 } else {
8887 // If it has been a "reasonably long time" since the service
8888 // was started, then reset our restart duration back to
8889 // the beginning, so we don't infinitely increase the duration
8890 // on a service that just occasionally gets killed (which is
8891 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008892 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008894 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008896 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008897 if (r.restartDelay < minDuration) {
8898 r.restartDelay = minDuration;
8899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 }
8901 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008902
8903 r.nextRestartTime = now + r.restartDelay;
8904
8905 // Make sure that we don't end up restarting a bunch of services
8906 // all at the same time.
8907 boolean repeat;
8908 do {
8909 repeat = false;
8910 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8911 ServiceRecord r2 = mRestartingServices.get(i);
8912 if (r2 != r && r.nextRestartTime
8913 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8914 && r.nextRestartTime
8915 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8916 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8917 r.restartDelay = r.nextRestartTime - now;
8918 repeat = true;
8919 break;
8920 }
8921 }
8922 } while (repeat);
8923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 if (!mRestartingServices.contains(r)) {
8925 mRestartingServices.add(r);
8926 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008927
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008928 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008931 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008933 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008935 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008936 r.shortName, r.restartDelay);
8937
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008938 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 }
8940
8941 final void performServiceRestartLocked(ServiceRecord r) {
8942 if (!mRestartingServices.contains(r)) {
8943 return;
8944 }
8945 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8946 }
8947
8948 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8949 if (r.restartDelay == 0) {
8950 return false;
8951 }
8952 r.resetRestartCounter();
8953 mRestartingServices.remove(r);
8954 mHandler.removeCallbacks(r.restarter);
8955 return true;
8956 }
8957
8958 private final boolean bringUpServiceLocked(ServiceRecord r,
8959 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008960 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008961 //r.dump(" ");
8962
Dianne Hackborn36124872009-10-08 16:22:03 -07008963 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 sendServiceArgsLocked(r, false);
8965 return true;
8966 }
8967
8968 if (!whileRestarting && r.restartDelay > 0) {
8969 // If waiting for a restart, then do nothing.
8970 return true;
8971 }
8972
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008973 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008974
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008975 // We are now bringing the service up, so no longer in the
8976 // restarting state.
8977 mRestartingServices.remove(r);
8978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 final String appName = r.processName;
8980 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8981 if (app != null && app.thread != null) {
8982 try {
8983 realStartServiceLocked(r, app);
8984 return true;
8985 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008986 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008987 }
8988
8989 // If a dead object exception was thrown -- fall through to
8990 // restart the application.
8991 }
8992
Dianne Hackborn36124872009-10-08 16:22:03 -07008993 // Not running -- get it started, and enqueue this service record
8994 // to be executed when the app comes up.
8995 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8996 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008997 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008998 + r.appInfo.packageName + "/"
8999 + r.appInfo.uid + " for service "
9000 + r.intent.getIntent() + ": process is bad");
9001 bringDownServiceLocked(r, true);
9002 return false;
9003 }
9004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 mPendingServices.add(r);
9007 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009009 return true;
9010 }
9011
9012 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009013 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009014 //r.dump(" ");
9015
9016 // Does it still need to run?
9017 if (!force && r.startRequested) {
9018 return;
9019 }
9020 if (r.connections.size() > 0) {
9021 if (!force) {
9022 // XXX should probably keep a count of the number of auto-create
9023 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009024 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009026 ArrayList<ConnectionRecord> cr = it.next();
9027 for (int i=0; i<cr.size(); i++) {
9028 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9029 return;
9030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 }
9032 }
9033 }
9034
9035 // Report to all of the connections that the service is no longer
9036 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009037 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009038 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009039 ArrayList<ConnectionRecord> c = it.next();
9040 for (int i=0; i<c.size(); i++) {
9041 try {
9042 c.get(i).conn.connected(r.name, null);
9043 } catch (Exception e) {
9044 Slog.w(TAG, "Failure disconnecting service " + r.name +
9045 " to connection " + c.get(i).conn.asBinder() +
9046 " (in " + c.get(i).binding.client.processName + ")", e);
9047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009048 }
9049 }
9050 }
9051
9052 // Tell the service that it has been unbound.
9053 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9054 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9055 while (it.hasNext()) {
9056 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009057 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 + ": hasBound=" + ibr.hasBound);
9059 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9060 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009061 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 updateOomAdjLocked(r.app);
9063 ibr.hasBound = false;
9064 r.app.thread.scheduleUnbindService(r,
9065 ibr.intent.getIntent());
9066 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009067 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 + r.shortName, e);
9069 serviceDoneExecutingLocked(r, true);
9070 }
9071 }
9072 }
9073 }
9074
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009075 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009076 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 System.identityHashCode(r), r.shortName,
9078 (r.app != null) ? r.app.pid : -1);
9079
9080 mServices.remove(r.name);
9081 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 r.totalRestartCount = 0;
9083 unscheduleServiceRestartLocked(r);
9084
9085 // Also make sure it is not on the pending list.
9086 int N = mPendingServices.size();
9087 for (int i=0; i<N; i++) {
9088 if (mPendingServices.get(i) == r) {
9089 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009090 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 i--;
9092 N--;
9093 }
9094 }
9095
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009096 r.cancelNotification();
9097 r.isForeground = false;
9098 r.foregroundId = 0;
9099 r.foregroundNoti = null;
9100
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009101 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009102 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009103 r.pendingStarts.clear();
9104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009105 if (r.app != null) {
9106 synchronized (r.stats.getBatteryStats()) {
9107 r.stats.stopLaunchedLocked();
9108 }
9109 r.app.services.remove(r);
9110 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009112 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 mStoppingServices.add(r);
9114 updateOomAdjLocked(r.app);
9115 r.app.thread.scheduleStopService(r);
9116 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009117 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 + r.shortName, e);
9119 serviceDoneExecutingLocked(r, true);
9120 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009121 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009123 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009124 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 }
9126 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009127 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009128 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 }
Vairavan Srinivasan50b9b942010-12-23 13:51:48 -08009130
9131 if (r.bindings.size() > 0) {
9132 r.bindings.clear();
9133 }
9134
9135 if (r.restarter instanceof ServiceRestarter) {
9136 ((ServiceRestarter)r.restarter).setService(null);
9137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009138 }
9139
9140 ComponentName startServiceLocked(IApplicationThread caller,
9141 Intent service, String resolvedType,
9142 int callingPid, int callingUid) {
9143 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009144 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 + " type=" + resolvedType + " args=" + service.getExtras());
9146
9147 if (caller != null) {
9148 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9149 if (callerApp == null) {
9150 throw new SecurityException(
9151 "Unable to find app for caller " + caller
9152 + " (pid=" + Binder.getCallingPid()
9153 + ") when starting service " + service);
9154 }
9155 }
9156
9157 ServiceLookupResult res =
9158 retrieveServiceLocked(service, resolvedType,
9159 callingPid, callingUid);
9160 if (res == null) {
9161 return null;
9162 }
9163 if (res.record == null) {
9164 return new ComponentName("!", res.permission != null
9165 ? res.permission : "private to package");
9166 }
9167 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009168 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9169 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009171 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 }
9173 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009174 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175 r.lastStartId++;
9176 if (r.lastStartId < 1) {
9177 r.lastStartId = 1;
9178 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009179 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9180 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 r.lastActivity = SystemClock.uptimeMillis();
9182 synchronized (r.stats.getBatteryStats()) {
9183 r.stats.startRunningLocked();
9184 }
9185 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9186 return new ComponentName("!", "Service process is bad");
9187 }
9188 return r.name;
9189 }
9190 }
9191
9192 public ComponentName startService(IApplicationThread caller, Intent service,
9193 String resolvedType) {
9194 // Refuse possible leaked file descriptors
9195 if (service != null && service.hasFileDescriptors() == true) {
9196 throw new IllegalArgumentException("File descriptors passed in Intent");
9197 }
9198
9199 synchronized(this) {
9200 final int callingPid = Binder.getCallingPid();
9201 final int callingUid = Binder.getCallingUid();
9202 final long origId = Binder.clearCallingIdentity();
9203 ComponentName res = startServiceLocked(caller, service,
9204 resolvedType, callingPid, callingUid);
9205 Binder.restoreCallingIdentity(origId);
9206 return res;
9207 }
9208 }
9209
9210 ComponentName startServiceInPackage(int uid,
9211 Intent service, String resolvedType) {
9212 synchronized(this) {
9213 final long origId = Binder.clearCallingIdentity();
9214 ComponentName res = startServiceLocked(null, service,
9215 resolvedType, -1, uid);
9216 Binder.restoreCallingIdentity(origId);
9217 return res;
9218 }
9219 }
9220
9221 public int stopService(IApplicationThread caller, Intent service,
9222 String resolvedType) {
9223 // Refuse possible leaked file descriptors
9224 if (service != null && service.hasFileDescriptors() == true) {
9225 throw new IllegalArgumentException("File descriptors passed in Intent");
9226 }
9227
9228 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009229 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 + " type=" + resolvedType);
9231
9232 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9233 if (caller != null && callerApp == null) {
9234 throw new SecurityException(
9235 "Unable to find app for caller " + caller
9236 + " (pid=" + Binder.getCallingPid()
9237 + ") when stopping service " + service);
9238 }
9239
9240 // If this service is active, make sure it is stopped.
9241 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9242 if (r != null) {
9243 if (r.record != null) {
9244 synchronized (r.record.stats.getBatteryStats()) {
9245 r.record.stats.stopRunningLocked();
9246 }
9247 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009248 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 final long origId = Binder.clearCallingIdentity();
9250 bringDownServiceLocked(r.record, false);
9251 Binder.restoreCallingIdentity(origId);
9252 return 1;
9253 }
9254 return -1;
9255 }
9256 }
9257
9258 return 0;
9259 }
9260
9261 public IBinder peekService(Intent service, String resolvedType) {
9262 // Refuse possible leaked file descriptors
9263 if (service != null && service.hasFileDescriptors() == true) {
9264 throw new IllegalArgumentException("File descriptors passed in Intent");
9265 }
9266
9267 IBinder ret = null;
9268
9269 synchronized(this) {
9270 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9271
9272 if (r != null) {
9273 // r.record is null if findServiceLocked() failed the caller permission check
9274 if (r.record == null) {
9275 throw new SecurityException(
9276 "Permission Denial: Accessing service " + r.record.name
9277 + " from pid=" + Binder.getCallingPid()
9278 + ", uid=" + Binder.getCallingUid()
9279 + " requires " + r.permission);
9280 }
9281 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9282 if (ib != null) {
9283 ret = ib.binder;
9284 }
9285 }
9286 }
9287
9288 return ret;
9289 }
9290
9291 public boolean stopServiceToken(ComponentName className, IBinder token,
9292 int startId) {
9293 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009294 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 + " " + token + " startId=" + startId);
9296 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009297 if (r != null) {
9298 if (startId >= 0) {
9299 // Asked to only stop if done with all work. Note that
9300 // to avoid leaks, we will take this as dropping all
9301 // start items up to and including this one.
9302 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9303 if (si != null) {
9304 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009305 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9306 cur.removeUriPermissionsLocked();
9307 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009308 break;
9309 }
9310 }
9311 }
9312
9313 if (r.lastStartId != startId) {
9314 return false;
9315 }
9316
9317 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009318 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009319 + " is last, but have " + r.deliveredStarts.size()
9320 + " remaining args");
9321 }
9322 }
9323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 synchronized (r.stats.getBatteryStats()) {
9325 r.stats.stopRunningLocked();
9326 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009327 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009328 }
9329 final long origId = Binder.clearCallingIdentity();
9330 bringDownServiceLocked(r, false);
9331 Binder.restoreCallingIdentity(origId);
9332 return true;
9333 }
9334 }
9335 return false;
9336 }
9337
9338 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009339 int id, Notification notification, boolean removeNotification) {
9340 final long origId = Binder.clearCallingIdentity();
9341 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 synchronized(this) {
9343 ServiceRecord r = findServiceLocked(className, token);
9344 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009345 if (id != 0) {
9346 if (notification == null) {
9347 throw new IllegalArgumentException("null notification");
9348 }
9349 if (r.foregroundId != id) {
9350 r.cancelNotification();
9351 r.foregroundId = id;
9352 }
9353 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9354 r.foregroundNoti = notification;
9355 r.isForeground = true;
9356 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 if (r.app != null) {
9358 updateServiceForegroundLocked(r.app, true);
9359 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009360 } else {
9361 if (r.isForeground) {
9362 r.isForeground = false;
9363 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009364 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009365 updateServiceForegroundLocked(r.app, true);
9366 }
9367 }
9368 if (removeNotification) {
9369 r.cancelNotification();
9370 r.foregroundId = 0;
9371 r.foregroundNoti = null;
9372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009373 }
9374 }
9375 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009376 } finally {
9377 Binder.restoreCallingIdentity(origId);
9378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 }
9380
9381 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9382 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009383 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009384 if (sr.isForeground) {
9385 anyForeground = true;
9386 break;
9387 }
9388 }
9389 if (anyForeground != proc.foregroundServices) {
9390 proc.foregroundServices = anyForeground;
9391 if (oomAdj) {
9392 updateOomAdjLocked();
9393 }
9394 }
9395 }
9396
9397 public int bindService(IApplicationThread caller, IBinder token,
9398 Intent service, String resolvedType,
9399 IServiceConnection connection, int flags) {
9400 // Refuse possible leaked file descriptors
9401 if (service != null && service.hasFileDescriptors() == true) {
9402 throw new IllegalArgumentException("File descriptors passed in Intent");
9403 }
9404
9405 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009406 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009407 + " type=" + resolvedType + " conn=" + connection.asBinder()
9408 + " flags=0x" + Integer.toHexString(flags));
9409 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9410 if (callerApp == null) {
9411 throw new SecurityException(
9412 "Unable to find app for caller " + caller
9413 + " (pid=" + Binder.getCallingPid()
9414 + ") when binding service " + service);
9415 }
9416
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009417 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009418 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009419 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009421 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 return 0;
9423 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009424 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 }
9426
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009427 int clientLabel = 0;
9428 PendingIntent clientIntent = null;
9429
9430 if (callerApp.info.uid == Process.SYSTEM_UID) {
9431 // Hacky kind of thing -- allow system stuff to tell us
9432 // what they are, so we can report this elsewhere for
9433 // others to know why certain services are running.
9434 try {
9435 clientIntent = (PendingIntent)service.getParcelableExtra(
9436 Intent.EXTRA_CLIENT_INTENT);
9437 } catch (RuntimeException e) {
9438 }
9439 if (clientIntent != null) {
9440 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9441 if (clientLabel != 0) {
9442 // There are no useful extras in the intent, trash them.
9443 // System code calling with this stuff just needs to know
9444 // this will happen.
9445 service = service.cloneFilter();
9446 }
9447 }
9448 }
9449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009450 ServiceLookupResult res =
9451 retrieveServiceLocked(service, resolvedType,
9452 Binder.getCallingPid(), Binder.getCallingUid());
9453 if (res == null) {
9454 return 0;
9455 }
9456 if (res.record == null) {
9457 return -1;
9458 }
9459 ServiceRecord s = res.record;
9460
9461 final long origId = Binder.clearCallingIdentity();
9462
9463 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009464 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009465 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009466 }
9467
9468 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9469 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009470 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471
9472 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009473 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9474 if (clist == null) {
9475 clist = new ArrayList<ConnectionRecord>();
9476 s.connections.put(binder, clist);
9477 }
9478 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 b.connections.add(c);
9480 if (activity != null) {
9481 if (activity.connections == null) {
9482 activity.connections = new HashSet<ConnectionRecord>();
9483 }
9484 activity.connections.add(c);
9485 }
9486 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009487 clist = mServiceConnections.get(binder);
9488 if (clist == null) {
9489 clist = new ArrayList<ConnectionRecord>();
9490 mServiceConnections.put(binder, clist);
9491 }
9492 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493
9494 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9495 s.lastActivity = SystemClock.uptimeMillis();
9496 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9497 return 0;
9498 }
9499 }
9500
9501 if (s.app != null) {
9502 // This could have made the service more important.
9503 updateOomAdjLocked(s.app);
9504 }
9505
Joe Onorato8a9b2202010-02-26 18:56:32 -08009506 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 + ": received=" + b.intent.received
9508 + " apps=" + b.intent.apps.size()
9509 + " doRebind=" + b.intent.doRebind);
9510
9511 if (s.app != null && b.intent.received) {
9512 // Service is already running, so we can immediately
9513 // publish the connection.
9514 try {
9515 c.conn.connected(s.name, b.intent.binder);
9516 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009517 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 + " to connection " + c.conn.asBinder()
9519 + " (in " + c.binding.client.processName + ")", e);
9520 }
9521
9522 // If this is the first app connected back to this binding,
9523 // and the service had previously asked to be told when
9524 // rebound, then do so.
9525 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9526 requestServiceBindingLocked(s, b.intent, true);
9527 }
9528 } else if (!b.intent.requested) {
9529 requestServiceBindingLocked(s, b.intent, false);
9530 }
9531
9532 Binder.restoreCallingIdentity(origId);
9533 }
9534
9535 return 1;
9536 }
9537
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009538 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009539 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009540 IBinder binder = c.conn.asBinder();
9541 AppBindRecord b = c.binding;
9542 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009543 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9544 if (clist != null) {
9545 clist.remove(c);
9546 if (clist.size() == 0) {
9547 s.connections.remove(binder);
9548 }
9549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 b.connections.remove(c);
9551 if (c.activity != null && c.activity != skipAct) {
9552 if (c.activity.connections != null) {
9553 c.activity.connections.remove(c);
9554 }
9555 }
9556 if (b.client != skipApp) {
9557 b.client.connections.remove(c);
9558 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009559 clist = mServiceConnections.get(binder);
9560 if (clist != null) {
9561 clist.remove(c);
9562 if (clist.size() == 0) {
9563 mServiceConnections.remove(binder);
9564 }
9565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566
9567 if (b.connections.size() == 0) {
9568 b.intent.apps.remove(b.client);
9569 }
9570
Joe Onorato8a9b2202010-02-26 18:56:32 -08009571 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 + ": shouldUnbind=" + b.intent.hasBound);
9573 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9574 && b.intent.hasBound) {
9575 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009576 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 updateOomAdjLocked(s.app);
9578 b.intent.hasBound = false;
9579 // Assume the client doesn't want to know about a rebind;
9580 // we will deal with that later if it asks for one.
9581 b.intent.doRebind = false;
9582 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9583 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009584 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585 serviceDoneExecutingLocked(s, true);
9586 }
9587 }
9588
9589 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9590 bringDownServiceLocked(s, false);
9591 }
9592 }
9593
9594 public boolean unbindService(IServiceConnection connection) {
9595 synchronized (this) {
9596 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009597 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009598 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9599 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009600 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601 + connection.asBinder());
9602 return false;
9603 }
9604
9605 final long origId = Binder.clearCallingIdentity();
9606
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009607 while (clist.size() > 0) {
9608 ConnectionRecord r = clist.get(0);
9609 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009611 if (r.binding.service.app != null) {
9612 // This could have made the service less important.
9613 updateOomAdjLocked(r.binding.service.app);
9614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 }
9616
9617 Binder.restoreCallingIdentity(origId);
9618 }
9619
9620 return true;
9621 }
9622
9623 public void publishService(IBinder token, Intent intent, IBinder service) {
9624 // Refuse possible leaked file descriptors
9625 if (intent != null && intent.hasFileDescriptors() == true) {
9626 throw new IllegalArgumentException("File descriptors passed in Intent");
9627 }
9628
9629 synchronized(this) {
9630 if (!(token instanceof ServiceRecord)) {
9631 throw new IllegalArgumentException("Invalid service token");
9632 }
9633 ServiceRecord r = (ServiceRecord)token;
9634
9635 final long origId = Binder.clearCallingIdentity();
9636
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009637 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 + " " + intent + ": " + service);
9639 if (r != null) {
9640 Intent.FilterComparison filter
9641 = new Intent.FilterComparison(intent);
9642 IntentBindRecord b = r.bindings.get(filter);
9643 if (b != null && !b.received) {
9644 b.binder = service;
9645 b.requested = true;
9646 b.received = true;
9647 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009648 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 = r.connections.values().iterator();
9650 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009651 ArrayList<ConnectionRecord> clist = it.next();
9652 for (int i=0; i<clist.size(); i++) {
9653 ConnectionRecord c = clist.get(i);
9654 if (!filter.equals(c.binding.intent.intent)) {
9655 if (DEBUG_SERVICE) Slog.v(
9656 TAG, "Not publishing to: " + c);
9657 if (DEBUG_SERVICE) Slog.v(
9658 TAG, "Bound intent: " + c.binding.intent.intent);
9659 if (DEBUG_SERVICE) Slog.v(
9660 TAG, "Published intent: " + intent);
9661 continue;
9662 }
9663 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9664 try {
9665 c.conn.connected(r.name, service);
9666 } catch (Exception e) {
9667 Slog.w(TAG, "Failure sending service " + r.name +
9668 " to connection " + c.conn.asBinder() +
9669 " (in " + c.binding.client.processName + ")", e);
9670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 }
9672 }
9673 }
9674 }
9675
9676 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9677
9678 Binder.restoreCallingIdentity(origId);
9679 }
9680 }
9681 }
9682
9683 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9684 // Refuse possible leaked file descriptors
9685 if (intent != null && intent.hasFileDescriptors() == true) {
9686 throw new IllegalArgumentException("File descriptors passed in Intent");
9687 }
9688
9689 synchronized(this) {
9690 if (!(token instanceof ServiceRecord)) {
9691 throw new IllegalArgumentException("Invalid service token");
9692 }
9693 ServiceRecord r = (ServiceRecord)token;
9694
9695 final long origId = Binder.clearCallingIdentity();
9696
9697 if (r != null) {
9698 Intent.FilterComparison filter
9699 = new Intent.FilterComparison(intent);
9700 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009701 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 + " at " + b + ": apps="
9703 + (b != null ? b.apps.size() : 0));
9704 if (b != null) {
9705 if (b.apps.size() > 0) {
9706 // Applications have already bound since the last
9707 // unbind, so just rebind right here.
9708 requestServiceBindingLocked(r, b, true);
9709 } else {
9710 // Note to tell the service the next time there is
9711 // a new client.
9712 b.doRebind = true;
9713 }
9714 }
9715
9716 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9717
9718 Binder.restoreCallingIdentity(origId);
9719 }
9720 }
9721 }
9722
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009723 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009724 synchronized(this) {
9725 if (!(token instanceof ServiceRecord)) {
9726 throw new IllegalArgumentException("Invalid service token");
9727 }
9728 ServiceRecord r = (ServiceRecord)token;
9729 boolean inStopping = mStoppingServices.contains(token);
9730 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009732 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 + " with incorrect token: given " + token
9734 + ", expected " + r);
9735 return;
9736 }
9737
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009738 if (type == 1) {
9739 // This is a call from a service start... take care of
9740 // book-keeping.
9741 r.callStart = true;
9742 switch (res) {
9743 case Service.START_STICKY_COMPATIBILITY:
9744 case Service.START_STICKY: {
9745 // We are done with the associated start arguments.
9746 r.findDeliveredStart(startId, true);
9747 // Don't stop if killed.
9748 r.stopIfKilled = false;
9749 break;
9750 }
9751 case Service.START_NOT_STICKY: {
9752 // We are done with the associated start arguments.
9753 r.findDeliveredStart(startId, true);
9754 if (r.lastStartId == startId) {
9755 // There is no more work, and this service
9756 // doesn't want to hang around if killed.
9757 r.stopIfKilled = true;
9758 }
9759 break;
9760 }
9761 case Service.START_REDELIVER_INTENT: {
9762 // We'll keep this item until they explicitly
9763 // call stop for it, but keep track of the fact
9764 // that it was delivered.
9765 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9766 if (si != null) {
9767 si.deliveryCount = 0;
9768 si.doneExecutingCount++;
9769 // Don't stop if killed.
9770 r.stopIfKilled = true;
9771 }
9772 break;
9773 }
9774 default:
9775 throw new IllegalArgumentException(
9776 "Unknown service start result: " + res);
9777 }
9778 if (res == Service.START_STICKY_COMPATIBILITY) {
9779 r.callStart = false;
9780 }
9781 }
9782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783 final long origId = Binder.clearCallingIdentity();
9784 serviceDoneExecutingLocked(r, inStopping);
9785 Binder.restoreCallingIdentity(origId);
9786 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009787 Slog.w(TAG, "Done executing unknown service from pid "
9788 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 }
9790 }
9791 }
9792
9793 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009794 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9795 + ": nesting=" + r.executeNesting
9796 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009797 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 r.executeNesting--;
9799 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009800 if (DEBUG_SERVICE) Slog.v(TAG,
9801 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 r.app.executingServices.remove(r);
9803 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009804 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9805 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9807 }
9808 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009809 if (DEBUG_SERVICE) Slog.v(TAG,
9810 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811 mStoppingServices.remove(r);
Mattias Petersson5f619b72010-10-27 09:32:51 +02009812 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814 updateOomAdjLocked(r.app);
9815 }
9816 }
9817
9818 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009819 String anrMessage = null;
9820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 synchronized(this) {
9822 if (proc.executingServices.size() == 0 || proc.thread == null) {
9823 return;
9824 }
9825 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9826 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9827 ServiceRecord timeout = null;
9828 long nextTime = 0;
9829 while (it.hasNext()) {
9830 ServiceRecord sr = it.next();
9831 if (sr.executingStart < maxTime) {
9832 timeout = sr;
9833 break;
9834 }
9835 if (sr.executingStart > nextTime) {
9836 nextTime = sr.executingStart;
9837 }
9838 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009839 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009840 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009841 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 } else {
9843 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9844 msg.obj = proc;
9845 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9846 }
9847 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009848
9849 if (anrMessage != null) {
9850 appNotResponding(proc, null, null, anrMessage);
9851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 }
9853
9854 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009855 // BACKUP AND RESTORE
9856 // =========================================================
9857
9858 // Cause the target app to be launched if necessary and its backup agent
9859 // instantiated. The backup agent will invoke backupAgentCreated() on the
9860 // activity manager to announce its creation.
9861 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009862 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009863 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9864
9865 synchronized(this) {
9866 // !!! TODO: currently no check here that we're already bound
9867 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9868 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9869 synchronized (stats) {
9870 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9871 }
9872
9873 BackupRecord r = new BackupRecord(ss, app, backupMode);
9874 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9875 // startProcessLocked() returns existing proc's record if it's already running
9876 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009877 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009878 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009879 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009880 return false;
9881 }
9882
9883 r.app = proc;
9884 mBackupTarget = r;
9885 mBackupAppName = app.packageName;
9886
Christopher Tate6fa95972009-06-05 18:43:55 -07009887 // Try not to kill the process during backup
9888 updateOomAdjLocked(proc);
9889
Christopher Tate181fafa2009-05-14 11:12:14 -07009890 // If the process is already attached, schedule the creation of the backup agent now.
9891 // If it is not yet live, this will be done when it attaches to the framework.
9892 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009893 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009894 try {
9895 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9896 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009897 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009898 }
9899 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009900 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009901 }
9902 // Invariants: at this point, the target app process exists and the application
9903 // is either already running or in the process of coming up. mBackupTarget and
9904 // mBackupAppName describe the app, so that when it binds back to the AM we
9905 // know that it's scheduled for a backup-agent operation.
9906 }
9907
9908 return true;
9909 }
9910
9911 // A backup agent has just come up
9912 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009913 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009914 + " = " + agent);
9915
9916 synchronized(this) {
9917 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009918 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009919 return;
9920 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009921 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009922
Dianne Hackborn06740692010-09-22 22:46:21 -07009923 long oldIdent = Binder.clearCallingIdentity();
9924 try {
9925 IBackupManager bm = IBackupManager.Stub.asInterface(
9926 ServiceManager.getService(Context.BACKUP_SERVICE));
9927 bm.agentConnected(agentPackageName, agent);
9928 } catch (RemoteException e) {
9929 // can't happen; the backup manager service is local
9930 } catch (Exception e) {
9931 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9932 e.printStackTrace();
9933 } finally {
9934 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009935 }
9936 }
9937
9938 // done with this agent
9939 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009940 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009941 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009942 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009943 return;
9944 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009945
9946 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009947 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009948 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009949 return;
9950 }
9951
Christopher Tate181fafa2009-05-14 11:12:14 -07009952 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009953 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009954 return;
9955 }
9956
Christopher Tate6fa95972009-06-05 18:43:55 -07009957 ProcessRecord proc = mBackupTarget.app;
9958 mBackupTarget = null;
9959 mBackupAppName = null;
9960
9961 // Not backing this app up any more; reset its OOM adjustment
9962 updateOomAdjLocked(proc);
9963
Christopher Tatec7b31e32009-06-10 15:49:30 -07009964 // If the app crashed during backup, 'thread' will be null here
9965 if (proc.thread != null) {
9966 try {
9967 proc.thread.scheduleDestroyBackupAgent(appInfo);
9968 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009969 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009970 e.printStackTrace();
9971 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009972 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009973 }
9974 }
9975 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 // BROADCASTS
9977 // =========================================================
9978
Josh Bartel7f208742010-02-25 11:01:44 -06009979 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 List cur) {
9981 final ContentResolver resolver = mContext.getContentResolver();
9982 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9983 if (list == null) {
9984 return cur;
9985 }
9986 int N = list.size();
9987 for (int i=0; i<N; i++) {
9988 Intent intent = list.get(i);
9989 if (filter.match(resolver, intent, true, TAG) >= 0) {
9990 if (cur == null) {
9991 cur = new ArrayList<Intent>();
9992 }
9993 cur.add(intent);
9994 }
9995 }
9996 return cur;
9997 }
9998
9999 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010000 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 + mBroadcastsScheduled);
10002
10003 if (mBroadcastsScheduled) {
10004 return;
10005 }
10006 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10007 mBroadcastsScheduled = true;
10008 }
10009
10010 public Intent registerReceiver(IApplicationThread caller,
10011 IIntentReceiver receiver, IntentFilter filter, String permission) {
10012 synchronized(this) {
10013 ProcessRecord callerApp = null;
10014 if (caller != null) {
10015 callerApp = getRecordForAppLocked(caller);
10016 if (callerApp == null) {
10017 throw new SecurityException(
10018 "Unable to find app for caller " + caller
10019 + " (pid=" + Binder.getCallingPid()
10020 + ") when registering receiver " + receiver);
10021 }
10022 }
10023
10024 List allSticky = null;
10025
10026 // Look for any matching sticky broadcasts...
10027 Iterator actions = filter.actionsIterator();
10028 if (actions != null) {
10029 while (actions.hasNext()) {
10030 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010031 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 }
10033 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010034 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 }
10036
10037 // The first sticky in the list is returned directly back to
10038 // the client.
10039 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10040
Joe Onorato8a9b2202010-02-26 18:56:32 -080010041 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 + ": " + sticky);
10043
10044 if (receiver == null) {
10045 return sticky;
10046 }
10047
10048 ReceiverList rl
10049 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10050 if (rl == null) {
10051 rl = new ReceiverList(this, callerApp,
10052 Binder.getCallingPid(),
10053 Binder.getCallingUid(), receiver);
10054 if (rl.app != null) {
10055 rl.app.receivers.add(rl);
10056 } else {
10057 try {
10058 receiver.asBinder().linkToDeath(rl, 0);
10059 } catch (RemoteException e) {
10060 return sticky;
10061 }
10062 rl.linkedToDeath = true;
10063 }
10064 mRegisteredReceivers.put(receiver.asBinder(), rl);
10065 }
10066 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10067 rl.add(bf);
10068 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010069 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 }
10071 mReceiverResolver.addFilter(bf);
10072
10073 // Enqueue broadcasts for all existing stickies that match
10074 // this filter.
10075 if (allSticky != null) {
10076 ArrayList receivers = new ArrayList();
10077 receivers.add(bf);
10078
10079 int N = allSticky.size();
10080 for (int i=0; i<N; i++) {
10081 Intent intent = (Intent)allSticky.get(i);
10082 BroadcastRecord r = new BroadcastRecord(intent, null,
10083 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010084 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010085 if (mParallelBroadcasts.size() == 0) {
10086 scheduleBroadcastsLocked();
10087 }
10088 mParallelBroadcasts.add(r);
10089 }
10090 }
10091
10092 return sticky;
10093 }
10094 }
10095
10096 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010097 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098
10099 boolean doNext = false;
10100
10101 synchronized(this) {
10102 ReceiverList rl
10103 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10104 if (rl != null) {
10105 if (rl.curBroadcast != null) {
10106 BroadcastRecord r = rl.curBroadcast;
10107 doNext = finishReceiverLocked(
10108 receiver.asBinder(), r.resultCode, r.resultData,
10109 r.resultExtras, r.resultAbort, true);
10110 }
10111
10112 if (rl.app != null) {
10113 rl.app.receivers.remove(rl);
10114 }
10115 removeReceiverLocked(rl);
10116 if (rl.linkedToDeath) {
10117 rl.linkedToDeath = false;
10118 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10119 }
10120 }
10121 }
10122
10123 if (!doNext) {
10124 return;
10125 }
10126
10127 final long origId = Binder.clearCallingIdentity();
10128 processNextBroadcast(false);
10129 trimApplications();
10130 Binder.restoreCallingIdentity(origId);
10131 }
10132
10133 void removeReceiverLocked(ReceiverList rl) {
10134 mRegisteredReceivers.remove(rl.receiver.asBinder());
10135 int N = rl.size();
10136 for (int i=0; i<N; i++) {
10137 mReceiverResolver.removeFilter(rl.get(i));
10138 }
10139 }
10140
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010141 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10142 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10143 ProcessRecord r = mLruProcesses.get(i);
10144 if (r.thread != null) {
10145 try {
10146 r.thread.dispatchPackageBroadcast(cmd, packages);
10147 } catch (RemoteException ex) {
10148 }
10149 }
10150 }
10151 }
10152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 private final int broadcastIntentLocked(ProcessRecord callerApp,
10154 String callerPackage, Intent intent, String resolvedType,
10155 IIntentReceiver resultTo, int resultCode, String resultData,
10156 Bundle map, String requiredPermission,
10157 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10158 intent = new Intent(intent);
10159
Joe Onorato8a9b2202010-02-26 18:56:32 -080010160 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010161 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10162 + " ordered=" + ordered);
10163 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010164 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 }
10166
10167 // Handle special intents: if this broadcast is from the package
10168 // manager about a package being removed, we need to remove all of
10169 // its activities from the history stack.
10170 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10171 intent.getAction());
10172 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10173 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010174 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 || uidRemoved) {
10176 if (checkComponentPermission(
10177 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10178 callingPid, callingUid, -1)
10179 == PackageManager.PERMISSION_GRANTED) {
10180 if (uidRemoved) {
10181 final Bundle intentExtras = intent.getExtras();
10182 final int uid = intentExtras != null
10183 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10184 if (uid >= 0) {
10185 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10186 synchronized (bs) {
10187 bs.removeUidStatsLocked(uid);
10188 }
10189 }
10190 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010191 // If resources are unvailble just force stop all
10192 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010193 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010194 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10195 if (list != null && (list.length > 0)) {
10196 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010197 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010198 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010199 sendPackageBroadcastLocked(
10200 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010201 }
10202 } else {
10203 Uri data = intent.getData();
10204 String ssp;
10205 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10206 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10207 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010208 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010209 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010210 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10211 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10212 new String[] {ssp});
10213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010214 }
10215 }
10216 }
10217 } else {
10218 String msg = "Permission Denial: " + intent.getAction()
10219 + " broadcast from " + callerPackage + " (pid=" + callingPid
10220 + ", uid=" + callingUid + ")"
10221 + " requires "
10222 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010223 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010224 throw new SecurityException(msg);
10225 }
10226 }
10227
10228 /*
10229 * If this is the time zone changed action, queue up a message that will reset the timezone
10230 * of all currently running processes. This message will get queued up before the broadcast
10231 * happens.
10232 */
10233 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10234 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10235 }
10236
Dianne Hackborn854060af2009-07-09 18:14:31 -070010237 /*
10238 * Prevent non-system code (defined here to be non-persistent
10239 * processes) from sending protected broadcasts.
10240 */
10241 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10242 || callingUid == Process.SHELL_UID || callingUid == 0) {
10243 // Always okay.
10244 } else if (callerApp == null || !callerApp.persistent) {
10245 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010246 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010247 intent.getAction())) {
10248 String msg = "Permission Denial: not allowed to send broadcast "
10249 + intent.getAction() + " from pid="
10250 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010251 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010252 throw new SecurityException(msg);
10253 }
10254 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010255 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010256 return BROADCAST_SUCCESS;
10257 }
10258 }
10259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 // Add to the sticky list if requested.
10261 if (sticky) {
10262 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10263 callingPid, callingUid)
10264 != PackageManager.PERMISSION_GRANTED) {
10265 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10266 + callingPid + ", uid=" + callingUid
10267 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010268 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010269 throw new SecurityException(msg);
10270 }
10271 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010272 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010273 + " and enforce permission " + requiredPermission);
10274 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10275 }
10276 if (intent.getComponent() != null) {
10277 throw new SecurityException(
10278 "Sticky broadcasts can't target a specific component");
10279 }
10280 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10281 if (list == null) {
10282 list = new ArrayList<Intent>();
10283 mStickyBroadcasts.put(intent.getAction(), list);
10284 }
10285 int N = list.size();
10286 int i;
10287 for (i=0; i<N; i++) {
10288 if (intent.filterEquals(list.get(i))) {
10289 // This sticky already exists, replace it.
10290 list.set(i, new Intent(intent));
10291 break;
10292 }
10293 }
10294 if (i >= N) {
10295 list.add(new Intent(intent));
10296 }
10297 }
10298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 // Figure out who all will receive this broadcast.
10300 List receivers = null;
10301 List<BroadcastFilter> registeredReceivers = null;
10302 try {
10303 if (intent.getComponent() != null) {
10304 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010305 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010306 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 if (ai != null) {
10308 receivers = new ArrayList();
10309 ResolveInfo ri = new ResolveInfo();
10310 ri.activityInfo = ai;
10311 receivers.add(ri);
10312 }
10313 } else {
10314 // Need to resolve the intent to interested receivers...
10315 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10316 == 0) {
10317 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010318 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010319 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 }
Mihai Preda074edef2009-05-18 17:13:31 +020010321 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 }
10323 } catch (RemoteException ex) {
10324 // pm is in same process, this will never happen.
10325 }
10326
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010327 final boolean replacePending =
10328 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10329
Joe Onorato8a9b2202010-02-26 18:56:32 -080010330 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010331 + " replacePending=" + replacePending);
10332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10334 if (!ordered && NR > 0) {
10335 // If we are not serializing this broadcast, then send the
10336 // registered receivers separately so they don't wait for the
10337 // components to be launched.
10338 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10339 callerPackage, callingPid, callingUid, requiredPermission,
10340 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010341 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010342 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 TAG, "Enqueueing parallel broadcast " + r
10344 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010345 boolean replaced = false;
10346 if (replacePending) {
10347 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10348 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010349 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010350 "***** DROPPING PARALLEL: " + intent);
10351 mParallelBroadcasts.set(i, r);
10352 replaced = true;
10353 break;
10354 }
10355 }
10356 }
10357 if (!replaced) {
10358 mParallelBroadcasts.add(r);
10359 scheduleBroadcastsLocked();
10360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 registeredReceivers = null;
10362 NR = 0;
10363 }
10364
10365 // Merge into one list.
10366 int ir = 0;
10367 if (receivers != null) {
10368 // A special case for PACKAGE_ADDED: do not allow the package
10369 // being added to see this broadcast. This prevents them from
10370 // using this as a back door to get run as soon as they are
10371 // installed. Maybe in the future we want to have a special install
10372 // broadcast or such for apps, but we'd like to deliberately make
10373 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010374 String skipPackages[] = null;
10375 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10376 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10377 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10378 Uri data = intent.getData();
10379 if (data != null) {
10380 String pkgName = data.getSchemeSpecificPart();
10381 if (pkgName != null) {
10382 skipPackages = new String[] { pkgName };
10383 }
10384 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010385 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010386 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010387 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010388 if (skipPackages != null && (skipPackages.length > 0)) {
10389 for (String skipPackage : skipPackages) {
10390 if (skipPackage != null) {
10391 int NT = receivers.size();
10392 for (int it=0; it<NT; it++) {
10393 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10394 if (curt.activityInfo.packageName.equals(skipPackage)) {
10395 receivers.remove(it);
10396 it--;
10397 NT--;
10398 }
10399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 }
10401 }
10402 }
10403
10404 int NT = receivers != null ? receivers.size() : 0;
10405 int it = 0;
10406 ResolveInfo curt = null;
10407 BroadcastFilter curr = null;
10408 while (it < NT && ir < NR) {
10409 if (curt == null) {
10410 curt = (ResolveInfo)receivers.get(it);
10411 }
10412 if (curr == null) {
10413 curr = registeredReceivers.get(ir);
10414 }
10415 if (curr.getPriority() >= curt.priority) {
10416 // Insert this broadcast record into the final list.
10417 receivers.add(it, curr);
10418 ir++;
10419 curr = null;
10420 it++;
10421 NT++;
10422 } else {
10423 // Skip to the next ResolveInfo in the final list.
10424 it++;
10425 curt = null;
10426 }
10427 }
10428 }
10429 while (ir < NR) {
10430 if (receivers == null) {
10431 receivers = new ArrayList();
10432 }
10433 receivers.add(registeredReceivers.get(ir));
10434 ir++;
10435 }
10436
10437 if ((receivers != null && receivers.size() > 0)
10438 || resultTo != null) {
10439 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10440 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010441 receivers, resultTo, resultCode, resultData, map, ordered,
10442 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010443 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010444 TAG, "Enqueueing ordered broadcast " + r
10445 + ": prev had " + mOrderedBroadcasts.size());
10446 if (DEBUG_BROADCAST) {
10447 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010448 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010450 boolean replaced = false;
10451 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010452 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010453 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010454 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010455 "***** DROPPING ORDERED: " + intent);
10456 mOrderedBroadcasts.set(i, r);
10457 replaced = true;
10458 break;
10459 }
10460 }
10461 }
10462 if (!replaced) {
10463 mOrderedBroadcasts.add(r);
10464 scheduleBroadcastsLocked();
10465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 }
10467
10468 return BROADCAST_SUCCESS;
10469 }
10470
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010471 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010472 // Refuse possible leaked file descriptors
10473 if (intent != null && intent.hasFileDescriptors() == true) {
10474 throw new IllegalArgumentException("File descriptors passed in Intent");
10475 }
10476
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010477 int flags = intent.getFlags();
10478
10479 if (!mProcessesReady) {
10480 // if the caller really truly claims to know what they're doing, go
10481 // ahead and allow the broadcast without launching any receivers
10482 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10483 intent = new Intent(intent);
10484 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10485 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10486 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10487 + " before boot completion");
10488 throw new IllegalStateException("Cannot broadcast before boot completed");
10489 }
10490 }
10491
10492 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10493 throw new IllegalArgumentException(
10494 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10495 }
10496
10497 return intent;
10498 }
10499
10500 public final int broadcastIntent(IApplicationThread caller,
10501 Intent intent, String resolvedType, IIntentReceiver resultTo,
10502 int resultCode, String resultData, Bundle map,
10503 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010504 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010505 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010507 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10508 final int callingPid = Binder.getCallingPid();
10509 final int callingUid = Binder.getCallingUid();
10510 final long origId = Binder.clearCallingIdentity();
10511 int res = broadcastIntentLocked(callerApp,
10512 callerApp != null ? callerApp.info.packageName : null,
10513 intent, resolvedType, resultTo,
10514 resultCode, resultData, map, requiredPermission, serialized,
10515 sticky, callingPid, callingUid);
10516 Binder.restoreCallingIdentity(origId);
10517 return res;
10518 }
10519 }
10520
10521 int broadcastIntentInPackage(String packageName, int uid,
10522 Intent intent, String resolvedType, IIntentReceiver resultTo,
10523 int resultCode, String resultData, Bundle map,
10524 String requiredPermission, boolean serialized, boolean sticky) {
10525 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010526 intent = verifyBroadcastLocked(intent);
10527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 final long origId = Binder.clearCallingIdentity();
10529 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10530 resultTo, resultCode, resultData, map, requiredPermission,
10531 serialized, sticky, -1, uid);
10532 Binder.restoreCallingIdentity(origId);
10533 return res;
10534 }
10535 }
10536
10537 public final void unbroadcastIntent(IApplicationThread caller,
10538 Intent intent) {
10539 // Refuse possible leaked file descriptors
10540 if (intent != null && intent.hasFileDescriptors() == true) {
10541 throw new IllegalArgumentException("File descriptors passed in Intent");
10542 }
10543
10544 synchronized(this) {
10545 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10546 != PackageManager.PERMISSION_GRANTED) {
10547 String msg = "Permission Denial: unbroadcastIntent() from pid="
10548 + Binder.getCallingPid()
10549 + ", uid=" + Binder.getCallingUid()
10550 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010551 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 throw new SecurityException(msg);
10553 }
10554 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10555 if (list != null) {
10556 int N = list.size();
10557 int i;
10558 for (i=0; i<N; i++) {
10559 if (intent.filterEquals(list.get(i))) {
10560 list.remove(i);
10561 break;
10562 }
10563 }
10564 }
10565 }
10566 }
10567
10568 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10569 String resultData, Bundle resultExtras, boolean resultAbort,
10570 boolean explicit) {
10571 if (mOrderedBroadcasts.size() == 0) {
10572 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010573 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574 }
10575 return false;
10576 }
10577 BroadcastRecord r = mOrderedBroadcasts.get(0);
10578 if (r.receiver == null) {
10579 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010580 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 }
10582 return false;
10583 }
10584 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010585 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 return false;
10587 }
10588 int state = r.state;
10589 r.state = r.IDLE;
10590 if (state == r.IDLE) {
10591 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010592 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 }
10594 }
10595 r.receiver = null;
10596 r.intent.setComponent(null);
10597 if (r.curApp != null) {
10598 r.curApp.curReceiver = null;
10599 }
10600 if (r.curFilter != null) {
10601 r.curFilter.receiverList.curBroadcast = null;
10602 }
10603 r.curFilter = null;
10604 r.curApp = null;
10605 r.curComponent = null;
10606 r.curReceiver = null;
10607 mPendingBroadcast = null;
10608
10609 r.resultCode = resultCode;
10610 r.resultData = resultData;
10611 r.resultExtras = resultExtras;
10612 r.resultAbort = resultAbort;
10613
10614 // We will process the next receiver right now if this is finishing
10615 // an app receiver (which is always asynchronous) or after we have
10616 // come back from calling a receiver.
10617 return state == BroadcastRecord.APP_RECEIVE
10618 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10619 }
10620
10621 public void finishReceiver(IBinder who, int resultCode, String resultData,
10622 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010623 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010624
10625 // Refuse possible leaked file descriptors
10626 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10627 throw new IllegalArgumentException("File descriptors passed in Bundle");
10628 }
10629
10630 boolean doNext;
10631
10632 final long origId = Binder.clearCallingIdentity();
10633
10634 synchronized(this) {
10635 doNext = finishReceiverLocked(
10636 who, resultCode, resultData, resultExtras, resultAbort, true);
10637 }
10638
10639 if (doNext) {
10640 processNextBroadcast(false);
10641 }
10642 trimApplications();
10643
10644 Binder.restoreCallingIdentity(origId);
10645 }
10646
Jeff Brown4d94a762010-09-23 11:33:28 -070010647 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 if (r.nextReceiver > 0) {
10649 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10650 if (curReceiver instanceof BroadcastFilter) {
10651 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010652 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010653 System.identityHashCode(r),
10654 r.intent.getAction(),
10655 r.nextReceiver - 1,
10656 System.identityHashCode(bf));
10657 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010658 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010659 System.identityHashCode(r),
10660 r.intent.getAction(),
10661 r.nextReceiver - 1,
10662 ((ResolveInfo)curReceiver).toString());
10663 }
10664 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010665 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010667 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010668 System.identityHashCode(r),
10669 r.intent.getAction(),
10670 r.nextReceiver,
10671 "NONE");
10672 }
10673 }
10674
Jeff Brown4d94a762010-09-23 11:33:28 -070010675 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10676 if (! mPendingBroadcastTimeoutMessage) {
10677 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10678 mHandler.sendMessageAtTime(msg, timeoutTime);
10679 mPendingBroadcastTimeoutMessage = true;
10680 }
10681 }
10682
10683 private final void cancelBroadcastTimeoutLocked() {
10684 if (mPendingBroadcastTimeoutMessage) {
10685 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10686 mPendingBroadcastTimeoutMessage = false;
10687 }
10688 }
10689
10690 private final void broadcastTimeoutLocked(boolean fromMsg) {
10691 if (fromMsg) {
10692 mPendingBroadcastTimeoutMessage = false;
10693 }
10694
10695 if (mOrderedBroadcasts.size() == 0) {
10696 return;
10697 }
10698
10699 long now = SystemClock.uptimeMillis();
10700 BroadcastRecord r = mOrderedBroadcasts.get(0);
10701 if (fromMsg) {
10702 if (mDidDexOpt) {
10703 // Delay timeouts until dexopt finishes.
10704 mDidDexOpt = false;
10705 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10706 setBroadcastTimeoutLocked(timeoutTime);
10707 return;
10708 }
10709 if (! mProcessesReady) {
10710 // Only process broadcast timeouts if the system is ready. That way
10711 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10712 // to do heavy lifting for system up.
10713 return;
10714 }
10715
10716 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10717 if (timeoutTime > now) {
10718 // We can observe premature timeouts because we do not cancel and reset the
10719 // broadcast timeout message after each receiver finishes. Instead, we set up
10720 // an initial timeout then kick it down the road a little further as needed
10721 // when it expires.
10722 if (DEBUG_BROADCAST) Slog.v(TAG,
10723 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10724 + timeoutTime);
10725 setBroadcastTimeoutLocked(timeoutTime);
10726 return;
10727 }
10728 }
10729
10730 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10731 + ", started " + (now - r.receiverTime) + "ms ago");
10732 r.receiverTime = now;
10733 r.anrCount++;
10734
10735 // Current receiver has passed its expiration date.
10736 if (r.nextReceiver <= 0) {
10737 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10738 return;
10739 }
10740
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010741 ProcessRecord app = null;
10742 String anrMessage = null;
10743
Jeff Brown4d94a762010-09-23 11:33:28 -070010744 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10745 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10746 logBroadcastReceiverDiscardLocked(r);
10747 if (curReceiver instanceof BroadcastFilter) {
10748 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10749 if (bf.receiverList.pid != 0
10750 && bf.receiverList.pid != MY_PID) {
10751 synchronized (this.mPidsSelfLocked) {
10752 app = this.mPidsSelfLocked.get(
10753 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010756 } else {
10757 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010759
Jeff Brown4d94a762010-09-23 11:33:28 -070010760 if (app != null) {
10761 anrMessage = "Broadcast of " + r.intent.toString();
10762 }
10763
10764 if (mPendingBroadcast == r) {
10765 mPendingBroadcast = null;
10766 }
10767
10768 // Move on to the next receiver.
10769 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10770 r.resultExtras, r.resultAbort, true);
10771 scheduleBroadcastsLocked();
10772
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010773 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010774 // Post the ANR to the handler since we do not want to process ANRs while
10775 // potentially holding our lock.
10776 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 }
10779
10780 private final void processCurBroadcastLocked(BroadcastRecord r,
10781 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010782 if (DEBUG_BROADCAST) Slog.v(TAG,
10783 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 if (app.thread == null) {
10785 throw new RemoteException();
10786 }
10787 r.receiver = app.thread.asBinder();
10788 r.curApp = app;
10789 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010790 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791
10792 // Tell the application to launch this receiver.
10793 r.intent.setComponent(r.curComponent);
10794
10795 boolean started = false;
10796 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010797 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 "Delivering to component " + r.curComponent
10799 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010800 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10802 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010803 if (DEBUG_BROADCAST) Slog.v(TAG,
10804 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 started = true;
10806 } finally {
10807 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010808 if (DEBUG_BROADCAST) Slog.v(TAG,
10809 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 r.receiver = null;
10811 r.curApp = null;
10812 app.curReceiver = null;
10813 }
10814 }
10815
10816 }
10817
Jeff Brown4d94a762010-09-23 11:33:28 -070010818 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010819 Intent intent, int resultCode, String data, Bundle extras,
10820 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010821 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 if (app != null && app.thread != null) {
10823 // If we have an app thread, do the call through that so it is
10824 // correctly ordered with other one-way calls.
10825 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010826 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010828 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 }
10830 }
10831
Jeff Brown4d94a762010-09-23 11:33:28 -070010832 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 BroadcastFilter filter, boolean ordered) {
10834 boolean skip = false;
10835 if (filter.requiredPermission != null) {
10836 int perm = checkComponentPermission(filter.requiredPermission,
10837 r.callingPid, r.callingUid, -1);
10838 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010839 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010840 + r.intent.toString()
10841 + " from " + r.callerPackage + " (pid="
10842 + r.callingPid + ", uid=" + r.callingUid + ")"
10843 + " requires " + filter.requiredPermission
10844 + " due to registered receiver " + filter);
10845 skip = true;
10846 }
10847 }
10848 if (r.requiredPermission != null) {
10849 int perm = checkComponentPermission(r.requiredPermission,
10850 filter.receiverList.pid, filter.receiverList.uid, -1);
10851 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010852 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 + r.intent.toString()
10854 + " to " + filter.receiverList.app
10855 + " (pid=" + filter.receiverList.pid
10856 + ", uid=" + filter.receiverList.uid + ")"
10857 + " requires " + r.requiredPermission
10858 + " due to sender " + r.callerPackage
10859 + " (uid " + r.callingUid + ")");
10860 skip = true;
10861 }
10862 }
10863
10864 if (!skip) {
10865 // If this is not being sent as an ordered broadcast, then we
10866 // don't want to touch the fields that keep track of the current
10867 // state of ordered broadcasts.
10868 if (ordered) {
10869 r.receiver = filter.receiverList.receiver.asBinder();
10870 r.curFilter = filter;
10871 filter.receiverList.curBroadcast = r;
10872 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010873 if (filter.receiverList.app != null) {
10874 // Bump hosting application to no longer be in background
10875 // scheduling class. Note that we can't do that if there
10876 // isn't an app... but we can only be in that case for
10877 // things that directly call the IActivityManager API, which
10878 // are already core system stuff so don't matter for this.
10879 r.curApp = filter.receiverList.app;
10880 filter.receiverList.app.curReceiver = r;
10881 updateOomAdjLocked();
10882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 }
10884 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010885 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010886 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010887 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010888 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010889 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010890 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010892 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 if (ordered) {
10894 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10895 }
10896 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010897 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 if (ordered) {
10899 r.receiver = null;
10900 r.curFilter = null;
10901 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010902 if (filter.receiverList.app != null) {
10903 filter.receiverList.app.curReceiver = null;
10904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905 }
10906 }
10907 }
10908 }
10909
Dianne Hackborn12527f92009-11-11 17:39:50 -080010910 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10911 if (r.callingUid < 0) {
10912 // This was from a registerReceiver() call; ignore it.
10913 return;
10914 }
10915 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10916 MAX_BROADCAST_HISTORY-1);
10917 r.finishTime = SystemClock.uptimeMillis();
10918 mBroadcastHistory[0] = r;
10919 }
10920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 private final void processNextBroadcast(boolean fromMsg) {
10922 synchronized(this) {
10923 BroadcastRecord r;
10924
Joe Onorato8a9b2202010-02-26 18:56:32 -080010925 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010927 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928
10929 updateCpuStats();
10930
10931 if (fromMsg) {
10932 mBroadcastsScheduled = false;
10933 }
10934
10935 // First, deliver any non-serialized broadcasts right away.
10936 while (mParallelBroadcasts.size() > 0) {
10937 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010938 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010940 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010941 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 for (int i=0; i<N; i++) {
10943 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010944 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010945 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010947 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010949 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010950 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010951 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 }
10953
10954 // Now take care of the next serialized one...
10955
10956 // If we are waiting for a process to come up to handle the next
10957 // broadcast, then do nothing at this point. Just in case, we
10958 // check that the process we're waiting for still exists.
10959 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010960 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010961 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010962 + mPendingBroadcast.curApp);
10963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964
10965 boolean isDead;
10966 synchronized (mPidsSelfLocked) {
10967 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10968 }
10969 if (!isDead) {
10970 // It's still alive, so keep waiting
10971 return;
10972 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010973 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010975 mPendingBroadcast.state = BroadcastRecord.IDLE;
10976 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 mPendingBroadcast = null;
10978 }
10979 }
10980
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010981 boolean looped = false;
10982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 do {
10984 if (mOrderedBroadcasts.size() == 0) {
10985 // No more broadcasts pending, so all done!
10986 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010987 if (looped) {
10988 // If we had finished the last ordered broadcast, then
10989 // make sure all processes have correct oom and sched
10990 // adjustments.
10991 updateOomAdjLocked();
10992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010993 return;
10994 }
10995 r = mOrderedBroadcasts.get(0);
10996 boolean forceReceive = false;
10997
10998 // Ensure that even if something goes awry with the timeout
10999 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011000 // and continue to make progress.
11001 //
11002 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011003 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011004 // one time heavy lifting after system upgrades and can take
11005 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011007 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011008 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 if ((numReceivers > 0) &&
11010 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 + " now=" + now
11013 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011014 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 + " intent=" + r.intent
11016 + " numReceivers=" + numReceivers
11017 + " nextReceiver=" + r.nextReceiver
11018 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011019 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 forceReceive = true;
11021 r.state = BroadcastRecord.IDLE;
11022 }
11023 }
11024
11025 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011026 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 "processNextBroadcast() called when not idle (state="
11028 + r.state + ")");
11029 return;
11030 }
11031
11032 if (r.receivers == null || r.nextReceiver >= numReceivers
11033 || r.resultAbort || forceReceive) {
11034 // No more receivers for this broadcast! Send the final
11035 // result if requested...
11036 if (r.resultTo != null) {
11037 try {
11038 if (DEBUG_BROADCAST) {
11039 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011040 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 + " seq=" + seq + " app=" + r.callerApp);
11042 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011043 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011045 r.resultData, r.resultExtras, false, false);
Johannes Carlsson58975912010-10-27 10:08:10 +020011046 // Set this to null so that the reference
11047 // (local and remote) isnt kept in the mBroadcastHistory.
11048 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011050 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 }
11052 }
11053
Joe Onorato8a9b2202010-02-26 18:56:32 -080011054 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011055 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056
Joe Onorato8a9b2202010-02-26 18:56:32 -080011057 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011058 + r);
11059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011061 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 mOrderedBroadcasts.remove(0);
11063 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011064 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 continue;
11066 }
11067 } while (r == null);
11068
11069 // Get the next receiver...
11070 int recIdx = r.nextReceiver++;
11071
11072 // Keep track of when this receiver started, and make sure there
11073 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011074 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011076 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077
Joe Onorato8a9b2202010-02-26 18:56:32 -080011078 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011079 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011080 }
11081 if (! mPendingBroadcastTimeoutMessage) {
11082 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011083 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011084 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11085 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086 }
11087
11088 Object nextReceiver = r.receivers.get(recIdx);
11089 if (nextReceiver instanceof BroadcastFilter) {
11090 // Simple case: this is a registered receiver who gets
11091 // a direct call.
11092 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011093 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011094 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011096 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 if (r.receiver == null || !r.ordered) {
11098 // The receiver has already finished, so schedule to
11099 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011100 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11101 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 r.state = BroadcastRecord.IDLE;
11103 scheduleBroadcastsLocked();
11104 }
11105 return;
11106 }
11107
11108 // Hard case: need to instantiate the receiver, possibly
11109 // starting its application process to host it.
11110
11111 ResolveInfo info =
11112 (ResolveInfo)nextReceiver;
11113
11114 boolean skip = false;
11115 int perm = checkComponentPermission(info.activityInfo.permission,
11116 r.callingPid, r.callingUid,
11117 info.activityInfo.exported
11118 ? -1 : info.activityInfo.applicationInfo.uid);
11119 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011120 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 + r.intent.toString()
11122 + " from " + r.callerPackage + " (pid=" + r.callingPid
11123 + ", uid=" + r.callingUid + ")"
11124 + " requires " + info.activityInfo.permission
11125 + " due to receiver " + info.activityInfo.packageName
11126 + "/" + info.activityInfo.name);
11127 skip = true;
11128 }
11129 if (r.callingUid != Process.SYSTEM_UID &&
11130 r.requiredPermission != null) {
11131 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011132 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133 checkPermission(r.requiredPermission,
11134 info.activityInfo.applicationInfo.packageName);
11135 } catch (RemoteException e) {
11136 perm = PackageManager.PERMISSION_DENIED;
11137 }
11138 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011139 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 + r.intent + " to "
11141 + info.activityInfo.applicationInfo.packageName
11142 + " requires " + r.requiredPermission
11143 + " due to sender " + r.callerPackage
11144 + " (uid " + r.callingUid + ")");
11145 skip = true;
11146 }
11147 }
11148 if (r.curApp != null && r.curApp.crashing) {
11149 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011150 if (DEBUG_BROADCAST) Slog.v(TAG,
11151 "Skipping deliver ordered " + r + " to " + r.curApp
11152 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153 skip = true;
11154 }
11155
11156 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011157 if (DEBUG_BROADCAST) Slog.v(TAG,
11158 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 r.receiver = null;
11160 r.curFilter = null;
11161 r.state = BroadcastRecord.IDLE;
11162 scheduleBroadcastsLocked();
11163 return;
11164 }
11165
11166 r.state = BroadcastRecord.APP_RECEIVE;
11167 String targetProcess = info.activityInfo.processName;
11168 r.curComponent = new ComponentName(
11169 info.activityInfo.applicationInfo.packageName,
11170 info.activityInfo.name);
11171 r.curReceiver = info.activityInfo;
11172
11173 // Is this receiver's application already running?
11174 ProcessRecord app = getProcessRecordLocked(targetProcess,
11175 info.activityInfo.applicationInfo.uid);
11176 if (app != null && app.thread != null) {
11177 try {
11178 processCurBroadcastLocked(r, app);
11179 return;
11180 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011181 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 + r.curComponent, e);
11183 }
11184
11185 // If a dead object exception was thrown -- fall through to
11186 // restart the application.
11187 }
11188
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011189 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011190 if (DEBUG_BROADCAST) Slog.v(TAG,
11191 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 if ((r.curApp=startProcessLocked(targetProcess,
11193 info.activityInfo.applicationInfo, true,
11194 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011195 "broadcast", r.curComponent,
11196 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11197 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 // Ah, this recipient is unavailable. Finish it if necessary,
11199 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011200 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011201 + info.activityInfo.applicationInfo.packageName + "/"
11202 + info.activityInfo.applicationInfo.uid + " for broadcast "
11203 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011204 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11206 r.resultExtras, r.resultAbort, true);
11207 scheduleBroadcastsLocked();
11208 r.state = BroadcastRecord.IDLE;
11209 return;
11210 }
11211
11212 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011213 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 }
11215 }
11216
11217 // =========================================================
11218 // INSTRUMENTATION
11219 // =========================================================
11220
11221 public boolean startInstrumentation(ComponentName className,
11222 String profileFile, int flags, Bundle arguments,
11223 IInstrumentationWatcher watcher) {
11224 // Refuse possible leaked file descriptors
11225 if (arguments != null && arguments.hasFileDescriptors()) {
11226 throw new IllegalArgumentException("File descriptors passed in Bundle");
11227 }
11228
11229 synchronized(this) {
11230 InstrumentationInfo ii = null;
11231 ApplicationInfo ai = null;
11232 try {
11233 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011234 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011236 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 } catch (PackageManager.NameNotFoundException e) {
11238 }
11239 if (ii == null) {
11240 reportStartInstrumentationFailure(watcher, className,
11241 "Unable to find instrumentation info for: " + className);
11242 return false;
11243 }
11244 if (ai == null) {
11245 reportStartInstrumentationFailure(watcher, className,
11246 "Unable to find instrumentation target package: " + ii.targetPackage);
11247 return false;
11248 }
11249
11250 int match = mContext.getPackageManager().checkSignatures(
11251 ii.targetPackage, ii.packageName);
11252 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11253 String msg = "Permission Denial: starting instrumentation "
11254 + className + " from pid="
11255 + Binder.getCallingPid()
11256 + ", uid=" + Binder.getCallingPid()
11257 + " not allowed because package " + ii.packageName
11258 + " does not have a signature matching the target "
11259 + ii.targetPackage;
11260 reportStartInstrumentationFailure(watcher, className, msg);
11261 throw new SecurityException(msg);
11262 }
11263
11264 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011265 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 ProcessRecord app = addAppLocked(ai);
11267 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011268 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 app.instrumentationProfileFile = profileFile;
11270 app.instrumentationArguments = arguments;
11271 app.instrumentationWatcher = watcher;
11272 app.instrumentationResultClass = className;
11273 Binder.restoreCallingIdentity(origId);
11274 }
11275
11276 return true;
11277 }
11278
11279 /**
11280 * Report errors that occur while attempting to start Instrumentation. Always writes the
11281 * error to the logs, but if somebody is watching, send the report there too. This enables
11282 * the "am" command to report errors with more information.
11283 *
11284 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11285 * @param cn The component name of the instrumentation.
11286 * @param report The error report.
11287 */
11288 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11289 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011290 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 try {
11292 if (watcher != null) {
11293 Bundle results = new Bundle();
11294 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11295 results.putString("Error", report);
11296 watcher.instrumentationStatus(cn, -1, results);
11297 }
11298 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011299 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011300 }
11301 }
11302
11303 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11304 if (app.instrumentationWatcher != null) {
11305 try {
11306 // NOTE: IInstrumentationWatcher *must* be oneway here
11307 app.instrumentationWatcher.instrumentationFinished(
11308 app.instrumentationClass,
11309 resultCode,
11310 results);
11311 } catch (RemoteException e) {
11312 }
11313 }
11314 app.instrumentationWatcher = null;
11315 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011316 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 app.instrumentationProfileFile = null;
11318 app.instrumentationArguments = null;
11319
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011320 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 }
11322
11323 public void finishInstrumentation(IApplicationThread target,
11324 int resultCode, Bundle results) {
11325 // Refuse possible leaked file descriptors
11326 if (results != null && results.hasFileDescriptors()) {
11327 throw new IllegalArgumentException("File descriptors passed in Intent");
11328 }
11329
11330 synchronized(this) {
11331 ProcessRecord app = getRecordForAppLocked(target);
11332 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011333 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 return;
11335 }
11336 final long origId = Binder.clearCallingIdentity();
11337 finishInstrumentationLocked(app, resultCode, results);
11338 Binder.restoreCallingIdentity(origId);
11339 }
11340 }
11341
11342 // =========================================================
11343 // CONFIGURATION
11344 // =========================================================
11345
11346 public ConfigurationInfo getDeviceConfigurationInfo() {
11347 ConfigurationInfo config = new ConfigurationInfo();
11348 synchronized (this) {
11349 config.reqTouchScreen = mConfiguration.touchscreen;
11350 config.reqKeyboardType = mConfiguration.keyboard;
11351 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011352 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11353 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11355 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011356 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11357 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11359 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011360 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 }
11362 return config;
11363 }
11364
11365 public Configuration getConfiguration() {
11366 Configuration ci;
11367 synchronized(this) {
11368 ci = new Configuration(mConfiguration);
11369 }
11370 return ci;
11371 }
11372
11373 public void updateConfiguration(Configuration values) {
11374 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11375 "updateConfiguration()");
11376
11377 synchronized(this) {
11378 if (values == null && mWindowManager != null) {
11379 // sentinel: fetch the current configuration from the window manager
11380 values = mWindowManager.computeNewConfiguration();
11381 }
11382
11383 final long origId = Binder.clearCallingIdentity();
11384 updateConfigurationLocked(values, null);
11385 Binder.restoreCallingIdentity(origId);
11386 }
11387 }
11388
11389 /**
11390 * Do either or both things: (1) change the current configuration, and (2)
11391 * make sure the given activity is running with the (now) current
11392 * configuration. Returns true if the activity has been left running, or
11393 * false if <var>starting</var> is being destroyed to match the new
11394 * configuration.
11395 */
11396 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011397 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011398 int changes = 0;
11399
11400 boolean kept = true;
11401
11402 if (values != null) {
11403 Configuration newConfig = new Configuration(mConfiguration);
11404 changes = newConfig.updateFrom(values);
11405 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011406 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011407 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 }
11409
Doug Zongker2bec3d42009-12-04 12:52:44 -080011410 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411
11412 if (values.locale != null) {
11413 saveLocaleLocked(values.locale,
11414 !values.locale.equals(mConfiguration.locale),
11415 values.userSetLocale);
11416 }
11417
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011418 mConfigurationSeq++;
11419 if (mConfigurationSeq <= 0) {
11420 mConfigurationSeq = 1;
11421 }
11422 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011424 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011425
11426 AttributeCache ac = AttributeCache.instance();
11427 if (ac != null) {
11428 ac.updateConfiguration(mConfiguration);
11429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011431 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11432 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11433 msg.obj = new Configuration(mConfiguration);
11434 mHandler.sendMessage(msg);
11435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011437 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11438 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439 try {
11440 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011441 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011442 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 app.thread.scheduleConfigurationChanged(mConfiguration);
11444 }
11445 } catch (Exception e) {
11446 }
11447 }
11448 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011449 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11450 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11452 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011453 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11454 broadcastIntentLocked(null, null,
11455 new Intent(Intent.ACTION_LOCALE_CHANGED),
11456 null, null, 0, null, null,
11457 null, false, false, MY_PID, Process.SYSTEM_UID);
11458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 }
11460 }
11461
11462 if (changes != 0 && starting == null) {
11463 // If the configuration changed, and the caller is not already
11464 // in the process of starting an activity, then find the top
11465 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011466 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 }
11468
11469 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011470 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011471 if (kept) {
11472 // If this didn't result in the starting activity being
11473 // destroyed, then we need to make sure at this point that all
11474 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011475 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011477 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 }
11479 }
11480
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011481 if (values != null && mWindowManager != null) {
11482 mWindowManager.setNewConfiguration(mConfiguration);
11483 }
11484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 return kept;
11486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487
11488 /**
11489 * Save the locale. You must be inside a synchronized (this) block.
11490 */
11491 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11492 if(isDiff) {
11493 SystemProperties.set("user.language", l.getLanguage());
11494 SystemProperties.set("user.region", l.getCountry());
11495 }
11496
11497 if(isPersist) {
11498 SystemProperties.set("persist.sys.language", l.getLanguage());
11499 SystemProperties.set("persist.sys.country", l.getCountry());
11500 SystemProperties.set("persist.sys.localevar", l.getVariant());
11501 }
11502 }
11503
11504 // =========================================================
11505 // LIFETIME MANAGEMENT
11506 // =========================================================
11507
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011508 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11509 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011510 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011511 // This adjustment has already been computed. If we are calling
11512 // from the top, we may have already computed our adjustment with
11513 // an earlier hidden adjustment that isn't really for us... if
11514 // so, use the new hidden adjustment.
11515 if (!recursed && app.hidden) {
11516 app.curAdj = hiddenAdj;
11517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 return app.curAdj;
11519 }
11520
11521 if (app.thread == null) {
11522 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011523 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 return (app.curAdj=EMPTY_APP_ADJ);
11525 }
11526
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011527 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11528 // The max adjustment doesn't allow this app to be anything
11529 // below foreground, so it is not worth doing work for it.
11530 app.adjType = "fixed";
11531 app.adjSeq = mAdjSeq;
11532 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011533 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011534 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11535 return (app.curAdj=app.maxAdj);
11536 }
11537
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011538 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011539 app.adjSource = null;
11540 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011541 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011542 app.empty = false;
11543 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544
The Android Open Source Project4df24232009-03-05 14:34:35 -080011545 // Determine the importance of the process, starting with most
11546 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011548 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011550 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011551 // The last app on the list is the foreground app.
11552 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011553 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011554 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011555 } else if (app.instrumentationClass != null) {
11556 // Don't want to kill running instrumentation.
11557 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011558 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011559 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011560 } else if (app.curReceiver != null ||
11561 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11562 // An app that is currently receiving a broadcast also
11563 // counts as being in the foreground.
11564 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011565 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011566 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011567 } else if (app.executingServices.size() > 0) {
11568 // An app that is currently executing a service callback also
11569 // counts as being in the foreground.
11570 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011571 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011572 app.adjType = "exec-service";
11573 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011575 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011576 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011577 app.adjType = "foreground-service";
11578 } else if (app.forcingToForeground != null) {
11579 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011580 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011581 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011582 app.adjType = "force-foreground";
11583 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011584 } else if (app == mHeavyWeightProcess) {
11585 // We don't want to kill the current heavy-weight process.
11586 adj = HEAVY_WEIGHT_APP_ADJ;
11587 schedGroup = Process.THREAD_GROUP_DEFAULT;
11588 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011589 } else if (app == mHomeProcess) {
11590 // This process is hosting what we currently consider to be the
11591 // home app, so we don't want to let it go into the background.
11592 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011593 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011594 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595 } else if ((N=app.activities.size()) != 0) {
11596 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011597 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011599 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011600 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011601 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011603 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011605 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011606 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011607 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011608 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 break;
11610 }
11611 }
11612 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011613 // A very not-needed process. If this is lower in the lru list,
11614 // we will push it in to the empty bucket.
11615 app.hidden = true;
11616 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011617 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011618 adj = hiddenAdj;
11619 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 }
11621
Joe Onorato8a9b2202010-02-26 18:56:32 -080011622 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011623
The Android Open Source Project4df24232009-03-05 14:34:35 -080011624 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 // there are applications dependent on our services or providers, but
11626 // this gives us a baseline and makes sure we don't get into an
11627 // infinite recursion.
11628 app.adjSeq = mAdjSeq;
11629 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011630
Christopher Tate6fa95972009-06-05 18:43:55 -070011631 if (mBackupTarget != null && app == mBackupTarget.app) {
11632 // If possible we want to avoid killing apps while they're being backed up
11633 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011634 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011635 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011636 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011637 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011638 }
11639 }
11640
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011641 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11642 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 final long now = SystemClock.uptimeMillis();
11644 // This process is more important if the top activity is
11645 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011646 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011648 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011649 if (s.startRequested) {
11650 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11651 // This service has seen some activity within
11652 // recent memory, so we will keep its process ahead
11653 // of the background processes.
11654 if (adj > SECONDARY_SERVER_ADJ) {
11655 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011656 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011657 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011658 }
11659 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011660 // If we have let the service slide into the background
11661 // state, still have some text describing what it is doing
11662 // even though the service no longer has an impact.
11663 if (adj > SECONDARY_SERVER_ADJ) {
11664 app.adjType = "started-bg-services";
11665 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011666 // Don't kill this process because it is doing work; it
11667 // has said it is doing work.
11668 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011670 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11671 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011672 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 = s.connections.values().iterator();
11674 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011675 ArrayList<ConnectionRecord> clist = kt.next();
11676 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11677 // XXX should compute this based on the max of
11678 // all connected clients.
11679 ConnectionRecord cr = clist.get(i);
11680 if (cr.binding.client == app) {
11681 // Binding to ourself is not interesting.
11682 continue;
11683 }
11684 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11685 ProcessRecord client = cr.binding.client;
11686 int myHiddenAdj = hiddenAdj;
11687 if (myHiddenAdj > client.hiddenAdj) {
11688 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11689 myHiddenAdj = client.hiddenAdj;
11690 } else {
11691 myHiddenAdj = VISIBLE_APP_ADJ;
11692 }
11693 }
11694 int clientAdj = computeOomAdjLocked(
11695 client, myHiddenAdj, TOP_APP, true);
11696 if (adj > clientAdj) {
11697 adj = clientAdj >= VISIBLE_APP_ADJ
11698 ? clientAdj : VISIBLE_APP_ADJ;
11699 if (!client.hidden) {
11700 app.hidden = false;
11701 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011702 if (client.keeping) {
11703 app.keeping = true;
11704 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011705 app.adjType = "service";
11706 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11707 .REASON_SERVICE_IN_USE;
11708 app.adjSource = cr.binding.client;
11709 app.adjTarget = s.name;
11710 }
11711 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11712 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11713 schedGroup = Process.THREAD_GROUP_DEFAULT;
11714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 }
11716 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011717 ActivityRecord a = cr.activity;
11718 //if (a != null) {
11719 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11720 //}
11721 if (a != null && adj > FOREGROUND_APP_ADJ &&
11722 (a.state == ActivityState.RESUMED
11723 || a.state == ActivityState.PAUSING)) {
11724 adj = FOREGROUND_APP_ADJ;
11725 schedGroup = Process.THREAD_GROUP_DEFAULT;
11726 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011727 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011728 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11729 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011730 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011731 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 }
11734 }
11735 }
11736 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011737
Dianne Hackborn287952c2010-09-22 22:34:31 -070011738 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011739 // would like to avoid killing it unless it would prevent the current
11740 // application from running. By default we put the process in
11741 // with the rest of the background processes; as we scan through
11742 // its services we may bump it up from there.
11743 if (adj > hiddenAdj) {
11744 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011745 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011746 app.adjType = "bg-services";
11747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 }
11749
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011750 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11751 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011752 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011753 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11754 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011755 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011756 if (cpr.clients.size() != 0) {
11757 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11758 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11759 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011760 if (client == app) {
11761 // Being our own client is not interesting.
11762 continue;
11763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764 int myHiddenAdj = hiddenAdj;
11765 if (myHiddenAdj > client.hiddenAdj) {
11766 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11767 myHiddenAdj = client.hiddenAdj;
11768 } else {
11769 myHiddenAdj = FOREGROUND_APP_ADJ;
11770 }
11771 }
11772 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011773 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774 if (adj > clientAdj) {
11775 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011776 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011777 if (!client.hidden) {
11778 app.hidden = false;
11779 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011780 if (client.keeping) {
11781 app.keeping = true;
11782 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011783 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011784 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11785 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011786 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011787 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011789 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11790 schedGroup = Process.THREAD_GROUP_DEFAULT;
11791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011792 }
11793 }
11794 // If the provider has external (non-framework) process
11795 // dependencies, ensure that its adjustment is at least
11796 // FOREGROUND_APP_ADJ.
11797 if (cpr.externals != 0) {
11798 if (adj > FOREGROUND_APP_ADJ) {
11799 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011800 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011801 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011802 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011803 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011804 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011805 }
11806 }
11807 }
11808 }
11809
11810 app.curRawAdj = adj;
11811
Joe Onorato8a9b2202010-02-26 18:56:32 -080011812 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11814 if (adj > app.maxAdj) {
11815 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011816 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011817 schedGroup = Process.THREAD_GROUP_DEFAULT;
11818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011820 if (adj < HIDDEN_APP_MIN_ADJ) {
11821 app.keeping = true;
11822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823
11824 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011825 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 return adj;
11828 }
11829
11830 /**
11831 * Ask a given process to GC right now.
11832 */
11833 final void performAppGcLocked(ProcessRecord app) {
11834 try {
11835 app.lastRequestedGc = SystemClock.uptimeMillis();
11836 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011837 if (app.reportLowMemory) {
11838 app.reportLowMemory = false;
11839 app.thread.scheduleLowMemory();
11840 } else {
11841 app.thread.processInBackground();
11842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 }
11844 } catch (Exception e) {
11845 // whatever.
11846 }
11847 }
11848
11849 /**
11850 * Returns true if things are idle enough to perform GCs.
11851 */
Josh Bartel7f208742010-02-25 11:01:44 -060011852 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 return mParallelBroadcasts.size() == 0
11854 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011855 && (mSleeping || (mMainStack.mResumedActivity != null &&
11856 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011857 }
11858
11859 /**
11860 * Perform GCs on all processes that are waiting for it, but only
11861 * if things are idle.
11862 */
11863 final void performAppGcsLocked() {
11864 final int N = mProcessesToGc.size();
11865 if (N <= 0) {
11866 return;
11867 }
Josh Bartel7f208742010-02-25 11:01:44 -060011868 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011869 while (mProcessesToGc.size() > 0) {
11870 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011871 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011872 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11873 <= SystemClock.uptimeMillis()) {
11874 // To avoid spamming the system, we will GC processes one
11875 // at a time, waiting a few seconds between each.
11876 performAppGcLocked(proc);
11877 scheduleAppGcsLocked();
11878 return;
11879 } else {
11880 // It hasn't been long enough since we last GCed this
11881 // process... put it in the list to wait for its time.
11882 addProcessToGcListLocked(proc);
11883 break;
11884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 }
11886 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011887
11888 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 }
11890 }
11891
11892 /**
11893 * If all looks good, perform GCs on all processes waiting for them.
11894 */
11895 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011896 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 performAppGcsLocked();
11898 return;
11899 }
11900 // Still not idle, wait some more.
11901 scheduleAppGcsLocked();
11902 }
11903
11904 /**
11905 * Schedule the execution of all pending app GCs.
11906 */
11907 final void scheduleAppGcsLocked() {
11908 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011909
11910 if (mProcessesToGc.size() > 0) {
11911 // Schedule a GC for the time to the next process.
11912 ProcessRecord proc = mProcessesToGc.get(0);
11913 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11914
11915 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11916 long now = SystemClock.uptimeMillis();
11917 if (when < (now+GC_TIMEOUT)) {
11918 when = now + GC_TIMEOUT;
11919 }
11920 mHandler.sendMessageAtTime(msg, when);
11921 }
11922 }
11923
11924 /**
11925 * Add a process to the array of processes waiting to be GCed. Keeps the
11926 * list in sorted order by the last GC time. The process can't already be
11927 * on the list.
11928 */
11929 final void addProcessToGcListLocked(ProcessRecord proc) {
11930 boolean added = false;
11931 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11932 if (mProcessesToGc.get(i).lastRequestedGc <
11933 proc.lastRequestedGc) {
11934 added = true;
11935 mProcessesToGc.add(i+1, proc);
11936 break;
11937 }
11938 }
11939 if (!added) {
11940 mProcessesToGc.add(0, proc);
11941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942 }
11943
11944 /**
11945 * Set up to ask a process to GC itself. This will either do it
11946 * immediately, or put it on the list of processes to gc the next
11947 * time things are idle.
11948 */
11949 final void scheduleAppGcLocked(ProcessRecord app) {
11950 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011951 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 return;
11953 }
11954 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011955 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956 scheduleAppGcsLocked();
11957 }
11958 }
11959
Dianne Hackborn287952c2010-09-22 22:34:31 -070011960 final void checkExcessivePowerUsageLocked(boolean doKills) {
11961 updateCpuStatsNow();
11962
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011963 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011964 boolean doWakeKills = doKills;
11965 boolean doCpuKills = doKills;
11966 if (mLastPowerCheckRealtime == 0) {
11967 doWakeKills = false;
11968 }
11969 if (mLastPowerCheckUptime == 0) {
11970 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011971 }
11972 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011973 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011974 }
11975 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011976 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11977 final long curUptime = SystemClock.uptimeMillis();
11978 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11979 mLastPowerCheckRealtime = curRealtime;
11980 mLastPowerCheckUptime = curUptime;
11981 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11982 doWakeKills = false;
11983 }
11984 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11985 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011986 }
11987 int i = mLruProcesses.size();
11988 while (i > 0) {
11989 i--;
11990 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011991 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011992 long wtime;
11993 synchronized (stats) {
11994 wtime = stats.getProcessWakeTime(app.info.uid,
11995 app.pid, curRealtime);
11996 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011997 long wtimeUsed = wtime - app.lastWakeTime;
11998 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11999 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012000 StringBuilder sb = new StringBuilder(128);
12001 sb.append("Wake for ");
12002 app.toShortString(sb);
12003 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012004 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012005 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012006 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012007 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012008 sb.append((wtimeUsed*100)/realtimeSince);
12009 sb.append("%)");
12010 Slog.i(TAG, sb.toString());
12011 sb.setLength(0);
12012 sb.append("CPU for ");
12013 app.toShortString(sb);
12014 sb.append(": over ");
12015 TimeUtils.formatDuration(uptimeSince, sb);
12016 sb.append(" used ");
12017 TimeUtils.formatDuration(cputimeUsed, sb);
12018 sb.append(" (");
12019 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012020 sb.append("%)");
12021 Slog.i(TAG, sb.toString());
12022 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012023 // If a process has held a wake lock for more
12024 // than 50% of the time during this period,
12025 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012026 if (doWakeKills && realtimeSince > 0
12027 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12028 synchronized (stats) {
12029 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12030 realtimeSince, wtimeUsed);
12031 }
12032 Slog.w(TAG, "Excessive wake lock in " + app.processName
12033 + " (pid " + app.pid + "): held " + wtimeUsed
12034 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012035 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12036 app.processName, app.setAdj, "excessive wake lock");
12037 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012038 } else if (doCpuKills && uptimeSince > 0
12039 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12040 synchronized (stats) {
12041 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12042 uptimeSince, cputimeUsed);
12043 }
12044 Slog.w(TAG, "Excessive CPU in " + app.processName
12045 + " (pid " + app.pid + "): used " + cputimeUsed
12046 + " during " + uptimeSince);
12047 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12048 app.processName, app.setAdj, "excessive cpu");
12049 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012050 } else {
12051 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012052 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012053 }
12054 }
12055 }
12056 }
12057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 private final boolean updateOomAdjLocked(
12059 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12060 app.hiddenAdj = hiddenAdj;
12061
12062 if (app.thread == null) {
12063 return true;
12064 }
12065
Dianne Hackborn287952c2010-09-22 22:34:31 -070012066 final boolean wasKeeping = app.keeping;
12067
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012068 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012069
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012070 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012071 if (app.curRawAdj != app.setRawAdj) {
12072 if (app.curRawAdj > FOREGROUND_APP_ADJ
12073 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12074 // If this app is transitioning from foreground to
12075 // non-foreground, have it do a gc.
12076 scheduleAppGcLocked(app);
12077 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12078 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12079 // Likewise do a gc when an app is moving in to the
12080 // background (such as a service stopping).
12081 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012082 }
12083
12084 if (wasKeeping && !app.keeping) {
12085 // This app is no longer something we want to keep. Note
12086 // its current wake lock time to later know to kill it if
12087 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012088 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12089 synchronized (stats) {
12090 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12091 app.pid, SystemClock.elapsedRealtime());
12092 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012093 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012096 app.setRawAdj = app.curRawAdj;
12097 }
12098 if (adj != app.setAdj) {
12099 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012100 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012101 TAG, "Set app " + app.processName +
12102 " oom adj to " + adj);
12103 app.setAdj = adj;
12104 } else {
12105 return false;
12106 }
12107 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012108 if (app.setSchedGroup != app.curSchedGroup) {
12109 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012110 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012111 "Setting process group of " + app.processName
12112 + " to " + app.curSchedGroup);
12113 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012114 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012115 try {
12116 Process.setProcessGroup(app.pid, app.curSchedGroup);
12117 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012118 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012119 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012120 e.printStackTrace();
12121 } finally {
12122 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012123 }
12124 }
12125 if (false) {
12126 if (app.thread != null) {
12127 try {
12128 app.thread.setSchedulingGroup(app.curSchedGroup);
12129 } catch (RemoteException e) {
12130 }
12131 }
12132 }
12133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012134 }
12135
12136 return true;
12137 }
12138
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012139 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012140 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012141 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012142 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012143 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012144 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012145 }
12146 }
12147 return resumedActivity;
12148 }
12149
12150 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012151 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12153 int curAdj = app.curAdj;
12154 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12155 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12156
12157 mAdjSeq++;
12158
12159 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12160 if (res) {
12161 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12162 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12163 if (nowHidden != wasHidden) {
12164 // Changed to/from hidden state, so apps after it in the LRU
12165 // list may also be changed.
12166 updateOomAdjLocked();
12167 }
12168 }
12169 return res;
12170 }
12171
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012172 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012174 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012175 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12176
12177 if (false) {
12178 RuntimeException e = new RuntimeException();
12179 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012180 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012181 }
12182
12183 mAdjSeq++;
12184
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012185 // Let's determine how many processes we have running vs.
12186 // how many slots we have for background processes; we may want
12187 // to put multiple processes in a slot of there are enough of
12188 // them.
12189 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12190 int factor = (mLruProcesses.size()-4)/numSlots;
12191 if (factor < 1) factor = 1;
12192 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012193 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012195 // First try updating the OOM adjustment for each of the
12196 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012197 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012198 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12199 while (i > 0) {
12200 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012201 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012202 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012203 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012204 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012206 step++;
12207 if (step >= factor) {
12208 step = 0;
12209 curHiddenAdj++;
12210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012211 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012212 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012213 if (!app.killedBackground) {
12214 numHidden++;
12215 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012216 Slog.i(TAG, "No longer want " + app.processName
12217 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012218 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12219 app.processName, app.setAdj, "too many background");
12220 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012221 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012222 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012223 }
12224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012225 } else {
12226 didOomAdj = false;
12227 }
12228 }
12229
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012230 // If we return false, we will fall back on killing processes to
12231 // have a fixed limit. Do this if a limit has been requested; else
12232 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12234 }
12235
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012236 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012237 synchronized (this) {
12238 int i;
12239
12240 // First remove any unused application processes whose package
12241 // has been removed.
12242 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12243 final ProcessRecord app = mRemovedProcesses.get(i);
12244 if (app.activities.size() == 0
12245 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012246 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 TAG, "Exiting empty application process "
12248 + app.processName + " ("
12249 + (app.thread != null ? app.thread.asBinder() : null)
12250 + ")\n");
12251 if (app.pid > 0 && app.pid != MY_PID) {
12252 Process.killProcess(app.pid);
12253 } else {
12254 try {
12255 app.thread.scheduleExit();
12256 } catch (Exception e) {
12257 // Ignore exceptions.
12258 }
12259 }
12260 cleanUpApplicationRecordLocked(app, false, -1);
12261 mRemovedProcesses.remove(i);
12262
12263 if (app.persistent) {
12264 if (app.persistent) {
12265 addAppLocked(app.info);
12266 }
12267 }
12268 }
12269 }
12270
12271 // Now try updating the OOM adjustment for each of the
12272 // application processes based on their current state.
12273 // If the setOomAdj() API is not supported, then go with our
12274 // back-up plan...
12275 if (!updateOomAdjLocked()) {
12276
12277 // Count how many processes are running services.
12278 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012279 for (i=mLruProcesses.size()-1; i>=0; i--) {
12280 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012281
12282 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012283 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012284 // Don't count processes holding services against our
12285 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012286 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012287 TAG, "Not trimming app " + app + " with services: "
12288 + app.services);
12289 numServiceProcs++;
12290 }
12291 }
12292
12293 int curMaxProcs = mProcessLimit;
12294 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12295 if (mAlwaysFinishActivities) {
12296 curMaxProcs = 1;
12297 }
12298 curMaxProcs += numServiceProcs;
12299
12300 // Quit as many processes as we can to get down to the desired
12301 // process count. First remove any processes that no longer
12302 // have activites running in them.
12303 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012304 i<mLruProcesses.size()
12305 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012306 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012307 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 // Quit an application only if it is not currently
12309 // running any activities.
12310 if (!app.persistent && app.activities.size() == 0
12311 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012312 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012313 TAG, "Exiting empty application process "
12314 + app.processName + " ("
12315 + (app.thread != null ? app.thread.asBinder() : null)
12316 + ")\n");
12317 if (app.pid > 0 && app.pid != MY_PID) {
12318 Process.killProcess(app.pid);
12319 } else {
12320 try {
12321 app.thread.scheduleExit();
12322 } catch (Exception e) {
12323 // Ignore exceptions.
12324 }
12325 }
12326 // todo: For now we assume the application is not buggy
12327 // or evil, and will quit as a result of our request.
12328 // Eventually we need to drive this off of the death
12329 // notification, and kill the process if it takes too long.
12330 cleanUpApplicationRecordLocked(app, false, i);
12331 i--;
12332 }
12333 }
12334
12335 // If we still have too many processes, now from the least
12336 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012337 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012338 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012339 " of " + curMaxProcs + " processes");
12340 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012341 i<mLruProcesses.size()
12342 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012343 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012344 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 // Quit the application only if we have a state saved for
12346 // all of its activities.
12347 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012348 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012349 int NUMA = app.activities.size();
12350 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012351 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012352 TAG, "Looking to quit " + app.processName);
12353 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012354 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012355 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012356 TAG, " " + r.intent.getComponent().flattenToShortString()
12357 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12358 canQuit = (r.haveState || !r.stateNotNeeded)
12359 && !r.visible && r.stopped;
12360 }
12361 if (canQuit) {
12362 // Finish all of the activities, and then the app itself.
12363 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012364 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012366 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012367 }
12368 r.resultTo = null;
12369 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012370 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 + app.processName + " ("
12372 + (app.thread != null ? app.thread.asBinder() : null)
12373 + ")\n");
12374 if (app.pid > 0 && app.pid != MY_PID) {
12375 Process.killProcess(app.pid);
12376 } else {
12377 try {
12378 app.thread.scheduleExit();
12379 } catch (Exception e) {
12380 // Ignore exceptions.
12381 }
12382 }
12383 // todo: For now we assume the application is not buggy
12384 // or evil, and will quit as a result of our request.
12385 // Eventually we need to drive this off of the death
12386 // notification, and kill the process if it takes too long.
12387 cleanUpApplicationRecordLocked(app, false, i);
12388 i--;
12389 //dump();
12390 }
12391 }
12392
12393 }
12394
12395 int curMaxActivities = MAX_ACTIVITIES;
12396 if (mAlwaysFinishActivities) {
12397 curMaxActivities = 1;
12398 }
12399
12400 // Finally, if there are too many activities now running, try to
12401 // finish as many as we can to get back down to the limit.
12402 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012403 i<mMainStack.mLRUActivities.size()
12404 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012405 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012406 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012407 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012408
12409 // We can finish this one if we have its icicle saved and
12410 // it is not persistent.
12411 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012412 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012413 final int origSize = mMainStack.mLRUActivities.size();
12414 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012415
12416 // This will remove it from the LRU list, so keep
12417 // our index at the same value. Note that this check to
12418 // see if the size changes is just paranoia -- if
12419 // something unexpected happens, we don't want to end up
12420 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012421 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012422 i--;
12423 }
12424 }
12425 }
12426 }
12427 }
12428
12429 /** This method sends the specified signal to each of the persistent apps */
12430 public void signalPersistentProcesses(int sig) throws RemoteException {
12431 if (sig != Process.SIGNAL_USR1) {
12432 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12433 }
12434
12435 synchronized (this) {
12436 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12437 != PackageManager.PERMISSION_GRANTED) {
12438 throw new SecurityException("Requires permission "
12439 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12440 }
12441
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012442 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12443 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012444 if (r.thread != null && r.persistent) {
12445 Process.sendSignal(r.pid, sig);
12446 }
12447 }
12448 }
12449 }
12450
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012451 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012452 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012453
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012454 try {
12455 synchronized (this) {
12456 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12457 // its own permission.
12458 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12459 != PackageManager.PERMISSION_GRANTED) {
12460 throw new SecurityException("Requires permission "
12461 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012462 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012463
12464 if (start && fd == null) {
12465 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012466 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012467
12468 ProcessRecord proc = null;
12469 try {
12470 int pid = Integer.parseInt(process);
12471 synchronized (mPidsSelfLocked) {
12472 proc = mPidsSelfLocked.get(pid);
12473 }
12474 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012475 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012476
12477 if (proc == null) {
12478 HashMap<String, SparseArray<ProcessRecord>> all
12479 = mProcessNames.getMap();
12480 SparseArray<ProcessRecord> procs = all.get(process);
12481 if (procs != null && procs.size() > 0) {
12482 proc = procs.valueAt(0);
12483 }
12484 }
12485
12486 if (proc == null || proc.thread == null) {
12487 throw new IllegalArgumentException("Unknown process: " + process);
12488 }
12489
12490 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12491 if (isSecure) {
12492 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12493 throw new SecurityException("Process not debuggable: " + proc);
12494 }
12495 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012496
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012497 proc.thread.profilerControl(start, path, fd);
12498 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012499 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012500 }
12501 } catch (RemoteException e) {
12502 throw new IllegalStateException("Process disappeared");
12503 } finally {
12504 if (fd != null) {
12505 try {
12506 fd.close();
12507 } catch (IOException e) {
12508 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012509 }
12510 }
12511 }
12512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012513 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12514 public void monitor() {
12515 synchronized (this) { }
12516 }
12517}