blob: 797c1fb0c065e484e79770b4a1b21f15ef0b7c57 [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();
5894 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5895 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 {
6080 if (dos != null) {
6081 try {
6082 dos.close();
6083 } catch (IOException e) {
6084 // TODO Auto-generated catch block
6085 e.printStackTrace();
6086 }
6087 }
6088 }
6089 }
6090
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006091 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 // In the simulator, startRunning will never have been called, which
6093 // normally sets a few crucial variables. Do it here instead.
6094 if (!Process.supportsProcesses()) {
6095 mStartRunning = true;
6096 mTopAction = Intent.ACTION_MAIN;
6097 }
6098
6099 synchronized(this) {
6100 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006101 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 return;
6103 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006104
6105 // Check to see if there are any update receivers to run.
6106 if (!mDidUpdate) {
6107 if (mWaitingUpdate) {
6108 return;
6109 }
6110 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6111 List<ResolveInfo> ris = null;
6112 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006113 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006114 intent, null, 0);
6115 } catch (RemoteException e) {
6116 }
6117 if (ris != null) {
6118 for (int i=ris.size()-1; i>=0; i--) {
6119 if ((ris.get(i).activityInfo.applicationInfo.flags
6120 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6121 ris.remove(i);
6122 }
6123 }
6124 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006125
6126 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6127
6128 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006129 for (int i=0; i<ris.size(); i++) {
6130 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006131 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6132 if (lastDoneReceivers.contains(comp)) {
6133 ris.remove(i);
6134 i--;
6135 }
6136 }
6137
6138 for (int i=0; i<ris.size(); i++) {
6139 ActivityInfo ai = ris.get(i).activityInfo;
6140 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6141 doneReceivers.add(comp);
6142 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006143 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006144 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006145 finisher = new IIntentReceiver.Stub() {
6146 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006147 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006148 boolean sticky) {
6149 // The raw IIntentReceiver interface is called
6150 // with the AM lock held, so redispatch to
6151 // execute our code without the lock.
6152 mHandler.post(new Runnable() {
6153 public void run() {
6154 synchronized (ActivityManagerService.this) {
6155 mDidUpdate = true;
6156 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006157 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006158 systemReady(goingCallback);
6159 }
6160 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006161 }
6162 };
6163 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006164 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006165 broadcastIntentLocked(null, null, intent, null, finisher,
6166 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006167 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006168 mWaitingUpdate = true;
6169 }
6170 }
6171 }
6172 if (mWaitingUpdate) {
6173 return;
6174 }
6175 mDidUpdate = true;
6176 }
6177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 mSystemReady = true;
6179 if (!mStartRunning) {
6180 return;
6181 }
6182 }
6183
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006184 ArrayList<ProcessRecord> procsToKill = null;
6185 synchronized(mPidsSelfLocked) {
6186 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6187 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6188 if (!isAllowedWhileBooting(proc.info)){
6189 if (procsToKill == null) {
6190 procsToKill = new ArrayList<ProcessRecord>();
6191 }
6192 procsToKill.add(proc);
6193 }
6194 }
6195 }
6196
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006197 synchronized(this) {
6198 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006199 for (int i=procsToKill.size()-1; i>=0; i--) {
6200 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006201 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006202 removeProcessLocked(proc, true);
6203 }
6204 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006205
6206 // Now that we have cleaned up any update processes, we
6207 // are ready to start launching real processes and know that
6208 // we won't trample on them any more.
6209 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006210 }
6211
Joe Onorato8a9b2202010-02-26 18:56:32 -08006212 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006213 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006214 SystemClock.uptimeMillis());
6215
6216 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006217 // Make sure we have no pre-ready processes sitting around.
6218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6220 ResolveInfo ri = mContext.getPackageManager()
6221 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006222 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 CharSequence errorMsg = null;
6224 if (ri != null) {
6225 ActivityInfo ai = ri.activityInfo;
6226 ApplicationInfo app = ai.applicationInfo;
6227 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6228 mTopAction = Intent.ACTION_FACTORY_TEST;
6229 mTopData = null;
6230 mTopComponent = new ComponentName(app.packageName,
6231 ai.name);
6232 } else {
6233 errorMsg = mContext.getResources().getText(
6234 com.android.internal.R.string.factorytest_not_system);
6235 }
6236 } else {
6237 errorMsg = mContext.getResources().getText(
6238 com.android.internal.R.string.factorytest_no_action);
6239 }
6240 if (errorMsg != null) {
6241 mTopAction = null;
6242 mTopData = null;
6243 mTopComponent = null;
6244 Message msg = Message.obtain();
6245 msg.what = SHOW_FACTORY_ERROR_MSG;
6246 msg.getData().putCharSequence("msg", errorMsg);
6247 mHandler.sendMessage(msg);
6248 }
6249 }
6250 }
6251
6252 retrieveSettings();
6253
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006254 if (goingCallback != null) goingCallback.run();
6255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 synchronized (this) {
6257 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6258 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006259 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006260 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 if (apps != null) {
6262 int N = apps.size();
6263 int i;
6264 for (i=0; i<N; i++) {
6265 ApplicationInfo info
6266 = (ApplicationInfo)apps.get(i);
6267 if (info != null &&
6268 !info.packageName.equals("android")) {
6269 addAppLocked(info);
6270 }
6271 }
6272 }
6273 } catch (RemoteException ex) {
6274 // pm is in same process, this will never happen.
6275 }
6276 }
6277
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006278 // Start up initial activity.
6279 mBooting = true;
6280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006282 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006283 Message msg = Message.obtain();
6284 msg.what = SHOW_UID_ERROR_MSG;
6285 mHandler.sendMessage(msg);
6286 }
6287 } catch (RemoteException e) {
6288 }
6289
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006290 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 }
6292 }
6293
Dan Egnorb7f03672009-12-09 16:22:32 -08006294 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006295 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006297 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006298 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299 startAppProblemLocked(app);
6300 app.stopFreezingAllLocked();
6301 return handleAppCrashLocked(app);
6302 }
6303
Dan Egnorb7f03672009-12-09 16:22:32 -08006304 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006305 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006307 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006308 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6309 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006310 startAppProblemLocked(app);
6311 app.stopFreezingAllLocked();
6312 }
6313
6314 /**
6315 * Generate a process error record, suitable for attachment to a ProcessRecord.
6316 *
6317 * @param app The ProcessRecord in which the error occurred.
6318 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6319 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006320 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321 * @param shortMsg Short message describing the crash.
6322 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006323 * @param stackTrace Full crash stack trace, may be null.
6324 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 * @return Returns a fully-formed AppErrorStateInfo record.
6326 */
6327 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006328 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 report.condition = condition;
6332 report.processName = app.processName;
6333 report.pid = app.pid;
6334 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006335 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 report.shortMsg = shortMsg;
6337 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006338 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339
6340 return report;
6341 }
6342
Dan Egnor42471dd2010-01-07 17:25:22 -08006343 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 synchronized (this) {
6345 app.crashing = false;
6346 app.crashingReport = null;
6347 app.notResponding = false;
6348 app.notRespondingReport = null;
6349 if (app.anrDialog == fromDialog) {
6350 app.anrDialog = null;
6351 }
6352 if (app.waitDialog == fromDialog) {
6353 app.waitDialog = null;
6354 }
6355 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006356 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006357 Slog.i(ActivityManagerService.TAG, "Killing "
6358 + app.processName + " (pid=" + app.pid + "): user's request");
6359 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6360 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 Process.killProcess(app.pid);
6362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 }
6364 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006365
Dan Egnorb7f03672009-12-09 16:22:32 -08006366 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 long now = SystemClock.uptimeMillis();
6368
6369 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6370 app.info.uid);
6371 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6372 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006373 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006375 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 app.info.processName, app.info.uid);
6377 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006378 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6379 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006381 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006383 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 }
6385 }
6386 if (!app.persistent) {
6387 // We don't want to start this process again until the user
6388 // explicitly does so... but for persistent process, we really
6389 // need to keep it running. If a persistent process is actually
6390 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006391 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006392 app.info.processName);
6393 mBadProcesses.put(app.info.processName, app.info.uid, now);
6394 app.bad = true;
6395 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6396 app.removed = true;
6397 removeProcessLocked(app, false);
6398 return false;
6399 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006400 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006401 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006402 if (r.app == app) {
6403 // If the top running activity is from this crashing
6404 // process, then terminate it to avoid getting in a loop.
6405 Slog.w(TAG, " Force finishing activity "
6406 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006407 int index = mMainStack.indexOfTokenLocked(r);
6408 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006409 Activity.RESULT_CANCELED, null, "crashed");
6410 // Also terminate an activities below it that aren't yet
6411 // stopped, to avoid a situation where one will get
6412 // re-start our crashing activity once it gets resumed again.
6413 index--;
6414 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006415 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006416 if (r.state == ActivityState.RESUMED
6417 || r.state == ActivityState.PAUSING
6418 || r.state == ActivityState.PAUSED) {
6419 if (!r.isHomeActivity) {
6420 Slog.w(TAG, " Force finishing activity "
6421 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006422 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006423 Activity.RESULT_CANCELED, null, "crashed");
6424 }
6425 }
6426 }
6427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006428 }
6429
6430 // Bump up the crash count of any services currently running in the proc.
6431 if (app.services.size() != 0) {
6432 // Any services running in the application need to be placed
6433 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006434 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006435 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006436 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006437 sr.crashCount++;
6438 }
6439 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006440
6441 // If the crashing process is what we consider to be the "home process" and it has been
6442 // replaced by a third-party app, clear the package preferred activities from packages
6443 // with a home activity running in the process to prevent a repeatedly crashing app
6444 // from blocking the user to manually clear the list.
6445 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6446 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6447 Iterator it = mHomeProcess.activities.iterator();
6448 while (it.hasNext()) {
Jean-Baptiste Queru1ca94792010-07-30 09:30:31 -07006449 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006450 if (r.isHomeActivity) {
6451 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6452 try {
6453 ActivityThread.getPackageManager()
6454 .clearPackagePreferredActivities(r.packageName);
6455 } catch (RemoteException c) {
6456 // pm is in same process, this will never happen.
6457 }
6458 }
6459 }
6460 }
6461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6463 return true;
6464 }
6465
6466 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006467 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6468 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 skipCurrentReceiverLocked(app);
6470 }
6471
6472 void skipCurrentReceiverLocked(ProcessRecord app) {
6473 boolean reschedule = false;
6474 BroadcastRecord r = app.curReceiver;
6475 if (r != null) {
6476 // The current broadcast is waiting for this app's receiver
6477 // to be finished. Looks like that's not going to happen, so
6478 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006479 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6481 r.resultExtras, r.resultAbort, true);
6482 reschedule = true;
6483 }
6484 r = mPendingBroadcast;
6485 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006486 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006487 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006488 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6490 r.resultExtras, r.resultAbort, true);
6491 reschedule = true;
6492 }
6493 if (reschedule) {
6494 scheduleBroadcastsLocked();
6495 }
6496 }
6497
Dan Egnor60d87622009-12-16 16:32:58 -08006498 /**
6499 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6500 * The application process will exit immediately after this call returns.
6501 * @param app object of the crashing app, null for the system server
6502 * @param crashInfo describing the exception
6503 */
6504 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6505 ProcessRecord r = findAppProcess(app);
6506
6507 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6508 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006509 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006510 crashInfo.exceptionClassName,
6511 crashInfo.exceptionMessage,
6512 crashInfo.throwFileName,
6513 crashInfo.throwLineNumber);
6514
Dan Egnor42471dd2010-01-07 17:25:22 -08006515 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006516
6517 crashApplication(r, crashInfo);
6518 }
6519
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006520 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006521 IBinder app,
6522 int violationMask,
6523 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006524 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006525
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006526 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006527 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006528 boolean logIt = true;
6529 synchronized (mAlreadyLoggedViolatedStacks) {
6530 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6531 logIt = false;
6532 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006533 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006534 // the relative pain numbers, without logging all
6535 // the stack traces repeatedly. We'd want to do
6536 // likewise in the client code, which also does
6537 // dup suppression, before the Binder call.
6538 } else {
6539 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6540 mAlreadyLoggedViolatedStacks.clear();
6541 }
6542 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6543 }
6544 }
6545 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006546 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006547 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006548 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006549
6550 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6551 AppErrorResult result = new AppErrorResult();
6552 synchronized (this) {
6553 final long origId = Binder.clearCallingIdentity();
6554
6555 Message msg = Message.obtain();
6556 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6557 HashMap<String, Object> data = new HashMap<String, Object>();
6558 data.put("result", result);
6559 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006560 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006561 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006562 msg.obj = data;
6563 mHandler.sendMessage(msg);
6564
6565 Binder.restoreCallingIdentity(origId);
6566 }
6567 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006568 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006569 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006570 }
6571
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006572 // Depending on the policy in effect, there could be a bunch of
6573 // these in quick succession so we try to batch these together to
6574 // minimize disk writes, number of dropbox entries, and maximize
6575 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006576 private void logStrictModeViolationToDropBox(
6577 ProcessRecord process,
6578 StrictMode.ViolationInfo info) {
6579 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006580 return;
6581 }
6582 final boolean isSystemApp = process == null ||
6583 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6584 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6585 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6586 final DropBoxManager dbox = (DropBoxManager)
6587 mContext.getSystemService(Context.DROPBOX_SERVICE);
6588
6589 // Exit early if the dropbox isn't configured to accept this report type.
6590 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6591
6592 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006593 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006594 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6595 synchronized (sb) {
6596 bufferWasEmpty = sb.length() == 0;
6597 appendDropBoxProcessHeaders(process, sb);
6598 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6599 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006600 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6601 if (info.violationNumThisLoop != 0) {
6602 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6603 }
6604 if (info != null && info.durationMillis != -1) {
6605 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006606 }
6607 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006608 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6609 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006610 }
6611 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006612
6613 // Only buffer up to ~64k. Various logging bits truncate
6614 // things at 128k.
6615 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006616 }
6617
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006618 // Flush immediately if the buffer's grown too large, or this
6619 // is a non-system app. Non-system apps are isolated with a
6620 // different tag & policy and not batched.
6621 //
6622 // Batching is useful during internal testing with
6623 // StrictMode settings turned up high. Without batching,
6624 // thousands of separate files could be created on boot.
6625 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006626 new Thread("Error dump: " + dropboxTag) {
6627 @Override
6628 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006629 String report;
6630 synchronized (sb) {
6631 report = sb.toString();
6632 sb.delete(0, sb.length());
6633 sb.trimToSize();
6634 }
6635 if (report.length() != 0) {
6636 dbox.addText(dropboxTag, report);
6637 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006638 }
6639 }.start();
6640 return;
6641 }
6642
6643 // System app batching:
6644 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006645 // An existing dropbox-writing thread is outstanding, so
6646 // we don't need to start it up. The existing thread will
6647 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006648 return;
6649 }
6650
6651 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6652 // (After this point, we shouldn't access AMS internal data structures.)
6653 new Thread("Error dump: " + dropboxTag) {
6654 @Override
6655 public void run() {
6656 // 5 second sleep to let stacks arrive and be batched together
6657 try {
6658 Thread.sleep(5000); // 5 seconds
6659 } catch (InterruptedException e) {}
6660
6661 String errorReport;
6662 synchronized (mStrictModeBuffer) {
6663 errorReport = mStrictModeBuffer.toString();
6664 if (errorReport.length() == 0) {
6665 return;
6666 }
6667 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6668 mStrictModeBuffer.trimToSize();
6669 }
6670 dbox.addText(dropboxTag, errorReport);
6671 }
6672 }.start();
6673 }
6674
Dan Egnor60d87622009-12-16 16:32:58 -08006675 /**
6676 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6677 * @param app object of the crashing app, null for the system server
6678 * @param tag reported by the caller
6679 * @param crashInfo describing the context of the error
6680 * @return true if the process should exit immediately (WTF is fatal)
6681 */
6682 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006683 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006684 ProcessRecord r = findAppProcess(app);
6685
6686 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6687 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006688 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006689 tag, crashInfo.exceptionMessage);
6690
Dan Egnor42471dd2010-01-07 17:25:22 -08006691 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006692
Doug Zongker43866e02010-01-07 12:09:54 -08006693 if (Settings.Secure.getInt(mContext.getContentResolver(),
6694 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006695 crashApplication(r, crashInfo);
6696 return true;
6697 } else {
6698 return false;
6699 }
6700 }
6701
6702 /**
6703 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6704 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6705 */
6706 private ProcessRecord findAppProcess(IBinder app) {
6707 if (app == null) {
6708 return null;
6709 }
6710
6711 synchronized (this) {
6712 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6713 final int NA = apps.size();
6714 for (int ia=0; ia<NA; ia++) {
6715 ProcessRecord p = apps.valueAt(ia);
6716 if (p.thread != null && p.thread.asBinder() == app) {
6717 return p;
6718 }
6719 }
6720 }
6721
Joe Onorato8a9b2202010-02-26 18:56:32 -08006722 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006723 return null;
6724 }
6725 }
6726
6727 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006728 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6729 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006730 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006731 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6732 // Note: ProcessRecord 'process' is guarded by the service
6733 // instance. (notably process.pkgList, which could otherwise change
6734 // concurrently during execution of this method)
6735 synchronized (this) {
6736 if (process == null || process.pid == MY_PID) {
6737 sb.append("Process: system_server\n");
6738 } else {
6739 sb.append("Process: ").append(process.processName).append("\n");
6740 }
6741 if (process == null) {
6742 return;
6743 }
Dan Egnora455d192010-03-12 08:52:28 -08006744 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006745 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006746 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6747 for (String pkg : process.pkgList) {
6748 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006749 try {
Dan Egnora455d192010-03-12 08:52:28 -08006750 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6751 if (pi != null) {
6752 sb.append(" v").append(pi.versionCode);
6753 if (pi.versionName != null) {
6754 sb.append(" (").append(pi.versionName).append(")");
6755 }
6756 }
6757 } catch (RemoteException e) {
6758 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006759 }
Dan Egnora455d192010-03-12 08:52:28 -08006760 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006761 }
Dan Egnora455d192010-03-12 08:52:28 -08006762 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006763 }
6764
6765 private static String processClass(ProcessRecord process) {
6766 if (process == null || process.pid == MY_PID) {
6767 return "system_server";
6768 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6769 return "system_app";
6770 } else {
6771 return "data_app";
6772 }
6773 }
6774
6775 /**
6776 * Write a description of an error (crash, WTF, ANR) to the drop box.
6777 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6778 * @param process which caused the error, null means the system server
6779 * @param activity which triggered the error, null if unknown
6780 * @param parent activity related to the error, null if unknown
6781 * @param subject line related to the error, null if absent
6782 * @param report in long form describing the error, null if absent
6783 * @param logFile to include in the report, null if none
6784 * @param crashInfo giving an application stack trace, null if absent
6785 */
6786 public void addErrorToDropBox(String eventType,
6787 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6788 final String report, final File logFile,
6789 final ApplicationErrorReport.CrashInfo crashInfo) {
6790 // NOTE -- this must never acquire the ActivityManagerService lock,
6791 // otherwise the watchdog may be prevented from resetting the system.
6792
6793 final String dropboxTag = processClass(process) + "_" + eventType;
6794 final DropBoxManager dbox = (DropBoxManager)
6795 mContext.getSystemService(Context.DROPBOX_SERVICE);
6796
6797 // Exit early if the dropbox isn't configured to accept this report type.
6798 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6799
6800 final StringBuilder sb = new StringBuilder(1024);
6801 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006802 if (activity != null) {
6803 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6804 }
6805 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6806 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6807 }
6808 if (parent != null && parent != activity) {
6809 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6810 }
6811 if (subject != null) {
6812 sb.append("Subject: ").append(subject).append("\n");
6813 }
6814 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6815 sb.append("\n");
6816
6817 // Do the rest in a worker thread to avoid blocking the caller on I/O
6818 // (After this point, we shouldn't access AMS internal data structures.)
6819 Thread worker = new Thread("Error dump: " + dropboxTag) {
6820 @Override
6821 public void run() {
6822 if (report != null) {
6823 sb.append(report);
6824 }
6825 if (logFile != null) {
6826 try {
6827 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6828 } catch (IOException e) {
6829 Slog.e(TAG, "Error reading " + logFile, e);
6830 }
6831 }
6832 if (crashInfo != null && crashInfo.stackTrace != null) {
6833 sb.append(crashInfo.stackTrace);
6834 }
6835
6836 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6837 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6838 if (lines > 0) {
6839 sb.append("\n");
6840
6841 // Merge several logcat streams, and take the last N lines
6842 InputStreamReader input = null;
6843 try {
6844 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6845 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6846 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6847
6848 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6849 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6850 input = new InputStreamReader(logcat.getInputStream());
6851
6852 int num;
6853 char[] buf = new char[8192];
6854 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6855 } catch (IOException e) {
6856 Slog.e(TAG, "Error running logcat", e);
6857 } finally {
6858 if (input != null) try { input.close(); } catch (IOException e) {}
6859 }
6860 }
6861
6862 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006863 }
Dan Egnora455d192010-03-12 08:52:28 -08006864 };
6865
6866 if (process == null || process.pid == MY_PID) {
6867 worker.run(); // We may be about to die -- need to run this synchronously
6868 } else {
6869 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006870 }
6871 }
6872
6873 /**
6874 * Bring up the "unexpected error" dialog box for a crashing app.
6875 * Deal with edge cases (intercepts from instrumented applications,
6876 * ActivityController, error intent receivers, that sort of thing).
6877 * @param r the application crashing
6878 * @param crashInfo describing the failure
6879 */
6880 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006881 long timeMillis = System.currentTimeMillis();
6882 String shortMsg = crashInfo.exceptionClassName;
6883 String longMsg = crashInfo.exceptionMessage;
6884 String stackTrace = crashInfo.stackTrace;
6885 if (shortMsg != null && longMsg != null) {
6886 longMsg = shortMsg + ": " + longMsg;
6887 } else if (shortMsg != null) {
6888 longMsg = shortMsg;
6889 }
6890
Dan Egnor60d87622009-12-16 16:32:58 -08006891 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006893 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006894 try {
6895 String name = r != null ? r.processName : null;
6896 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006897 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006898 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006899 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 + " at watcher's request");
6901 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006902 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 }
6904 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006905 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 }
6907 }
6908
6909 final long origId = Binder.clearCallingIdentity();
6910
6911 // If this process is running instrumentation, finish it.
6912 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006913 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006915 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6916 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006917 Bundle info = new Bundle();
6918 info.putString("shortMsg", shortMsg);
6919 info.putString("longMsg", longMsg);
6920 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6921 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006922 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 }
6924
Dan Egnor60d87622009-12-16 16:32:58 -08006925 // If we can't identify the process or it's already exceeded its crash quota,
6926 // quit right away without showing a crash dialog.
6927 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006929 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 }
6931
6932 Message msg = Message.obtain();
6933 msg.what = SHOW_ERROR_MSG;
6934 HashMap data = new HashMap();
6935 data.put("result", result);
6936 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 msg.obj = data;
6938 mHandler.sendMessage(msg);
6939
6940 Binder.restoreCallingIdentity(origId);
6941 }
6942
6943 int res = result.get();
6944
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006945 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006946 synchronized (this) {
6947 if (r != null) {
6948 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6949 SystemClock.uptimeMillis());
6950 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006951 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006952 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006953 }
6954 }
6955
6956 if (appErrorIntent != null) {
6957 try {
6958 mContext.startActivity(appErrorIntent);
6959 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006960 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006963 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006964
6965 Intent createAppErrorIntentLocked(ProcessRecord r,
6966 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6967 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006968 if (report == null) {
6969 return null;
6970 }
6971 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6972 result.setComponent(r.errorReportReceiver);
6973 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6974 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6975 return result;
6976 }
6977
Dan Egnorb7f03672009-12-09 16:22:32 -08006978 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6979 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006980 if (r.errorReportReceiver == null) {
6981 return null;
6982 }
6983
6984 if (!r.crashing && !r.notResponding) {
6985 return null;
6986 }
6987
Dan Egnorb7f03672009-12-09 16:22:32 -08006988 ApplicationErrorReport report = new ApplicationErrorReport();
6989 report.packageName = r.info.packageName;
6990 report.installerPackageName = r.errorReportReceiver.getPackageName();
6991 report.processName = r.processName;
6992 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006993 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006994
Dan Egnorb7f03672009-12-09 16:22:32 -08006995 if (r.crashing) {
6996 report.type = ApplicationErrorReport.TYPE_CRASH;
6997 report.crashInfo = crashInfo;
6998 } else if (r.notResponding) {
6999 report.type = ApplicationErrorReport.TYPE_ANR;
7000 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007001
Dan Egnorb7f03672009-12-09 16:22:32 -08007002 report.anrInfo.activity = r.notRespondingReport.tag;
7003 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7004 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007005 }
7006
Dan Egnorb7f03672009-12-09 16:22:32 -08007007 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007008 }
7009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007010 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7011 // assume our apps are happy - lazy create the list
7012 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7013
7014 synchronized (this) {
7015
7016 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007017 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7018 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007019 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7020 // This one's in trouble, so we'll generate a report for it
7021 // crashes are higher priority (in case there's a crash *and* an anr)
7022 ActivityManager.ProcessErrorStateInfo report = null;
7023 if (app.crashing) {
7024 report = app.crashingReport;
7025 } else if (app.notResponding) {
7026 report = app.notRespondingReport;
7027 }
7028
7029 if (report != null) {
7030 if (errList == null) {
7031 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7032 }
7033 errList.add(report);
7034 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007035 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 " crashing = " + app.crashing +
7037 " notResponding = " + app.notResponding);
7038 }
7039 }
7040 }
7041 }
7042
7043 return errList;
7044 }
7045
7046 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7047 // Lazy instantiation of list
7048 List<ActivityManager.RunningAppProcessInfo> runList = null;
7049 synchronized (this) {
7050 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007051 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7052 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7054 // Generate process state info for running application
7055 ActivityManager.RunningAppProcessInfo currApp =
7056 new ActivityManager.RunningAppProcessInfo(app.processName,
7057 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007058 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007059 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007060 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007063 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7065 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7066 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007067 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7068 } else if (adj >= HOME_APP_ADJ) {
7069 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7070 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 } else if (adj >= SECONDARY_SERVER_ADJ) {
7072 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007073 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
7074 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
7075 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7076 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 } else if (adj >= VISIBLE_APP_ADJ) {
7078 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7079 } else {
7080 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7081 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007082 currApp.importanceReasonCode = app.adjTypeCode;
7083 if (app.adjSource instanceof ProcessRecord) {
7084 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007085 } else if (app.adjSource instanceof ActivityRecord) {
7086 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007087 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7088 }
7089 if (app.adjTarget instanceof ComponentName) {
7090 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7091 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007092 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 // + " lru=" + currApp.lru);
7094 if (runList == null) {
7095 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7096 }
7097 runList.add(currApp);
7098 }
7099 }
7100 }
7101 return runList;
7102 }
7103
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007104 public List<ApplicationInfo> getRunningExternalApplications() {
7105 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7106 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7107 if (runningApps != null && runningApps.size() > 0) {
7108 Set<String> extList = new HashSet<String>();
7109 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7110 if (app.pkgList != null) {
7111 for (String pkg : app.pkgList) {
7112 extList.add(pkg);
7113 }
7114 }
7115 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007116 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007117 for (String pkg : extList) {
7118 try {
7119 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7120 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7121 retList.add(info);
7122 }
7123 } catch (RemoteException e) {
7124 }
7125 }
7126 }
7127 return retList;
7128 }
7129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 @Override
7131 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007132 if (checkCallingPermission(android.Manifest.permission.DUMP)
7133 != PackageManager.PERMISSION_GRANTED) {
7134 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7135 + Binder.getCallingPid()
7136 + ", uid=" + Binder.getCallingUid()
7137 + " without permission "
7138 + android.Manifest.permission.DUMP);
7139 return;
7140 }
7141
7142 boolean dumpAll = false;
7143
7144 int opti = 0;
7145 while (opti < args.length) {
7146 String opt = args[opti];
7147 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7148 break;
7149 }
7150 opti++;
7151 if ("-a".equals(opt)) {
7152 dumpAll = true;
7153 } else if ("-h".equals(opt)) {
7154 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007155 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007156 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007157 pw.println(" a[ctivities]: activity stack state");
7158 pw.println(" b[roadcasts]: broadcast state");
7159 pw.println(" i[ntents]: pending intent state");
7160 pw.println(" p[rocesses]: process state");
7161 pw.println(" o[om]: out of memory management");
7162 pw.println(" prov[iders]: content provider state");
7163 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007164 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007166 } else {
7167 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007169 }
7170
7171 // Is the caller requesting to dump a particular piece of data?
7172 if (opti < args.length) {
7173 String cmd = args[opti];
7174 opti++;
7175 if ("activities".equals(cmd) || "a".equals(cmd)) {
7176 synchronized (this) {
7177 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007179 return;
7180 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7181 synchronized (this) {
7182 dumpBroadcastsLocked(fd, pw, args, opti, true);
7183 }
7184 return;
7185 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7186 synchronized (this) {
7187 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7188 }
7189 return;
7190 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7191 synchronized (this) {
7192 dumpProcessesLocked(fd, pw, args, opti, true);
7193 }
7194 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007195 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7196 synchronized (this) {
7197 dumpOomLocked(fd, pw, args, opti, true);
7198 }
7199 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007200 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7201 synchronized (this) {
7202 dumpProvidersLocked(fd, pw, args, opti, true);
7203 }
7204 return;
7205 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007206 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007207 return;
7208 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7209 synchronized (this) {
7210 dumpServicesLocked(fd, pw, args, opti, true);
7211 }
7212 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007214 }
7215
7216 // No piece of data specified, dump everything.
7217 synchronized (this) {
7218 boolean needSep;
7219 if (dumpAll) {
7220 pw.println("Providers in Current Activity Manager State:");
7221 }
7222 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7223 if (needSep) {
7224 pw.println(" ");
7225 }
7226 if (dumpAll) {
7227 pw.println("-------------------------------------------------------------------------------");
7228 pw.println("Broadcasts in Current Activity Manager State:");
7229 }
7230 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7231 if (needSep) {
7232 pw.println(" ");
7233 }
7234 if (dumpAll) {
7235 pw.println("-------------------------------------------------------------------------------");
7236 pw.println("Services in Current Activity Manager State:");
7237 }
7238 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7239 if (needSep) {
7240 pw.println(" ");
7241 }
7242 if (dumpAll) {
7243 pw.println("-------------------------------------------------------------------------------");
7244 pw.println("PendingIntents in Current Activity Manager State:");
7245 }
7246 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7247 if (needSep) {
7248 pw.println(" ");
7249 }
7250 if (dumpAll) {
7251 pw.println("-------------------------------------------------------------------------------");
7252 pw.println("Activities in Current Activity Manager State:");
7253 }
7254 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7255 if (needSep) {
7256 pw.println(" ");
7257 }
7258 if (dumpAll) {
7259 pw.println("-------------------------------------------------------------------------------");
7260 pw.println("Processes in Current Activity Manager State:");
7261 }
7262 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7263 }
7264 }
7265
7266 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7267 int opti, boolean dumpAll, boolean needHeader) {
7268 if (needHeader) {
7269 pw.println(" Activity stack:");
7270 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007271 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 pw.println(" ");
7273 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007274 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7275 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007277 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007278 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007279 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007280 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007282 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007283 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007284 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007285 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007286 pw.println(" ");
7287 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007288 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007291 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007292 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7293 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007294 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007295 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007297 if (dumpAll && mRecentTasks.size() > 0) {
7298 pw.println(" ");
7299 pw.println("Recent tasks in Current Activity Manager State:");
7300
7301 final int N = mRecentTasks.size();
7302 for (int i=0; i<N; i++) {
7303 TaskRecord tr = mRecentTasks.get(i);
7304 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7305 pw.println(tr);
7306 mRecentTasks.get(i).dump(pw, " ");
7307 }
7308 }
7309
7310 pw.println(" ");
7311 pw.println(" mCurTask: " + mCurTask);
7312
7313 return true;
7314 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007315
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007316 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7317 int opti, boolean dumpAll) {
7318 boolean needSep = false;
7319 int numPers = 0;
7320
7321 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7323 final int NA = procs.size();
7324 for (int ia=0; ia<NA; ia++) {
7325 if (!needSep) {
7326 pw.println(" All known processes:");
7327 needSep = true;
7328 }
7329 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007330 pw.print(r.persistent ? " *PERS*" : " *APP*");
7331 pw.print(" UID "); pw.print(procs.keyAt(ia));
7332 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 r.dump(pw, " ");
7334 if (r.persistent) {
7335 numPers++;
7336 }
7337 }
7338 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007339 }
7340
7341 if (mLruProcesses.size() > 0) {
7342 if (needSep) pw.println(" ");
7343 needSep = true;
7344 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007345 dumpProcessOomList(pw, this, mLruProcesses, " ",
7346 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007347 needSep = true;
7348 }
7349
7350 synchronized (mPidsSelfLocked) {
7351 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 if (needSep) pw.println(" ");
7353 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007354 pw.println(" PID mappings:");
7355 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7356 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7357 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358 }
7359 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007360 }
7361
7362 if (mForegroundProcesses.size() > 0) {
7363 if (needSep) pw.println(" ");
7364 needSep = true;
7365 pw.println(" Foreground Processes:");
7366 for (int i=0; i<mForegroundProcesses.size(); i++) {
7367 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7368 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007370 }
7371
7372 if (mPersistentStartingProcesses.size() > 0) {
7373 if (needSep) pw.println(" ");
7374 needSep = true;
7375 pw.println(" Persisent processes that are starting:");
7376 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007377 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007380 if (mStartingProcesses.size() > 0) {
7381 if (needSep) pw.println(" ");
7382 needSep = true;
7383 pw.println(" Processes that are starting:");
7384 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007385 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007388 if (mRemovedProcesses.size() > 0) {
7389 if (needSep) pw.println(" ");
7390 needSep = true;
7391 pw.println(" Processes that are being removed:");
7392 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007393 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007394 }
7395
7396 if (mProcessesOnHold.size() > 0) {
7397 if (needSep) pw.println(" ");
7398 needSep = true;
7399 pw.println(" Processes that are on old until the system is ready:");
7400 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007401 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403
Dianne Hackborn287952c2010-09-22 22:34:31 -07007404 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007405
7406 if (mProcessCrashTimes.getMap().size() > 0) {
7407 if (needSep) pw.println(" ");
7408 needSep = true;
7409 pw.println(" Time since processes crashed:");
7410 long now = SystemClock.uptimeMillis();
7411 for (Map.Entry<String, SparseArray<Long>> procs
7412 : mProcessCrashTimes.getMap().entrySet()) {
7413 SparseArray<Long> uids = procs.getValue();
7414 final int N = uids.size();
7415 for (int i=0; i<N; i++) {
7416 pw.print(" Process "); pw.print(procs.getKey());
7417 pw.print(" uid "); pw.print(uids.keyAt(i));
7418 pw.print(": last crashed ");
7419 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007420 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007421 }
7422 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007425 if (mBadProcesses.getMap().size() > 0) {
7426 if (needSep) pw.println(" ");
7427 needSep = true;
7428 pw.println(" Bad processes:");
7429 for (Map.Entry<String, SparseArray<Long>> procs
7430 : mBadProcesses.getMap().entrySet()) {
7431 SparseArray<Long> uids = procs.getValue();
7432 final int N = uids.size();
7433 for (int i=0; i<N; i++) {
7434 pw.print(" Bad process "); pw.print(procs.getKey());
7435 pw.print(" uid "); pw.print(uids.keyAt(i));
7436 pw.print(": crashed at time ");
7437 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 }
7439 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007442 pw.println(" ");
7443 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007444 if (mHeavyWeightProcess != null) {
7445 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7446 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007447 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007448 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007449 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7450 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7451 || mOrigWaitForDebugger) {
7452 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7453 + " mDebugTransient=" + mDebugTransient
7454 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7455 }
7456 if (mAlwaysFinishActivities || mController != null) {
7457 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7458 + " mController=" + mController);
7459 }
7460 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007463 + " mProcessesReady=" + mProcessesReady
7464 + " mSystemReady=" + mSystemReady);
7465 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 + " mBooted=" + mBooted
7467 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007468 pw.print(" mLastPowerCheckRealtime=");
7469 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7470 pw.println("");
7471 pw.print(" mLastPowerCheckUptime=");
7472 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7473 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007474 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7475 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007476 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007478
7479 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007480 }
7481
Dianne Hackborn287952c2010-09-22 22:34:31 -07007482 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7483 int opti, boolean needSep, boolean dumpAll) {
7484 if (mProcessesToGc.size() > 0) {
7485 if (needSep) pw.println(" ");
7486 needSep = true;
7487 pw.println(" Processes that are waiting to GC:");
7488 long now = SystemClock.uptimeMillis();
7489 for (int i=0; i<mProcessesToGc.size(); i++) {
7490 ProcessRecord proc = mProcessesToGc.get(i);
7491 pw.print(" Process "); pw.println(proc);
7492 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7493 pw.print(", last gced=");
7494 pw.print(now-proc.lastRequestedGc);
7495 pw.print(" ms ago, last lowMem=");
7496 pw.print(now-proc.lastLowMemory);
7497 pw.println(" ms ago");
7498
7499 }
7500 }
7501 return needSep;
7502 }
7503
7504 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7505 int opti, boolean dumpAll) {
7506 boolean needSep = false;
7507
7508 if (mLruProcesses.size() > 0) {
7509 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7510
7511 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7512 @Override
7513 public int compare(ProcessRecord object1, ProcessRecord object2) {
7514 if (object1.setAdj != object2.setAdj) {
7515 return object1.setAdj > object2.setAdj ? -1 : 1;
7516 }
7517 if (object1.setSchedGroup != object2.setSchedGroup) {
7518 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7519 }
7520 if (object1.keeping != object2.keeping) {
7521 return object1.keeping ? -1 : 1;
7522 }
7523 if (object1.pid != object2.pid) {
7524 return object1.pid > object2.pid ? -1 : 1;
7525 }
7526 return 0;
7527 }
7528 };
7529
7530 Collections.sort(procs, comparator);
7531
7532 if (needSep) pw.println(" ");
7533 needSep = true;
7534 pw.println(" Process OOM control:");
7535 dumpProcessOomList(pw, this, procs, " ",
7536 "Proc", "PERS", true);
7537 needSep = true;
7538 }
7539
7540 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7541
7542 pw.println(" ");
7543 pw.println(" mHomeProcess: " + mHomeProcess);
7544 if (mHeavyWeightProcess != null) {
7545 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7546 }
7547
7548 return true;
7549 }
7550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 /**
7552 * There are three ways to call this:
7553 * - no service specified: dump all the services
7554 * - a flattened component name that matched an existing service was specified as the
7555 * first arg: dump that one service
7556 * - the first arg isn't the flattened component name of an existing service:
7557 * dump all services whose component contains the first arg as a substring
7558 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007559 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7560 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 String[] newArgs;
7562 String componentNameString;
7563 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007564 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 componentNameString = null;
7566 newArgs = EMPTY_STRING_ARRAY;
7567 r = null;
7568 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569 componentNameString = args[opti];
7570 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007572 synchronized (this) {
7573 r = componentName != null ? mServices.get(componentName) : null;
7574 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007575 newArgs = new String[args.length - opti];
7576 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007577 }
7578
7579 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007580 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007582 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7583 synchronized (this) {
7584 for (ServiceRecord r1 : mServices.values()) {
7585 if (componentNameString == null
7586 || r1.name.flattenToString().contains(componentNameString)) {
7587 services.add(r1);
7588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589 }
7590 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007591 for (int i=0; i<services.size(); i++) {
7592 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 }
7595 }
7596
7597 /**
7598 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7599 * there is a thread associated with the service.
7600 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007601 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7602 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007604 if (dumpAll) {
7605 synchronized (this) {
7606 pw.print(" * "); pw.println(r);
7607 r.dump(pw, " ");
7608 }
7609 pw.println("");
7610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 if (r.app != null && r.app.thread != null) {
7612 try {
7613 // flush anything that is already in the PrintWriter since the thread is going
7614 // to write to the file descriptor directly
7615 pw.flush();
7616 r.app.thread.dumpService(fd, r, args);
7617 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007618 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 } catch (RemoteException e) {
7620 pw.println("got a RemoteException while dumping the service");
7621 }
7622 }
7623 }
7624
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007625 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7626 int opti, boolean dumpAll) {
7627 boolean needSep = false;
7628
7629 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007630 if (mRegisteredReceivers.size() > 0) {
7631 pw.println(" ");
7632 pw.println(" Registered Receivers:");
7633 Iterator it = mRegisteredReceivers.values().iterator();
7634 while (it.hasNext()) {
7635 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007636 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007637 r.dump(pw, " ");
7638 }
7639 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 pw.println(" ");
7642 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007643 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007644 needSep = true;
7645 }
7646
7647 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7648 || mPendingBroadcast != null) {
7649 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007651 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007653 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7654 pw.println(" Broadcast #" + i + ":");
7655 mParallelBroadcasts.get(i).dump(pw, " ");
7656 }
7657 if (mOrderedBroadcasts.size() > 0) {
7658 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007659 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007660 }
7661 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7662 pw.println(" Serialized Broadcast #" + i + ":");
7663 mOrderedBroadcasts.get(i).dump(pw, " ");
7664 }
7665 pw.println(" ");
7666 pw.println(" Pending broadcast:");
7667 if (mPendingBroadcast != null) {
7668 mPendingBroadcast.dump(pw, " ");
7669 } else {
7670 pw.println(" (null)");
7671 }
7672 needSep = true;
7673 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007674
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007675 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007677 pw.println(" Historical broadcasts:");
7678 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7679 BroadcastRecord r = mBroadcastHistory[i];
7680 if (r == null) {
7681 break;
7682 }
7683 pw.println(" Historical Broadcast #" + i + ":");
7684 r.dump(pw, " ");
7685 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007686 needSep = true;
7687 }
7688
7689 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007690 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691 pw.println(" Sticky broadcasts:");
7692 StringBuilder sb = new StringBuilder(128);
7693 for (Map.Entry<String, ArrayList<Intent>> ent
7694 : mStickyBroadcasts.entrySet()) {
7695 pw.print(" * Sticky action "); pw.print(ent.getKey());
7696 pw.println(":");
7697 ArrayList<Intent> intents = ent.getValue();
7698 final int N = intents.size();
7699 for (int i=0; i<N; i++) {
7700 sb.setLength(0);
7701 sb.append(" Intent: ");
7702 intents.get(i).toShortString(sb, true, false);
7703 pw.println(sb.toString());
7704 Bundle bundle = intents.get(i).getExtras();
7705 if (bundle != null) {
7706 pw.print(" ");
7707 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007708 }
7709 }
7710 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007711 needSep = true;
7712 }
7713
7714 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007715 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007716 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 pw.println(" mHandler:");
7718 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007719 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007721
7722 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 }
7724
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007725 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7726 int opti, boolean dumpAll) {
7727 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007728
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 if (mServices.size() > 0) {
7731 pw.println(" Active services:");
7732 Iterator<ServiceRecord> it = mServices.values().iterator();
7733 while (it.hasNext()) {
7734 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007735 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736 r.dump(pw, " ");
7737 }
7738 needSep = true;
7739 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007742 if (mPendingServices.size() > 0) {
7743 if (needSep) pw.println(" ");
7744 pw.println(" Pending services:");
7745 for (int i=0; i<mPendingServices.size(); i++) {
7746 ServiceRecord r = mPendingServices.get(i);
7747 pw.print(" * Pending "); pw.println(r);
7748 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 needSep = true;
7751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 if (mRestartingServices.size() > 0) {
7754 if (needSep) pw.println(" ");
7755 pw.println(" Restarting services:");
7756 for (int i=0; i<mRestartingServices.size(); i++) {
7757 ServiceRecord r = mRestartingServices.get(i);
7758 pw.print(" * Restarting "); pw.println(r);
7759 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007761 needSep = true;
7762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007764 if (mStoppingServices.size() > 0) {
7765 if (needSep) pw.println(" ");
7766 pw.println(" Stopping services:");
7767 for (int i=0; i<mStoppingServices.size(); i++) {
7768 ServiceRecord r = mStoppingServices.get(i);
7769 pw.print(" * Stopping "); pw.println(r);
7770 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 needSep = true;
7773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 if (mServiceConnections.size() > 0) {
7777 if (needSep) pw.println(" ");
7778 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007779 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007780 = mServiceConnections.values().iterator();
7781 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007782 ArrayList<ConnectionRecord> r = it.next();
7783 for (int i=0; i<r.size(); i++) {
7784 pw.print(" * "); pw.println(r.get(i));
7785 r.get(i).dump(pw, " ");
7786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007788 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 }
7790 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007791
7792 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 }
7794
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007795 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7796 int opti, boolean dumpAll) {
7797 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007799 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 if (mProvidersByClass.size() > 0) {
7801 if (needSep) pw.println(" ");
7802 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007803 Iterator<Map.Entry<String, ContentProviderRecord>> it
7804 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007806 Map.Entry<String, ContentProviderRecord> e = it.next();
7807 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007808 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809 r.dump(pw, " ");
7810 }
7811 needSep = true;
7812 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007813
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007814 if (mProvidersByName.size() > 0) {
7815 pw.println(" ");
7816 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007817 Iterator<Map.Entry<String, ContentProviderRecord>> it
7818 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007819 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.print(e.getKey()); pw.print(": ");
7823 pw.println(r);
7824 }
7825 needSep = true;
7826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007828
7829 if (mLaunchingProviders.size() > 0) {
7830 if (needSep) pw.println(" ");
7831 pw.println(" Launching content providers:");
7832 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7833 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7834 pw.println(mLaunchingProviders.get(i));
7835 }
7836 needSep = true;
7837 }
7838
7839 if (mGrantedUriPermissions.size() > 0) {
7840 pw.println();
7841 pw.println("Granted Uri Permissions:");
7842 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7843 int uid = mGrantedUriPermissions.keyAt(i);
7844 HashMap<Uri, UriPermission> perms
7845 = mGrantedUriPermissions.valueAt(i);
7846 pw.print(" * UID "); pw.print(uid);
7847 pw.println(" holds:");
7848 for (UriPermission perm : perms.values()) {
7849 pw.print(" "); pw.println(perm);
7850 perm.dump(pw, " ");
7851 }
7852 }
7853 needSep = true;
7854 }
7855
7856 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 }
7858
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007859 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7860 int opti, boolean dumpAll) {
7861 boolean needSep = false;
7862
7863 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007864 if (this.mIntentSenderRecords.size() > 0) {
7865 Iterator<WeakReference<PendingIntentRecord>> it
7866 = mIntentSenderRecords.values().iterator();
7867 while (it.hasNext()) {
7868 WeakReference<PendingIntentRecord> ref = it.next();
7869 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007870 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007872 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007873 rec.dump(pw, " ");
7874 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007875 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 }
7877 }
7878 }
7879 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007880
7881 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 }
7883
7884 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007885 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 TaskRecord lastTask = null;
7887 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007888 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007889 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 if (lastTask != r.task) {
7891 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007892 pw.print(prefix);
7893 pw.print(full ? "* " : " ");
7894 pw.println(lastTask);
7895 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007896 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007899 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7900 pw.print(" #"); pw.print(i); pw.print(": ");
7901 pw.println(r);
7902 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007903 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 }
7906 }
7907
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007908 private static String buildOomTag(String prefix, String space, int val, int base) {
7909 if (val == base) {
7910 if (space == null) return prefix;
7911 return prefix + " ";
7912 }
7913 return prefix + "+" + Integer.toString(val-base);
7914 }
7915
7916 private static final int dumpProcessList(PrintWriter pw,
7917 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007918 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007920 final int N = list.size()-1;
7921 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007923 pw.println(String.format("%s%s #%2d: %s",
7924 prefix, (r.persistent ? persistentLabel : normalLabel),
7925 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926 if (r.persistent) {
7927 numPers++;
7928 }
7929 }
7930 return numPers;
7931 }
7932
Dianne Hackborn287952c2010-09-22 22:34:31 -07007933 private static final void dumpProcessOomList(PrintWriter pw,
7934 ActivityManagerService service, List<ProcessRecord> list,
7935 String prefix, String normalLabel, String persistentLabel,
7936 boolean inclDetails) {
7937
7938 final long curRealtime = SystemClock.elapsedRealtime();
7939 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7940 final long curUptime = SystemClock.uptimeMillis();
7941 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7942
7943 final int N = list.size()-1;
7944 for (int i=N; i>=0; i--) {
7945 ProcessRecord r = list.get(i);
7946 String oomAdj;
7947 if (r.setAdj >= EMPTY_APP_ADJ) {
7948 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7949 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7950 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7951 } else if (r.setAdj >= HOME_APP_ADJ) {
7952 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7953 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7954 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7955 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7956 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7957 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7958 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7959 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7960 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7961 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7962 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7963 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7964 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7965 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7966 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7967 } else if (r.setAdj >= SYSTEM_ADJ) {
7968 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7969 } else {
7970 oomAdj = Integer.toString(r.setAdj);
7971 }
7972 String schedGroup;
7973 switch (r.setSchedGroup) {
7974 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7975 schedGroup = "B";
7976 break;
7977 case Process.THREAD_GROUP_DEFAULT:
7978 schedGroup = "F";
7979 break;
7980 default:
7981 schedGroup = Integer.toString(r.setSchedGroup);
7982 break;
7983 }
7984 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7985 prefix, (r.persistent ? persistentLabel : normalLabel),
7986 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
7987 if (r.adjSource != null || r.adjTarget != null) {
7988 pw.print(prefix);
7989 pw.print(" ");
7990 if (r.adjTarget instanceof ComponentName) {
7991 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7992 } else if (r.adjTarget != null) {
7993 pw.print(r.adjTarget.toString());
7994 } else {
7995 pw.print("{null}");
7996 }
7997 pw.print("<=");
7998 if (r.adjSource instanceof ProcessRecord) {
7999 pw.print("Proc{");
8000 pw.print(((ProcessRecord)r.adjSource).toShortString());
8001 pw.println("}");
8002 } else if (r.adjSource != null) {
8003 pw.println(r.adjSource.toString());
8004 } else {
8005 pw.println("{null}");
8006 }
8007 }
8008 if (inclDetails) {
8009 pw.print(prefix);
8010 pw.print(" ");
8011 pw.print("oom: max="); pw.print(r.maxAdj);
8012 pw.print(" hidden="); pw.print(r.hiddenAdj);
8013 pw.print(" curRaw="); pw.print(r.curRawAdj);
8014 pw.print(" setRaw="); pw.print(r.setRawAdj);
8015 pw.print(" cur="); pw.print(r.curAdj);
8016 pw.print(" set="); pw.println(r.setAdj);
8017 pw.print(prefix);
8018 pw.print(" ");
8019 pw.print("keeping="); pw.print(r.keeping);
8020 pw.print(" hidden="); pw.print(r.hidden);
8021 pw.print(" empty="); pw.println(r.empty);
8022
8023 if (!r.keeping) {
8024 if (r.lastWakeTime != 0) {
8025 long wtime;
8026 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8027 synchronized (stats) {
8028 wtime = stats.getProcessWakeTime(r.info.uid,
8029 r.pid, curRealtime);
8030 }
8031 long timeUsed = wtime - r.lastWakeTime;
8032 pw.print(prefix);
8033 pw.print(" ");
8034 pw.print("keep awake over ");
8035 TimeUtils.formatDuration(realtimeSince, pw);
8036 pw.print(" used ");
8037 TimeUtils.formatDuration(timeUsed, pw);
8038 pw.print(" (");
8039 pw.print((timeUsed*100)/realtimeSince);
8040 pw.println("%)");
8041 }
8042 if (r.lastCpuTime != 0) {
8043 long timeUsed = r.curCpuTime - r.lastCpuTime;
8044 pw.print(prefix);
8045 pw.print(" ");
8046 pw.print("run cpu over ");
8047 TimeUtils.formatDuration(uptimeSince, pw);
8048 pw.print(" used ");
8049 TimeUtils.formatDuration(timeUsed, pw);
8050 pw.print(" (");
8051 pw.print((timeUsed*100)/uptimeSince);
8052 pw.println("%)");
8053 }
8054 }
8055 }
8056 }
8057 }
8058
Dianne Hackborn472ad872010-04-07 17:31:48 -07008059 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008060 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008061 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008062 long uptime = SystemClock.uptimeMillis();
8063 long realtime = SystemClock.elapsedRealtime();
8064
8065 if (isCheckinRequest) {
8066 // short checkin version
8067 pw.println(uptime + "," + realtime);
8068 pw.flush();
8069 } else {
8070 pw.println("Applications Memory Usage (kB):");
8071 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8072 }
8073 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8074 ProcessRecord r = (ProcessRecord)list.get(i);
8075 if (r.thread != null) {
8076 if (!isCheckinRequest) {
8077 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8078 pw.flush();
8079 }
8080 try {
8081 r.thread.asBinder().dump(fd, args);
8082 } catch (RemoteException e) {
8083 if (!isCheckinRequest) {
8084 pw.println("Got RemoteException!");
8085 pw.flush();
8086 }
8087 }
8088 }
8089 }
8090 }
8091
8092 /**
8093 * Searches array of arguments for the specified string
8094 * @param args array of argument strings
8095 * @param value value to search for
8096 * @return true if the value is contained in the array
8097 */
8098 private static boolean scanArgs(String[] args, String value) {
8099 if (args != null) {
8100 for (String arg : args) {
8101 if (value.equals(arg)) {
8102 return true;
8103 }
8104 }
8105 }
8106 return false;
8107 }
8108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 private final void killServicesLocked(ProcessRecord app,
8110 boolean allowRestart) {
8111 // Report disconnected services.
8112 if (false) {
8113 // XXX we are letting the client link to the service for
8114 // death notifications.
8115 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008116 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008118 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008120 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 = r.connections.values().iterator();
8122 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008123 ArrayList<ConnectionRecord> cl = jt.next();
8124 for (int i=0; i<cl.size(); i++) {
8125 ConnectionRecord c = cl.get(i);
8126 if (c.binding.client != app) {
8127 try {
8128 //c.conn.connected(r.className, null);
8129 } catch (Exception e) {
8130 // todo: this should be asynchronous!
8131 Slog.w(TAG, "Exception thrown disconnected servce "
8132 + r.shortName
8133 + " from app " + app.processName, e);
8134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 }
8136 }
8137 }
8138 }
8139 }
8140 }
8141 }
8142
8143 // Clean up any connections this application has to other services.
8144 if (app.connections.size() > 0) {
8145 Iterator<ConnectionRecord> it = app.connections.iterator();
8146 while (it.hasNext()) {
8147 ConnectionRecord r = it.next();
8148 removeConnectionLocked(r, app, null);
8149 }
8150 }
8151 app.connections.clear();
8152
8153 if (app.services.size() != 0) {
8154 // Any services running in the application need to be placed
8155 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008156 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008157 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008158 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 synchronized (sr.stats.getBatteryStats()) {
8160 sr.stats.stopLaunchedLocked();
8161 }
8162 sr.app = null;
8163 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008164 if (mStoppingServices.remove(sr)) {
8165 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8166 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008167
8168 boolean hasClients = sr.bindings.size() > 0;
8169 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008170 Iterator<IntentBindRecord> bindings
8171 = sr.bindings.values().iterator();
8172 while (bindings.hasNext()) {
8173 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008174 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 + ": shouldUnbind=" + b.hasBound);
8176 b.binder = null;
8177 b.requested = b.received = b.hasBound = false;
8178 }
8179 }
8180
8181 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008182 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008184 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 sr.crashCount, sr.shortName, app.pid);
8186 bringDownServiceLocked(sr, true);
8187 } else if (!allowRestart) {
8188 bringDownServiceLocked(sr, true);
8189 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008190 boolean canceled = scheduleServiceRestartLocked(sr, true);
8191
8192 // Should the service remain running? Note that in the
8193 // extreme case of so many attempts to deliver a command
8194 // that it failed, that we also will stop it here.
8195 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8196 if (sr.pendingStarts.size() == 0) {
8197 sr.startRequested = false;
8198 if (!hasClients) {
8199 // Whoops, no reason to restart!
8200 bringDownServiceLocked(sr, true);
8201 }
8202 }
8203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 }
8205 }
8206
8207 if (!allowRestart) {
8208 app.services.clear();
8209 }
8210 }
8211
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008212 // Make sure we have no more records on the stopping list.
8213 int i = mStoppingServices.size();
8214 while (i > 0) {
8215 i--;
8216 ServiceRecord sr = mStoppingServices.get(i);
8217 if (sr.app == app) {
8218 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008219 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008220 }
8221 }
8222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 app.executingServices.clear();
8224 }
8225
8226 private final void removeDyingProviderLocked(ProcessRecord proc,
8227 ContentProviderRecord cpr) {
8228 synchronized (cpr) {
8229 cpr.launchingApp = null;
8230 cpr.notifyAll();
8231 }
8232
8233 mProvidersByClass.remove(cpr.info.name);
8234 String names[] = cpr.info.authority.split(";");
8235 for (int j = 0; j < names.length; j++) {
8236 mProvidersByName.remove(names[j]);
8237 }
8238
8239 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8240 while (cit.hasNext()) {
8241 ProcessRecord capp = cit.next();
8242 if (!capp.persistent && capp.thread != null
8243 && capp.pid != 0
8244 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008245 Slog.i(TAG, "Kill " + capp.processName
8246 + " (pid " + capp.pid + "): provider " + cpr.info.name
8247 + " in dying process " + proc.processName);
8248 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8249 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008250 Process.killProcess(capp.pid);
8251 }
8252 }
8253
8254 mLaunchingProviders.remove(cpr);
8255 }
8256
8257 /**
8258 * Main code for cleaning up a process when it has gone away. This is
8259 * called both as a result of the process dying, or directly when stopping
8260 * a process when running in single process mode.
8261 */
8262 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8263 boolean restarting, int index) {
8264 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008265 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 }
8267
Dianne Hackborn36124872009-10-08 16:22:03 -07008268 mProcessesToGc.remove(app);
8269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 // Dismiss any open dialogs.
8271 if (app.crashDialog != null) {
8272 app.crashDialog.dismiss();
8273 app.crashDialog = null;
8274 }
8275 if (app.anrDialog != null) {
8276 app.anrDialog.dismiss();
8277 app.anrDialog = null;
8278 }
8279 if (app.waitDialog != null) {
8280 app.waitDialog.dismiss();
8281 app.waitDialog = null;
8282 }
8283
8284 app.crashing = false;
8285 app.notResponding = false;
8286
8287 app.resetPackageList();
8288 app.thread = null;
8289 app.forcingToForeground = null;
8290 app.foregroundServices = false;
8291
8292 killServicesLocked(app, true);
8293
8294 boolean restart = false;
8295
8296 int NL = mLaunchingProviders.size();
8297
8298 // Remove published content providers.
8299 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008300 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008302 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 cpr.provider = null;
8304 cpr.app = null;
8305
8306 // See if someone is waiting for this provider... in which
8307 // case we don't remove it, but just let it restart.
8308 int i = 0;
8309 if (!app.bad) {
8310 for (; i<NL; i++) {
8311 if (mLaunchingProviders.get(i) == cpr) {
8312 restart = true;
8313 break;
8314 }
8315 }
8316 } else {
8317 i = NL;
8318 }
8319
8320 if (i >= NL) {
8321 removeDyingProviderLocked(app, cpr);
8322 NL = mLaunchingProviders.size();
8323 }
8324 }
8325 app.pubProviders.clear();
8326 }
8327
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008328 // Take care of any launching providers waiting for this process.
8329 if (checkAppInLaunchingProvidersLocked(app, false)) {
8330 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008331 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008333 // Unregister from connected content providers.
8334 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008335 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 while (it.hasNext()) {
8337 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8338 cpr.clients.remove(app);
8339 }
8340 app.conProviders.clear();
8341 }
8342
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008343 // At this point there may be remaining entries in mLaunchingProviders
8344 // where we were the only one waiting, so they are no longer of use.
8345 // Look for these and clean up if found.
8346 // XXX Commented out for now. Trying to figure out a way to reproduce
8347 // the actual situation to identify what is actually going on.
8348 if (false) {
8349 for (int i=0; i<NL; i++) {
8350 ContentProviderRecord cpr = (ContentProviderRecord)
8351 mLaunchingProviders.get(i);
8352 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8353 synchronized (cpr) {
8354 cpr.launchingApp = null;
8355 cpr.notifyAll();
8356 }
8357 }
8358 }
8359 }
8360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 skipCurrentReceiverLocked(app);
8362
8363 // Unregister any receivers.
8364 if (app.receivers.size() > 0) {
8365 Iterator<ReceiverList> it = app.receivers.iterator();
8366 while (it.hasNext()) {
8367 removeReceiverLocked(it.next());
8368 }
8369 app.receivers.clear();
8370 }
8371
Christopher Tate181fafa2009-05-14 11:12:14 -07008372 // If the app is undergoing backup, tell the backup manager about it
8373 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008374 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008375 try {
8376 IBackupManager bm = IBackupManager.Stub.asInterface(
8377 ServiceManager.getService(Context.BACKUP_SERVICE));
8378 bm.agentDisconnected(app.info.packageName);
8379 } catch (RemoteException e) {
8380 // can't happen; backup manager is local
8381 }
8382 }
8383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 // If the caller is restarting this app, then leave it in its
8385 // current lists and let the caller take care of it.
8386 if (restarting) {
8387 return;
8388 }
8389
8390 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008391 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008392 "Removing non-persistent process during cleanup: " + app);
8393 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008394 if (mHeavyWeightProcess == app) {
8395 mHeavyWeightProcess = null;
8396 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 } else if (!app.removed) {
8399 // This app is persistent, so we need to keep its record around.
8400 // If it is not already on the pending app list, add it there
8401 // and start a new process for it.
8402 app.thread = null;
8403 app.forcingToForeground = null;
8404 app.foregroundServices = false;
8405 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8406 mPersistentStartingProcesses.add(app);
8407 restart = true;
8408 }
8409 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008410 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8411 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 mProcessesOnHold.remove(app);
8413
The Android Open Source Project4df24232009-03-05 14:34:35 -08008414 if (app == mHomeProcess) {
8415 mHomeProcess = null;
8416 }
8417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008418 if (restart) {
8419 // We have components that still need to be running in the
8420 // process, so re-launch it.
8421 mProcessNames.put(app.processName, app.info.uid, app);
8422 startProcessLocked(app, "restart", app.processName);
8423 } else if (app.pid > 0 && app.pid != MY_PID) {
8424 // Goodbye!
8425 synchronized (mPidsSelfLocked) {
8426 mPidsSelfLocked.remove(app.pid);
8427 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8428 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008429 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 }
8431 }
8432
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008433 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8434 // Look through the content providers we are waiting to have launched,
8435 // and if any run in this process then either schedule a restart of
8436 // the process or kill the client waiting for it if this process has
8437 // gone bad.
8438 int NL = mLaunchingProviders.size();
8439 boolean restart = false;
8440 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008441 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008442 if (cpr.launchingApp == app) {
8443 if (!alwaysBad && !app.bad) {
8444 restart = true;
8445 } else {
8446 removeDyingProviderLocked(app, cpr);
8447 NL = mLaunchingProviders.size();
8448 }
8449 }
8450 }
8451 return restart;
8452 }
8453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008454 // =========================================================
8455 // SERVICES
8456 // =========================================================
8457
8458 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8459 ActivityManager.RunningServiceInfo info =
8460 new ActivityManager.RunningServiceInfo();
8461 info.service = r.name;
8462 if (r.app != null) {
8463 info.pid = r.app.pid;
8464 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008465 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008466 info.process = r.processName;
8467 info.foreground = r.isForeground;
8468 info.activeSince = r.createTime;
8469 info.started = r.startRequested;
8470 info.clientCount = r.connections.size();
8471 info.crashCount = r.crashCount;
8472 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008473 if (r.isForeground) {
8474 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8475 }
8476 if (r.startRequested) {
8477 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8478 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008479 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008480 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8481 }
8482 if (r.app != null && r.app.persistent) {
8483 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8484 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008485
8486 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8487 for (int i=0; i<connl.size(); i++) {
8488 ConnectionRecord conn = connl.get(i);
8489 if (conn.clientLabel != 0) {
8490 info.clientPackage = conn.binding.client.info.packageName;
8491 info.clientLabel = conn.clientLabel;
8492 return info;
8493 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008494 }
8495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 return info;
8497 }
8498
8499 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8500 int flags) {
8501 synchronized (this) {
8502 ArrayList<ActivityManager.RunningServiceInfo> res
8503 = new ArrayList<ActivityManager.RunningServiceInfo>();
8504
8505 if (mServices.size() > 0) {
8506 Iterator<ServiceRecord> it = mServices.values().iterator();
8507 while (it.hasNext() && res.size() < maxNum) {
8508 res.add(makeRunningServiceInfoLocked(it.next()));
8509 }
8510 }
8511
8512 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8513 ServiceRecord r = mRestartingServices.get(i);
8514 ActivityManager.RunningServiceInfo info =
8515 makeRunningServiceInfoLocked(r);
8516 info.restarting = r.nextRestartTime;
8517 res.add(info);
8518 }
8519
8520 return res;
8521 }
8522 }
8523
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008524 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8525 synchronized (this) {
8526 ServiceRecord r = mServices.get(name);
8527 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008528 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8529 for (int i=0; i<conn.size(); i++) {
8530 if (conn.get(i).clientIntent != null) {
8531 return conn.get(i).clientIntent;
8532 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008533 }
8534 }
8535 }
8536 }
8537 return null;
8538 }
8539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 private final ServiceRecord findServiceLocked(ComponentName name,
8541 IBinder token) {
8542 ServiceRecord r = mServices.get(name);
8543 return r == token ? r : null;
8544 }
8545
8546 private final class ServiceLookupResult {
8547 final ServiceRecord record;
8548 final String permission;
8549
8550 ServiceLookupResult(ServiceRecord _record, String _permission) {
8551 record = _record;
8552 permission = _permission;
8553 }
8554 };
8555
8556 private ServiceLookupResult findServiceLocked(Intent service,
8557 String resolvedType) {
8558 ServiceRecord r = null;
8559 if (service.getComponent() != null) {
8560 r = mServices.get(service.getComponent());
8561 }
8562 if (r == null) {
8563 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8564 r = mServicesByIntent.get(filter);
8565 }
8566
8567 if (r == null) {
8568 try {
8569 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008570 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 service, resolvedType, 0);
8572 ServiceInfo sInfo =
8573 rInfo != null ? rInfo.serviceInfo : null;
8574 if (sInfo == null) {
8575 return null;
8576 }
8577
8578 ComponentName name = new ComponentName(
8579 sInfo.applicationInfo.packageName, sInfo.name);
8580 r = mServices.get(name);
8581 } catch (RemoteException ex) {
8582 // pm is in same process, this will never happen.
8583 }
8584 }
8585 if (r != null) {
8586 int callingPid = Binder.getCallingPid();
8587 int callingUid = Binder.getCallingUid();
8588 if (checkComponentPermission(r.permission,
8589 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8590 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008591 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008592 + " from pid=" + callingPid
8593 + ", uid=" + callingUid
8594 + " requires " + r.permission);
8595 return new ServiceLookupResult(null, r.permission);
8596 }
8597 return new ServiceLookupResult(r, null);
8598 }
8599 return null;
8600 }
8601
8602 private class ServiceRestarter implements Runnable {
8603 private ServiceRecord mService;
8604
8605 void setService(ServiceRecord service) {
8606 mService = service;
8607 }
8608
8609 public void run() {
8610 synchronized(ActivityManagerService.this) {
8611 performServiceRestartLocked(mService);
8612 }
8613 }
8614 }
8615
8616 private ServiceLookupResult retrieveServiceLocked(Intent service,
8617 String resolvedType, int callingPid, int callingUid) {
8618 ServiceRecord r = null;
8619 if (service.getComponent() != null) {
8620 r = mServices.get(service.getComponent());
8621 }
8622 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8623 r = mServicesByIntent.get(filter);
8624 if (r == null) {
8625 try {
8626 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008627 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008628 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 ServiceInfo sInfo =
8630 rInfo != null ? rInfo.serviceInfo : null;
8631 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008632 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 ": not found");
8634 return null;
8635 }
8636
8637 ComponentName name = new ComponentName(
8638 sInfo.applicationInfo.packageName, sInfo.name);
8639 r = mServices.get(name);
8640 if (r == null) {
8641 filter = new Intent.FilterComparison(service.cloneFilter());
8642 ServiceRestarter res = new ServiceRestarter();
8643 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8644 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8645 synchronized (stats) {
8646 ss = stats.getServiceStatsLocked(
8647 sInfo.applicationInfo.uid, sInfo.packageName,
8648 sInfo.name);
8649 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008650 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 res.setService(r);
8652 mServices.put(name, r);
8653 mServicesByIntent.put(filter, r);
8654
8655 // Make sure this component isn't in the pending list.
8656 int N = mPendingServices.size();
8657 for (int i=0; i<N; i++) {
8658 ServiceRecord pr = mPendingServices.get(i);
8659 if (pr.name.equals(name)) {
8660 mPendingServices.remove(i);
8661 i--;
8662 N--;
8663 }
8664 }
8665 }
8666 } catch (RemoteException ex) {
8667 // pm is in same process, this will never happen.
8668 }
8669 }
8670 if (r != null) {
8671 if (checkComponentPermission(r.permission,
8672 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8673 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008674 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008675 + " from pid=" + Binder.getCallingPid()
8676 + ", uid=" + Binder.getCallingUid()
8677 + " requires " + r.permission);
8678 return new ServiceLookupResult(null, r.permission);
8679 }
8680 return new ServiceLookupResult(r, null);
8681 }
8682 return null;
8683 }
8684
Dianne Hackborn287952c2010-09-22 22:34:31 -07008685 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8686 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8687 + why + " of " + r + " in app " + r.app);
8688 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8689 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008690 long now = SystemClock.uptimeMillis();
8691 if (r.executeNesting == 0 && r.app != null) {
8692 if (r.app.executingServices.size() == 0) {
8693 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8694 msg.obj = r.app;
8695 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8696 }
8697 r.app.executingServices.add(r);
8698 }
8699 r.executeNesting++;
8700 r.executingStart = now;
8701 }
8702
8703 private final void sendServiceArgsLocked(ServiceRecord r,
8704 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008705 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 if (N == 0) {
8707 return;
8708 }
8709
Dianne Hackborn39792d22010-08-19 18:01:52 -07008710 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008712 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008713 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8714 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008715 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008716 // If somehow we got a dummy start at the front, then
8717 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008718 continue;
8719 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008720 si.deliveredTime = SystemClock.uptimeMillis();
8721 r.deliveredStarts.add(si);
8722 si.deliveryCount++;
8723 if (si.targetPermissionUid >= 0) {
8724 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008725 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008726 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008727 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 if (!oomAdjusted) {
8729 oomAdjusted = true;
8730 updateOomAdjLocked(r.app);
8731 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008732 int flags = 0;
8733 if (si.deliveryCount > 0) {
8734 flags |= Service.START_FLAG_RETRY;
8735 }
8736 if (si.doneExecutingCount > 0) {
8737 flags |= Service.START_FLAG_REDELIVERY;
8738 }
8739 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008740 } catch (RemoteException e) {
8741 // Remote process gone... we'll let the normal cleanup take
8742 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008743 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008744 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008746 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 break;
8748 }
8749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008750 }
8751
8752 private final boolean requestServiceBindingLocked(ServiceRecord r,
8753 IntentBindRecord i, boolean rebind) {
8754 if (r.app == null || r.app.thread == null) {
8755 // If service is not currently running, can't yet bind.
8756 return false;
8757 }
8758 if ((!i.requested || rebind) && i.apps.size() > 0) {
8759 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008760 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8762 if (!rebind) {
8763 i.requested = true;
8764 }
8765 i.hasBound = true;
8766 i.doRebind = false;
8767 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008768 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769 return false;
8770 }
8771 }
8772 return true;
8773 }
8774
8775 private final void requestServiceBindingsLocked(ServiceRecord r) {
8776 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8777 while (bindings.hasNext()) {
8778 IntentBindRecord i = bindings.next();
8779 if (!requestServiceBindingLocked(r, i, false)) {
8780 break;
8781 }
8782 }
8783 }
8784
8785 private final void realStartServiceLocked(ServiceRecord r,
8786 ProcessRecord app) throws RemoteException {
8787 if (app.thread == null) {
8788 throw new RemoteException();
8789 }
8790
8791 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008792 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793
8794 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008795 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008796 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008797
8798 boolean created = false;
8799 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008800 mStringBuilder.setLength(0);
8801 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008802 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008804 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 synchronized (r.stats.getBatteryStats()) {
8806 r.stats.startLaunchedLocked();
8807 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008808 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008810 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 created = true;
8812 } finally {
8813 if (!created) {
8814 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008815 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 }
8817 }
8818
8819 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008820
8821 // If the service is in the started state, and there are no
8822 // pending arguments, then fake up one so its onStartCommand() will
8823 // be called.
8824 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8825 r.lastStartId++;
8826 if (r.lastStartId < 1) {
8827 r.lastStartId = 1;
8828 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008829 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008830 }
8831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008832 sendServiceArgsLocked(r, true);
8833 }
8834
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008835 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8836 boolean allowCancel) {
8837 boolean canceled = false;
8838
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008839 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008840 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008841 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008842
8843 // Any delivered but not yet finished starts should be put back
8844 // on the pending list.
8845 final int N = r.deliveredStarts.size();
8846 if (N > 0) {
8847 for (int i=N-1; i>=0; i--) {
8848 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008849 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008850 if (si.intent == null) {
8851 // We'll generate this again if needed.
8852 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8853 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8854 r.pendingStarts.add(0, si);
8855 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8856 dur *= 2;
8857 if (minDuration < dur) minDuration = dur;
8858 if (resetTime < dur) resetTime = dur;
8859 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008860 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008861 + r.name);
8862 canceled = true;
8863 }
8864 }
8865 r.deliveredStarts.clear();
8866 }
8867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 r.totalRestartCount++;
8869 if (r.restartDelay == 0) {
8870 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008871 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 } else {
8873 // If it has been a "reasonably long time" since the service
8874 // was started, then reset our restart duration back to
8875 // the beginning, so we don't infinitely increase the duration
8876 // on a service that just occasionally gets killed (which is
8877 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008878 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008880 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008881 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008882 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008883 if (r.restartDelay < minDuration) {
8884 r.restartDelay = minDuration;
8885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 }
8887 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008888
8889 r.nextRestartTime = now + r.restartDelay;
8890
8891 // Make sure that we don't end up restarting a bunch of services
8892 // all at the same time.
8893 boolean repeat;
8894 do {
8895 repeat = false;
8896 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8897 ServiceRecord r2 = mRestartingServices.get(i);
8898 if (r2 != r && r.nextRestartTime
8899 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8900 && r.nextRestartTime
8901 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8902 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8903 r.restartDelay = r.nextRestartTime - now;
8904 repeat = true;
8905 break;
8906 }
8907 }
8908 } while (repeat);
8909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 if (!mRestartingServices.contains(r)) {
8911 mRestartingServices.add(r);
8912 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008913
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008914 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008917 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008918 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008919 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008921 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008922 r.shortName, r.restartDelay);
8923
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008924 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008925 }
8926
8927 final void performServiceRestartLocked(ServiceRecord r) {
8928 if (!mRestartingServices.contains(r)) {
8929 return;
8930 }
8931 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8932 }
8933
8934 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8935 if (r.restartDelay == 0) {
8936 return false;
8937 }
8938 r.resetRestartCounter();
8939 mRestartingServices.remove(r);
8940 mHandler.removeCallbacks(r.restarter);
8941 return true;
8942 }
8943
8944 private final boolean bringUpServiceLocked(ServiceRecord r,
8945 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008946 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 //r.dump(" ");
8948
Dianne Hackborn36124872009-10-08 16:22:03 -07008949 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 sendServiceArgsLocked(r, false);
8951 return true;
8952 }
8953
8954 if (!whileRestarting && r.restartDelay > 0) {
8955 // If waiting for a restart, then do nothing.
8956 return true;
8957 }
8958
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008959 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008961 // We are now bringing the service up, so no longer in the
8962 // restarting state.
8963 mRestartingServices.remove(r);
8964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008965 final String appName = r.processName;
8966 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8967 if (app != null && app.thread != null) {
8968 try {
8969 realStartServiceLocked(r, app);
8970 return true;
8971 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008972 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 }
8974
8975 // If a dead object exception was thrown -- fall through to
8976 // restart the application.
8977 }
8978
Dianne Hackborn36124872009-10-08 16:22:03 -07008979 // Not running -- get it started, and enqueue this service record
8980 // to be executed when the app comes up.
8981 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8982 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008983 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008984 + r.appInfo.packageName + "/"
8985 + r.appInfo.uid + " for service "
8986 + r.intent.getIntent() + ": process is bad");
8987 bringDownServiceLocked(r, true);
8988 return false;
8989 }
8990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 mPendingServices.add(r);
8993 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 return true;
8996 }
8997
8998 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008999 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 //r.dump(" ");
9001
9002 // Does it still need to run?
9003 if (!force && r.startRequested) {
9004 return;
9005 }
9006 if (r.connections.size() > 0) {
9007 if (!force) {
9008 // XXX should probably keep a count of the number of auto-create
9009 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009010 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009011 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009012 ArrayList<ConnectionRecord> cr = it.next();
9013 for (int i=0; i<cr.size(); i++) {
9014 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9015 return;
9016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009017 }
9018 }
9019 }
9020
9021 // Report to all of the connections that the service is no longer
9022 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009023 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009025 ArrayList<ConnectionRecord> c = it.next();
9026 for (int i=0; i<c.size(); i++) {
9027 try {
9028 c.get(i).conn.connected(r.name, null);
9029 } catch (Exception e) {
9030 Slog.w(TAG, "Failure disconnecting service " + r.name +
9031 " to connection " + c.get(i).conn.asBinder() +
9032 " (in " + c.get(i).binding.client.processName + ")", e);
9033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 }
9035 }
9036 }
9037
9038 // Tell the service that it has been unbound.
9039 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9040 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9041 while (it.hasNext()) {
9042 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009043 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 + ": hasBound=" + ibr.hasBound);
9045 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9046 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009047 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009048 updateOomAdjLocked(r.app);
9049 ibr.hasBound = false;
9050 r.app.thread.scheduleUnbindService(r,
9051 ibr.intent.getIntent());
9052 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009053 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 + r.shortName, e);
9055 serviceDoneExecutingLocked(r, true);
9056 }
9057 }
9058 }
9059 }
9060
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009061 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009062 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 System.identityHashCode(r), r.shortName,
9064 (r.app != null) ? r.app.pid : -1);
9065
9066 mServices.remove(r.name);
9067 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 r.totalRestartCount = 0;
9069 unscheduleServiceRestartLocked(r);
9070
9071 // Also make sure it is not on the pending list.
9072 int N = mPendingServices.size();
9073 for (int i=0; i<N; i++) {
9074 if (mPendingServices.get(i) == r) {
9075 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009076 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 i--;
9078 N--;
9079 }
9080 }
9081
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009082 r.cancelNotification();
9083 r.isForeground = false;
9084 r.foregroundId = 0;
9085 r.foregroundNoti = null;
9086
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009087 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009088 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009089 r.pendingStarts.clear();
9090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 if (r.app != null) {
9092 synchronized (r.stats.getBatteryStats()) {
9093 r.stats.stopLaunchedLocked();
9094 }
9095 r.app.services.remove(r);
9096 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009098 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 mStoppingServices.add(r);
9100 updateOomAdjLocked(r.app);
9101 r.app.thread.scheduleStopService(r);
9102 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009103 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 + r.shortName, e);
9105 serviceDoneExecutingLocked(r, true);
9106 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009107 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009109 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009110 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 }
9112 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009113 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009114 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009115 }
9116 }
9117
9118 ComponentName startServiceLocked(IApplicationThread caller,
9119 Intent service, String resolvedType,
9120 int callingPid, int callingUid) {
9121 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009122 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009123 + " type=" + resolvedType + " args=" + service.getExtras());
9124
9125 if (caller != null) {
9126 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9127 if (callerApp == null) {
9128 throw new SecurityException(
9129 "Unable to find app for caller " + caller
9130 + " (pid=" + Binder.getCallingPid()
9131 + ") when starting service " + service);
9132 }
9133 }
9134
9135 ServiceLookupResult res =
9136 retrieveServiceLocked(service, resolvedType,
9137 callingPid, callingUid);
9138 if (res == null) {
9139 return null;
9140 }
9141 if (res.record == null) {
9142 return new ComponentName("!", res.permission != null
9143 ? res.permission : "private to package");
9144 }
9145 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009146 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9147 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009149 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009150 }
9151 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009152 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 r.lastStartId++;
9154 if (r.lastStartId < 1) {
9155 r.lastStartId = 1;
9156 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009157 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9158 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009159 r.lastActivity = SystemClock.uptimeMillis();
9160 synchronized (r.stats.getBatteryStats()) {
9161 r.stats.startRunningLocked();
9162 }
9163 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9164 return new ComponentName("!", "Service process is bad");
9165 }
9166 return r.name;
9167 }
9168 }
9169
9170 public ComponentName startService(IApplicationThread caller, Intent service,
9171 String resolvedType) {
9172 // Refuse possible leaked file descriptors
9173 if (service != null && service.hasFileDescriptors() == true) {
9174 throw new IllegalArgumentException("File descriptors passed in Intent");
9175 }
9176
9177 synchronized(this) {
9178 final int callingPid = Binder.getCallingPid();
9179 final int callingUid = Binder.getCallingUid();
9180 final long origId = Binder.clearCallingIdentity();
9181 ComponentName res = startServiceLocked(caller, service,
9182 resolvedType, callingPid, callingUid);
9183 Binder.restoreCallingIdentity(origId);
9184 return res;
9185 }
9186 }
9187
9188 ComponentName startServiceInPackage(int uid,
9189 Intent service, String resolvedType) {
9190 synchronized(this) {
9191 final long origId = Binder.clearCallingIdentity();
9192 ComponentName res = startServiceLocked(null, service,
9193 resolvedType, -1, uid);
9194 Binder.restoreCallingIdentity(origId);
9195 return res;
9196 }
9197 }
9198
9199 public int stopService(IApplicationThread caller, Intent service,
9200 String resolvedType) {
9201 // Refuse possible leaked file descriptors
9202 if (service != null && service.hasFileDescriptors() == true) {
9203 throw new IllegalArgumentException("File descriptors passed in Intent");
9204 }
9205
9206 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009207 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 + " type=" + resolvedType);
9209
9210 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9211 if (caller != null && callerApp == null) {
9212 throw new SecurityException(
9213 "Unable to find app for caller " + caller
9214 + " (pid=" + Binder.getCallingPid()
9215 + ") when stopping service " + service);
9216 }
9217
9218 // If this service is active, make sure it is stopped.
9219 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9220 if (r != null) {
9221 if (r.record != null) {
9222 synchronized (r.record.stats.getBatteryStats()) {
9223 r.record.stats.stopRunningLocked();
9224 }
9225 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009226 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 final long origId = Binder.clearCallingIdentity();
9228 bringDownServiceLocked(r.record, false);
9229 Binder.restoreCallingIdentity(origId);
9230 return 1;
9231 }
9232 return -1;
9233 }
9234 }
9235
9236 return 0;
9237 }
9238
9239 public IBinder peekService(Intent service, String resolvedType) {
9240 // Refuse possible leaked file descriptors
9241 if (service != null && service.hasFileDescriptors() == true) {
9242 throw new IllegalArgumentException("File descriptors passed in Intent");
9243 }
9244
9245 IBinder ret = null;
9246
9247 synchronized(this) {
9248 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9249
9250 if (r != null) {
9251 // r.record is null if findServiceLocked() failed the caller permission check
9252 if (r.record == null) {
9253 throw new SecurityException(
9254 "Permission Denial: Accessing service " + r.record.name
9255 + " from pid=" + Binder.getCallingPid()
9256 + ", uid=" + Binder.getCallingUid()
9257 + " requires " + r.permission);
9258 }
9259 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9260 if (ib != null) {
9261 ret = ib.binder;
9262 }
9263 }
9264 }
9265
9266 return ret;
9267 }
9268
9269 public boolean stopServiceToken(ComponentName className, IBinder token,
9270 int startId) {
9271 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009272 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 + " " + token + " startId=" + startId);
9274 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009275 if (r != null) {
9276 if (startId >= 0) {
9277 // Asked to only stop if done with all work. Note that
9278 // to avoid leaks, we will take this as dropping all
9279 // start items up to and including this one.
9280 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9281 if (si != null) {
9282 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009283 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9284 cur.removeUriPermissionsLocked();
9285 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009286 break;
9287 }
9288 }
9289 }
9290
9291 if (r.lastStartId != startId) {
9292 return false;
9293 }
9294
9295 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009296 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009297 + " is last, but have " + r.deliveredStarts.size()
9298 + " remaining args");
9299 }
9300 }
9301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 synchronized (r.stats.getBatteryStats()) {
9303 r.stats.stopRunningLocked();
9304 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009305 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 }
9307 final long origId = Binder.clearCallingIdentity();
9308 bringDownServiceLocked(r, false);
9309 Binder.restoreCallingIdentity(origId);
9310 return true;
9311 }
9312 }
9313 return false;
9314 }
9315
9316 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009317 int id, Notification notification, boolean removeNotification) {
9318 final long origId = Binder.clearCallingIdentity();
9319 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 synchronized(this) {
9321 ServiceRecord r = findServiceLocked(className, token);
9322 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009323 if (id != 0) {
9324 if (notification == null) {
9325 throw new IllegalArgumentException("null notification");
9326 }
9327 if (r.foregroundId != id) {
9328 r.cancelNotification();
9329 r.foregroundId = id;
9330 }
9331 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9332 r.foregroundNoti = notification;
9333 r.isForeground = true;
9334 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 if (r.app != null) {
9336 updateServiceForegroundLocked(r.app, true);
9337 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009338 } else {
9339 if (r.isForeground) {
9340 r.isForeground = false;
9341 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009342 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009343 updateServiceForegroundLocked(r.app, true);
9344 }
9345 }
9346 if (removeNotification) {
9347 r.cancelNotification();
9348 r.foregroundId = 0;
9349 r.foregroundNoti = null;
9350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009351 }
9352 }
9353 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009354 } finally {
9355 Binder.restoreCallingIdentity(origId);
9356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 }
9358
9359 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9360 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009361 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 if (sr.isForeground) {
9363 anyForeground = true;
9364 break;
9365 }
9366 }
9367 if (anyForeground != proc.foregroundServices) {
9368 proc.foregroundServices = anyForeground;
9369 if (oomAdj) {
9370 updateOomAdjLocked();
9371 }
9372 }
9373 }
9374
9375 public int bindService(IApplicationThread caller, IBinder token,
9376 Intent service, String resolvedType,
9377 IServiceConnection connection, int flags) {
9378 // Refuse possible leaked file descriptors
9379 if (service != null && service.hasFileDescriptors() == true) {
9380 throw new IllegalArgumentException("File descriptors passed in Intent");
9381 }
9382
9383 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009384 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 + " type=" + resolvedType + " conn=" + connection.asBinder()
9386 + " flags=0x" + Integer.toHexString(flags));
9387 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9388 if (callerApp == null) {
9389 throw new SecurityException(
9390 "Unable to find app for caller " + caller
9391 + " (pid=" + Binder.getCallingPid()
9392 + ") when binding service " + service);
9393 }
9394
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009395 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009397 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009398 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009399 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 return 0;
9401 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009402 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403 }
9404
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009405 int clientLabel = 0;
9406 PendingIntent clientIntent = null;
9407
9408 if (callerApp.info.uid == Process.SYSTEM_UID) {
9409 // Hacky kind of thing -- allow system stuff to tell us
9410 // what they are, so we can report this elsewhere for
9411 // others to know why certain services are running.
9412 try {
9413 clientIntent = (PendingIntent)service.getParcelableExtra(
9414 Intent.EXTRA_CLIENT_INTENT);
9415 } catch (RuntimeException e) {
9416 }
9417 if (clientIntent != null) {
9418 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9419 if (clientLabel != 0) {
9420 // There are no useful extras in the intent, trash them.
9421 // System code calling with this stuff just needs to know
9422 // this will happen.
9423 service = service.cloneFilter();
9424 }
9425 }
9426 }
9427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009428 ServiceLookupResult res =
9429 retrieveServiceLocked(service, resolvedType,
9430 Binder.getCallingPid(), Binder.getCallingUid());
9431 if (res == null) {
9432 return 0;
9433 }
9434 if (res.record == null) {
9435 return -1;
9436 }
9437 ServiceRecord s = res.record;
9438
9439 final long origId = Binder.clearCallingIdentity();
9440
9441 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009442 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009443 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009444 }
9445
9446 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9447 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009448 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449
9450 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009451 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9452 if (clist == null) {
9453 clist = new ArrayList<ConnectionRecord>();
9454 s.connections.put(binder, clist);
9455 }
9456 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009457 b.connections.add(c);
9458 if (activity != null) {
9459 if (activity.connections == null) {
9460 activity.connections = new HashSet<ConnectionRecord>();
9461 }
9462 activity.connections.add(c);
9463 }
9464 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009465 clist = mServiceConnections.get(binder);
9466 if (clist == null) {
9467 clist = new ArrayList<ConnectionRecord>();
9468 mServiceConnections.put(binder, clist);
9469 }
9470 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471
9472 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9473 s.lastActivity = SystemClock.uptimeMillis();
9474 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9475 return 0;
9476 }
9477 }
9478
9479 if (s.app != null) {
9480 // This could have made the service more important.
9481 updateOomAdjLocked(s.app);
9482 }
9483
Joe Onorato8a9b2202010-02-26 18:56:32 -08009484 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009485 + ": received=" + b.intent.received
9486 + " apps=" + b.intent.apps.size()
9487 + " doRebind=" + b.intent.doRebind);
9488
9489 if (s.app != null && b.intent.received) {
9490 // Service is already running, so we can immediately
9491 // publish the connection.
9492 try {
9493 c.conn.connected(s.name, b.intent.binder);
9494 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009495 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009496 + " to connection " + c.conn.asBinder()
9497 + " (in " + c.binding.client.processName + ")", e);
9498 }
9499
9500 // If this is the first app connected back to this binding,
9501 // and the service had previously asked to be told when
9502 // rebound, then do so.
9503 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9504 requestServiceBindingLocked(s, b.intent, true);
9505 }
9506 } else if (!b.intent.requested) {
9507 requestServiceBindingLocked(s, b.intent, false);
9508 }
9509
9510 Binder.restoreCallingIdentity(origId);
9511 }
9512
9513 return 1;
9514 }
9515
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009516 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009517 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 IBinder binder = c.conn.asBinder();
9519 AppBindRecord b = c.binding;
9520 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009521 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9522 if (clist != null) {
9523 clist.remove(c);
9524 if (clist.size() == 0) {
9525 s.connections.remove(binder);
9526 }
9527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 b.connections.remove(c);
9529 if (c.activity != null && c.activity != skipAct) {
9530 if (c.activity.connections != null) {
9531 c.activity.connections.remove(c);
9532 }
9533 }
9534 if (b.client != skipApp) {
9535 b.client.connections.remove(c);
9536 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009537 clist = mServiceConnections.get(binder);
9538 if (clist != null) {
9539 clist.remove(c);
9540 if (clist.size() == 0) {
9541 mServiceConnections.remove(binder);
9542 }
9543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544
9545 if (b.connections.size() == 0) {
9546 b.intent.apps.remove(b.client);
9547 }
9548
Joe Onorato8a9b2202010-02-26 18:56:32 -08009549 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 + ": shouldUnbind=" + b.intent.hasBound);
9551 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9552 && b.intent.hasBound) {
9553 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009554 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555 updateOomAdjLocked(s.app);
9556 b.intent.hasBound = false;
9557 // Assume the client doesn't want to know about a rebind;
9558 // we will deal with that later if it asks for one.
9559 b.intent.doRebind = false;
9560 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9561 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009562 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009563 serviceDoneExecutingLocked(s, true);
9564 }
9565 }
9566
9567 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9568 bringDownServiceLocked(s, false);
9569 }
9570 }
9571
9572 public boolean unbindService(IServiceConnection connection) {
9573 synchronized (this) {
9574 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009575 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009576 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9577 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009578 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009579 + connection.asBinder());
9580 return false;
9581 }
9582
9583 final long origId = Binder.clearCallingIdentity();
9584
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009585 while (clist.size() > 0) {
9586 ConnectionRecord r = clist.get(0);
9587 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009589 if (r.binding.service.app != null) {
9590 // This could have made the service less important.
9591 updateOomAdjLocked(r.binding.service.app);
9592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009593 }
9594
9595 Binder.restoreCallingIdentity(origId);
9596 }
9597
9598 return true;
9599 }
9600
9601 public void publishService(IBinder token, Intent intent, IBinder service) {
9602 // Refuse possible leaked file descriptors
9603 if (intent != null && intent.hasFileDescriptors() == true) {
9604 throw new IllegalArgumentException("File descriptors passed in Intent");
9605 }
9606
9607 synchronized(this) {
9608 if (!(token instanceof ServiceRecord)) {
9609 throw new IllegalArgumentException("Invalid service token");
9610 }
9611 ServiceRecord r = (ServiceRecord)token;
9612
9613 final long origId = Binder.clearCallingIdentity();
9614
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009615 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 + " " + intent + ": " + service);
9617 if (r != null) {
9618 Intent.FilterComparison filter
9619 = new Intent.FilterComparison(intent);
9620 IntentBindRecord b = r.bindings.get(filter);
9621 if (b != null && !b.received) {
9622 b.binder = service;
9623 b.requested = true;
9624 b.received = true;
9625 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009626 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 = r.connections.values().iterator();
9628 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009629 ArrayList<ConnectionRecord> clist = it.next();
9630 for (int i=0; i<clist.size(); i++) {
9631 ConnectionRecord c = clist.get(i);
9632 if (!filter.equals(c.binding.intent.intent)) {
9633 if (DEBUG_SERVICE) Slog.v(
9634 TAG, "Not publishing to: " + c);
9635 if (DEBUG_SERVICE) Slog.v(
9636 TAG, "Bound intent: " + c.binding.intent.intent);
9637 if (DEBUG_SERVICE) Slog.v(
9638 TAG, "Published intent: " + intent);
9639 continue;
9640 }
9641 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9642 try {
9643 c.conn.connected(r.name, service);
9644 } catch (Exception e) {
9645 Slog.w(TAG, "Failure sending service " + r.name +
9646 " to connection " + c.conn.asBinder() +
9647 " (in " + c.binding.client.processName + ")", e);
9648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 }
9650 }
9651 }
9652 }
9653
9654 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9655
9656 Binder.restoreCallingIdentity(origId);
9657 }
9658 }
9659 }
9660
9661 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9662 // Refuse possible leaked file descriptors
9663 if (intent != null && intent.hasFileDescriptors() == true) {
9664 throw new IllegalArgumentException("File descriptors passed in Intent");
9665 }
9666
9667 synchronized(this) {
9668 if (!(token instanceof ServiceRecord)) {
9669 throw new IllegalArgumentException("Invalid service token");
9670 }
9671 ServiceRecord r = (ServiceRecord)token;
9672
9673 final long origId = Binder.clearCallingIdentity();
9674
9675 if (r != null) {
9676 Intent.FilterComparison filter
9677 = new Intent.FilterComparison(intent);
9678 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009679 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009680 + " at " + b + ": apps="
9681 + (b != null ? b.apps.size() : 0));
9682 if (b != null) {
9683 if (b.apps.size() > 0) {
9684 // Applications have already bound since the last
9685 // unbind, so just rebind right here.
9686 requestServiceBindingLocked(r, b, true);
9687 } else {
9688 // Note to tell the service the next time there is
9689 // a new client.
9690 b.doRebind = true;
9691 }
9692 }
9693
9694 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9695
9696 Binder.restoreCallingIdentity(origId);
9697 }
9698 }
9699 }
9700
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009701 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 synchronized(this) {
9703 if (!(token instanceof ServiceRecord)) {
9704 throw new IllegalArgumentException("Invalid service token");
9705 }
9706 ServiceRecord r = (ServiceRecord)token;
9707 boolean inStopping = mStoppingServices.contains(token);
9708 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009710 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 + " with incorrect token: given " + token
9712 + ", expected " + r);
9713 return;
9714 }
9715
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009716 if (type == 1) {
9717 // This is a call from a service start... take care of
9718 // book-keeping.
9719 r.callStart = true;
9720 switch (res) {
9721 case Service.START_STICKY_COMPATIBILITY:
9722 case Service.START_STICKY: {
9723 // We are done with the associated start arguments.
9724 r.findDeliveredStart(startId, true);
9725 // Don't stop if killed.
9726 r.stopIfKilled = false;
9727 break;
9728 }
9729 case Service.START_NOT_STICKY: {
9730 // We are done with the associated start arguments.
9731 r.findDeliveredStart(startId, true);
9732 if (r.lastStartId == startId) {
9733 // There is no more work, and this service
9734 // doesn't want to hang around if killed.
9735 r.stopIfKilled = true;
9736 }
9737 break;
9738 }
9739 case Service.START_REDELIVER_INTENT: {
9740 // We'll keep this item until they explicitly
9741 // call stop for it, but keep track of the fact
9742 // that it was delivered.
9743 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9744 if (si != null) {
9745 si.deliveryCount = 0;
9746 si.doneExecutingCount++;
9747 // Don't stop if killed.
9748 r.stopIfKilled = true;
9749 }
9750 break;
9751 }
9752 default:
9753 throw new IllegalArgumentException(
9754 "Unknown service start result: " + res);
9755 }
9756 if (res == Service.START_STICKY_COMPATIBILITY) {
9757 r.callStart = false;
9758 }
9759 }
9760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 final long origId = Binder.clearCallingIdentity();
9762 serviceDoneExecutingLocked(r, inStopping);
9763 Binder.restoreCallingIdentity(origId);
9764 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009765 Slog.w(TAG, "Done executing unknown service from pid "
9766 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 }
9768 }
9769 }
9770
9771 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009772 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9773 + ": nesting=" + r.executeNesting
9774 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009775 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009776 r.executeNesting--;
9777 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009778 if (DEBUG_SERVICE) Slog.v(TAG,
9779 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 r.app.executingServices.remove(r);
9781 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009782 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9783 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9785 }
9786 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009787 if (DEBUG_SERVICE) Slog.v(TAG,
9788 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 mStoppingServices.remove(r);
9790 }
9791 updateOomAdjLocked(r.app);
9792 }
9793 }
9794
9795 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009796 String anrMessage = null;
9797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 synchronized(this) {
9799 if (proc.executingServices.size() == 0 || proc.thread == null) {
9800 return;
9801 }
9802 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9803 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9804 ServiceRecord timeout = null;
9805 long nextTime = 0;
9806 while (it.hasNext()) {
9807 ServiceRecord sr = it.next();
9808 if (sr.executingStart < maxTime) {
9809 timeout = sr;
9810 break;
9811 }
9812 if (sr.executingStart > nextTime) {
9813 nextTime = sr.executingStart;
9814 }
9815 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009816 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009817 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009818 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 } else {
9820 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9821 msg.obj = proc;
9822 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9823 }
9824 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009825
9826 if (anrMessage != null) {
9827 appNotResponding(proc, null, null, anrMessage);
9828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 }
9830
9831 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009832 // BACKUP AND RESTORE
9833 // =========================================================
9834
9835 // Cause the target app to be launched if necessary and its backup agent
9836 // instantiated. The backup agent will invoke backupAgentCreated() on the
9837 // activity manager to announce its creation.
9838 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009839 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009840 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9841
9842 synchronized(this) {
9843 // !!! TODO: currently no check here that we're already bound
9844 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9845 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9846 synchronized (stats) {
9847 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9848 }
9849
9850 BackupRecord r = new BackupRecord(ss, app, backupMode);
9851 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9852 // startProcessLocked() returns existing proc's record if it's already running
9853 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009854 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009855 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009856 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009857 return false;
9858 }
9859
9860 r.app = proc;
9861 mBackupTarget = r;
9862 mBackupAppName = app.packageName;
9863
Christopher Tate6fa95972009-06-05 18:43:55 -07009864 // Try not to kill the process during backup
9865 updateOomAdjLocked(proc);
9866
Christopher Tate181fafa2009-05-14 11:12:14 -07009867 // If the process is already attached, schedule the creation of the backup agent now.
9868 // If it is not yet live, this will be done when it attaches to the framework.
9869 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009870 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009871 try {
9872 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9873 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009874 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009875 }
9876 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009877 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009878 }
9879 // Invariants: at this point, the target app process exists and the application
9880 // is either already running or in the process of coming up. mBackupTarget and
9881 // mBackupAppName describe the app, so that when it binds back to the AM we
9882 // know that it's scheduled for a backup-agent operation.
9883 }
9884
9885 return true;
9886 }
9887
9888 // A backup agent has just come up
9889 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009890 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009891 + " = " + agent);
9892
9893 synchronized(this) {
9894 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009895 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009896 return;
9897 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009898 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009899
Dianne Hackborn06740692010-09-22 22:46:21 -07009900 long oldIdent = Binder.clearCallingIdentity();
9901 try {
9902 IBackupManager bm = IBackupManager.Stub.asInterface(
9903 ServiceManager.getService(Context.BACKUP_SERVICE));
9904 bm.agentConnected(agentPackageName, agent);
9905 } catch (RemoteException e) {
9906 // can't happen; the backup manager service is local
9907 } catch (Exception e) {
9908 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9909 e.printStackTrace();
9910 } finally {
9911 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009912 }
9913 }
9914
9915 // done with this agent
9916 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009917 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009918 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009919 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009920 return;
9921 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009922
9923 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009924 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009925 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009926 return;
9927 }
9928
Christopher Tate181fafa2009-05-14 11:12:14 -07009929 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009930 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009931 return;
9932 }
9933
Christopher Tate6fa95972009-06-05 18:43:55 -07009934 ProcessRecord proc = mBackupTarget.app;
9935 mBackupTarget = null;
9936 mBackupAppName = null;
9937
9938 // Not backing this app up any more; reset its OOM adjustment
9939 updateOomAdjLocked(proc);
9940
Christopher Tatec7b31e32009-06-10 15:49:30 -07009941 // If the app crashed during backup, 'thread' will be null here
9942 if (proc.thread != null) {
9943 try {
9944 proc.thread.scheduleDestroyBackupAgent(appInfo);
9945 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009946 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009947 e.printStackTrace();
9948 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009949 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009950 }
9951 }
9952 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 // BROADCASTS
9954 // =========================================================
9955
Josh Bartel7f208742010-02-25 11:01:44 -06009956 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 List cur) {
9958 final ContentResolver resolver = mContext.getContentResolver();
9959 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9960 if (list == null) {
9961 return cur;
9962 }
9963 int N = list.size();
9964 for (int i=0; i<N; i++) {
9965 Intent intent = list.get(i);
9966 if (filter.match(resolver, intent, true, TAG) >= 0) {
9967 if (cur == null) {
9968 cur = new ArrayList<Intent>();
9969 }
9970 cur.add(intent);
9971 }
9972 }
9973 return cur;
9974 }
9975
9976 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009977 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009978 + mBroadcastsScheduled);
9979
9980 if (mBroadcastsScheduled) {
9981 return;
9982 }
9983 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9984 mBroadcastsScheduled = true;
9985 }
9986
9987 public Intent registerReceiver(IApplicationThread caller,
9988 IIntentReceiver receiver, IntentFilter filter, String permission) {
9989 synchronized(this) {
9990 ProcessRecord callerApp = null;
9991 if (caller != null) {
9992 callerApp = getRecordForAppLocked(caller);
9993 if (callerApp == null) {
9994 throw new SecurityException(
9995 "Unable to find app for caller " + caller
9996 + " (pid=" + Binder.getCallingPid()
9997 + ") when registering receiver " + receiver);
9998 }
9999 }
10000
10001 List allSticky = null;
10002
10003 // Look for any matching sticky broadcasts...
10004 Iterator actions = filter.actionsIterator();
10005 if (actions != null) {
10006 while (actions.hasNext()) {
10007 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010008 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 }
10010 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010011 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010012 }
10013
10014 // The first sticky in the list is returned directly back to
10015 // the client.
10016 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10017
Joe Onorato8a9b2202010-02-26 18:56:32 -080010018 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 + ": " + sticky);
10020
10021 if (receiver == null) {
10022 return sticky;
10023 }
10024
10025 ReceiverList rl
10026 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10027 if (rl == null) {
10028 rl = new ReceiverList(this, callerApp,
10029 Binder.getCallingPid(),
10030 Binder.getCallingUid(), receiver);
10031 if (rl.app != null) {
10032 rl.app.receivers.add(rl);
10033 } else {
10034 try {
10035 receiver.asBinder().linkToDeath(rl, 0);
10036 } catch (RemoteException e) {
10037 return sticky;
10038 }
10039 rl.linkedToDeath = true;
10040 }
10041 mRegisteredReceivers.put(receiver.asBinder(), rl);
10042 }
10043 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10044 rl.add(bf);
10045 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010046 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 }
10048 mReceiverResolver.addFilter(bf);
10049
10050 // Enqueue broadcasts for all existing stickies that match
10051 // this filter.
10052 if (allSticky != null) {
10053 ArrayList receivers = new ArrayList();
10054 receivers.add(bf);
10055
10056 int N = allSticky.size();
10057 for (int i=0; i<N; i++) {
10058 Intent intent = (Intent)allSticky.get(i);
10059 BroadcastRecord r = new BroadcastRecord(intent, null,
10060 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010061 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062 if (mParallelBroadcasts.size() == 0) {
10063 scheduleBroadcastsLocked();
10064 }
10065 mParallelBroadcasts.add(r);
10066 }
10067 }
10068
10069 return sticky;
10070 }
10071 }
10072
10073 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010074 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075
10076 boolean doNext = false;
10077
10078 synchronized(this) {
10079 ReceiverList rl
10080 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10081 if (rl != null) {
10082 if (rl.curBroadcast != null) {
10083 BroadcastRecord r = rl.curBroadcast;
10084 doNext = finishReceiverLocked(
10085 receiver.asBinder(), r.resultCode, r.resultData,
10086 r.resultExtras, r.resultAbort, true);
10087 }
10088
10089 if (rl.app != null) {
10090 rl.app.receivers.remove(rl);
10091 }
10092 removeReceiverLocked(rl);
10093 if (rl.linkedToDeath) {
10094 rl.linkedToDeath = false;
10095 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10096 }
10097 }
10098 }
10099
10100 if (!doNext) {
10101 return;
10102 }
10103
10104 final long origId = Binder.clearCallingIdentity();
10105 processNextBroadcast(false);
10106 trimApplications();
10107 Binder.restoreCallingIdentity(origId);
10108 }
10109
10110 void removeReceiverLocked(ReceiverList rl) {
10111 mRegisteredReceivers.remove(rl.receiver.asBinder());
10112 int N = rl.size();
10113 for (int i=0; i<N; i++) {
10114 mReceiverResolver.removeFilter(rl.get(i));
10115 }
10116 }
10117
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010118 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10119 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10120 ProcessRecord r = mLruProcesses.get(i);
10121 if (r.thread != null) {
10122 try {
10123 r.thread.dispatchPackageBroadcast(cmd, packages);
10124 } catch (RemoteException ex) {
10125 }
10126 }
10127 }
10128 }
10129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 private final int broadcastIntentLocked(ProcessRecord callerApp,
10131 String callerPackage, Intent intent, String resolvedType,
10132 IIntentReceiver resultTo, int resultCode, String resultData,
10133 Bundle map, String requiredPermission,
10134 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10135 intent = new Intent(intent);
10136
Joe Onorato8a9b2202010-02-26 18:56:32 -080010137 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10139 + " ordered=" + ordered);
10140 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010141 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 }
10143
10144 // Handle special intents: if this broadcast is from the package
10145 // manager about a package being removed, we need to remove all of
10146 // its activities from the history stack.
10147 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10148 intent.getAction());
10149 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10150 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010151 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152 || uidRemoved) {
10153 if (checkComponentPermission(
10154 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10155 callingPid, callingUid, -1)
10156 == PackageManager.PERMISSION_GRANTED) {
10157 if (uidRemoved) {
10158 final Bundle intentExtras = intent.getExtras();
10159 final int uid = intentExtras != null
10160 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10161 if (uid >= 0) {
10162 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10163 synchronized (bs) {
10164 bs.removeUidStatsLocked(uid);
10165 }
10166 }
10167 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010168 // If resources are unvailble just force stop all
10169 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010170 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010171 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10172 if (list != null && (list.length > 0)) {
10173 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010174 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010175 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010176 sendPackageBroadcastLocked(
10177 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010178 }
10179 } else {
10180 Uri data = intent.getData();
10181 String ssp;
10182 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10183 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10184 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010185 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010186 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010187 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10188 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10189 new String[] {ssp});
10190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 }
10192 }
10193 }
10194 } else {
10195 String msg = "Permission Denial: " + intent.getAction()
10196 + " broadcast from " + callerPackage + " (pid=" + callingPid
10197 + ", uid=" + callingUid + ")"
10198 + " requires "
10199 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010200 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 throw new SecurityException(msg);
10202 }
10203 }
10204
10205 /*
10206 * If this is the time zone changed action, queue up a message that will reset the timezone
10207 * of all currently running processes. This message will get queued up before the broadcast
10208 * happens.
10209 */
10210 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10211 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10212 }
10213
Dianne Hackborn854060af2009-07-09 18:14:31 -070010214 /*
10215 * Prevent non-system code (defined here to be non-persistent
10216 * processes) from sending protected broadcasts.
10217 */
10218 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10219 || callingUid == Process.SHELL_UID || callingUid == 0) {
10220 // Always okay.
10221 } else if (callerApp == null || !callerApp.persistent) {
10222 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010223 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010224 intent.getAction())) {
10225 String msg = "Permission Denial: not allowed to send broadcast "
10226 + intent.getAction() + " from pid="
10227 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010228 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010229 throw new SecurityException(msg);
10230 }
10231 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010232 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010233 return BROADCAST_SUCCESS;
10234 }
10235 }
10236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 // Add to the sticky list if requested.
10238 if (sticky) {
10239 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10240 callingPid, callingUid)
10241 != PackageManager.PERMISSION_GRANTED) {
10242 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10243 + callingPid + ", uid=" + callingUid
10244 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010245 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 throw new SecurityException(msg);
10247 }
10248 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010249 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 + " and enforce permission " + requiredPermission);
10251 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10252 }
10253 if (intent.getComponent() != null) {
10254 throw new SecurityException(
10255 "Sticky broadcasts can't target a specific component");
10256 }
10257 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10258 if (list == null) {
10259 list = new ArrayList<Intent>();
10260 mStickyBroadcasts.put(intent.getAction(), list);
10261 }
10262 int N = list.size();
10263 int i;
10264 for (i=0; i<N; i++) {
10265 if (intent.filterEquals(list.get(i))) {
10266 // This sticky already exists, replace it.
10267 list.set(i, new Intent(intent));
10268 break;
10269 }
10270 }
10271 if (i >= N) {
10272 list.add(new Intent(intent));
10273 }
10274 }
10275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010276 // Figure out who all will receive this broadcast.
10277 List receivers = null;
10278 List<BroadcastFilter> registeredReceivers = null;
10279 try {
10280 if (intent.getComponent() != null) {
10281 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010282 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010283 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 if (ai != null) {
10285 receivers = new ArrayList();
10286 ResolveInfo ri = new ResolveInfo();
10287 ri.activityInfo = ai;
10288 receivers.add(ri);
10289 }
10290 } else {
10291 // Need to resolve the intent to interested receivers...
10292 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10293 == 0) {
10294 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010295 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010296 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 }
Mihai Preda074edef2009-05-18 17:13:31 +020010298 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 }
10300 } catch (RemoteException ex) {
10301 // pm is in same process, this will never happen.
10302 }
10303
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010304 final boolean replacePending =
10305 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10306
Joe Onorato8a9b2202010-02-26 18:56:32 -080010307 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010308 + " replacePending=" + replacePending);
10309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10311 if (!ordered && NR > 0) {
10312 // If we are not serializing this broadcast, then send the
10313 // registered receivers separately so they don't wait for the
10314 // components to be launched.
10315 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10316 callerPackage, callingPid, callingUid, requiredPermission,
10317 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010318 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010319 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 TAG, "Enqueueing parallel broadcast " + r
10321 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010322 boolean replaced = false;
10323 if (replacePending) {
10324 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10325 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010326 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010327 "***** DROPPING PARALLEL: " + intent);
10328 mParallelBroadcasts.set(i, r);
10329 replaced = true;
10330 break;
10331 }
10332 }
10333 }
10334 if (!replaced) {
10335 mParallelBroadcasts.add(r);
10336 scheduleBroadcastsLocked();
10337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 registeredReceivers = null;
10339 NR = 0;
10340 }
10341
10342 // Merge into one list.
10343 int ir = 0;
10344 if (receivers != null) {
10345 // A special case for PACKAGE_ADDED: do not allow the package
10346 // being added to see this broadcast. This prevents them from
10347 // using this as a back door to get run as soon as they are
10348 // installed. Maybe in the future we want to have a special install
10349 // broadcast or such for apps, but we'd like to deliberately make
10350 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010351 String skipPackages[] = null;
10352 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10353 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10354 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10355 Uri data = intent.getData();
10356 if (data != null) {
10357 String pkgName = data.getSchemeSpecificPart();
10358 if (pkgName != null) {
10359 skipPackages = new String[] { pkgName };
10360 }
10361 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010362 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010363 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010364 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010365 if (skipPackages != null && (skipPackages.length > 0)) {
10366 for (String skipPackage : skipPackages) {
10367 if (skipPackage != null) {
10368 int NT = receivers.size();
10369 for (int it=0; it<NT; it++) {
10370 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10371 if (curt.activityInfo.packageName.equals(skipPackage)) {
10372 receivers.remove(it);
10373 it--;
10374 NT--;
10375 }
10376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 }
10378 }
10379 }
10380
10381 int NT = receivers != null ? receivers.size() : 0;
10382 int it = 0;
10383 ResolveInfo curt = null;
10384 BroadcastFilter curr = null;
10385 while (it < NT && ir < NR) {
10386 if (curt == null) {
10387 curt = (ResolveInfo)receivers.get(it);
10388 }
10389 if (curr == null) {
10390 curr = registeredReceivers.get(ir);
10391 }
10392 if (curr.getPriority() >= curt.priority) {
10393 // Insert this broadcast record into the final list.
10394 receivers.add(it, curr);
10395 ir++;
10396 curr = null;
10397 it++;
10398 NT++;
10399 } else {
10400 // Skip to the next ResolveInfo in the final list.
10401 it++;
10402 curt = null;
10403 }
10404 }
10405 }
10406 while (ir < NR) {
10407 if (receivers == null) {
10408 receivers = new ArrayList();
10409 }
10410 receivers.add(registeredReceivers.get(ir));
10411 ir++;
10412 }
10413
10414 if ((receivers != null && receivers.size() > 0)
10415 || resultTo != null) {
10416 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10417 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010418 receivers, resultTo, resultCode, resultData, map, ordered,
10419 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010420 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010421 TAG, "Enqueueing ordered broadcast " + r
10422 + ": prev had " + mOrderedBroadcasts.size());
10423 if (DEBUG_BROADCAST) {
10424 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010425 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010427 boolean replaced = false;
10428 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010429 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010430 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010431 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010432 "***** DROPPING ORDERED: " + intent);
10433 mOrderedBroadcasts.set(i, r);
10434 replaced = true;
10435 break;
10436 }
10437 }
10438 }
10439 if (!replaced) {
10440 mOrderedBroadcasts.add(r);
10441 scheduleBroadcastsLocked();
10442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 }
10444
10445 return BROADCAST_SUCCESS;
10446 }
10447
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010448 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 // Refuse possible leaked file descriptors
10450 if (intent != null && intent.hasFileDescriptors() == true) {
10451 throw new IllegalArgumentException("File descriptors passed in Intent");
10452 }
10453
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010454 int flags = intent.getFlags();
10455
10456 if (!mProcessesReady) {
10457 // if the caller really truly claims to know what they're doing, go
10458 // ahead and allow the broadcast without launching any receivers
10459 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10460 intent = new Intent(intent);
10461 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10462 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10463 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10464 + " before boot completion");
10465 throw new IllegalStateException("Cannot broadcast before boot completed");
10466 }
10467 }
10468
10469 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10470 throw new IllegalArgumentException(
10471 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10472 }
10473
10474 return intent;
10475 }
10476
10477 public final int broadcastIntent(IApplicationThread caller,
10478 Intent intent, String resolvedType, IIntentReceiver resultTo,
10479 int resultCode, String resultData, Bundle map,
10480 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010481 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010482 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10485 final int callingPid = Binder.getCallingPid();
10486 final int callingUid = Binder.getCallingUid();
10487 final long origId = Binder.clearCallingIdentity();
10488 int res = broadcastIntentLocked(callerApp,
10489 callerApp != null ? callerApp.info.packageName : null,
10490 intent, resolvedType, resultTo,
10491 resultCode, resultData, map, requiredPermission, serialized,
10492 sticky, callingPid, callingUid);
10493 Binder.restoreCallingIdentity(origId);
10494 return res;
10495 }
10496 }
10497
10498 int broadcastIntentInPackage(String packageName, int uid,
10499 Intent intent, String resolvedType, IIntentReceiver resultTo,
10500 int resultCode, String resultData, Bundle map,
10501 String requiredPermission, boolean serialized, boolean sticky) {
10502 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010503 intent = verifyBroadcastLocked(intent);
10504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 final long origId = Binder.clearCallingIdentity();
10506 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10507 resultTo, resultCode, resultData, map, requiredPermission,
10508 serialized, sticky, -1, uid);
10509 Binder.restoreCallingIdentity(origId);
10510 return res;
10511 }
10512 }
10513
10514 public final void unbroadcastIntent(IApplicationThread caller,
10515 Intent intent) {
10516 // Refuse possible leaked file descriptors
10517 if (intent != null && intent.hasFileDescriptors() == true) {
10518 throw new IllegalArgumentException("File descriptors passed in Intent");
10519 }
10520
10521 synchronized(this) {
10522 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10523 != PackageManager.PERMISSION_GRANTED) {
10524 String msg = "Permission Denial: unbroadcastIntent() from pid="
10525 + Binder.getCallingPid()
10526 + ", uid=" + Binder.getCallingUid()
10527 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010528 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529 throw new SecurityException(msg);
10530 }
10531 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10532 if (list != null) {
10533 int N = list.size();
10534 int i;
10535 for (i=0; i<N; i++) {
10536 if (intent.filterEquals(list.get(i))) {
10537 list.remove(i);
10538 break;
10539 }
10540 }
10541 }
10542 }
10543 }
10544
10545 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10546 String resultData, Bundle resultExtras, boolean resultAbort,
10547 boolean explicit) {
10548 if (mOrderedBroadcasts.size() == 0) {
10549 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010550 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 }
10552 return false;
10553 }
10554 BroadcastRecord r = mOrderedBroadcasts.get(0);
10555 if (r.receiver == null) {
10556 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010557 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010558 }
10559 return false;
10560 }
10561 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010562 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563 return false;
10564 }
10565 int state = r.state;
10566 r.state = r.IDLE;
10567 if (state == r.IDLE) {
10568 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010569 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 }
10571 }
10572 r.receiver = null;
10573 r.intent.setComponent(null);
10574 if (r.curApp != null) {
10575 r.curApp.curReceiver = null;
10576 }
10577 if (r.curFilter != null) {
10578 r.curFilter.receiverList.curBroadcast = null;
10579 }
10580 r.curFilter = null;
10581 r.curApp = null;
10582 r.curComponent = null;
10583 r.curReceiver = null;
10584 mPendingBroadcast = null;
10585
10586 r.resultCode = resultCode;
10587 r.resultData = resultData;
10588 r.resultExtras = resultExtras;
10589 r.resultAbort = resultAbort;
10590
10591 // We will process the next receiver right now if this is finishing
10592 // an app receiver (which is always asynchronous) or after we have
10593 // come back from calling a receiver.
10594 return state == BroadcastRecord.APP_RECEIVE
10595 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10596 }
10597
10598 public void finishReceiver(IBinder who, int resultCode, String resultData,
10599 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010600 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601
10602 // Refuse possible leaked file descriptors
10603 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10604 throw new IllegalArgumentException("File descriptors passed in Bundle");
10605 }
10606
10607 boolean doNext;
10608
10609 final long origId = Binder.clearCallingIdentity();
10610
10611 synchronized(this) {
10612 doNext = finishReceiverLocked(
10613 who, resultCode, resultData, resultExtras, resultAbort, true);
10614 }
10615
10616 if (doNext) {
10617 processNextBroadcast(false);
10618 }
10619 trimApplications();
10620
10621 Binder.restoreCallingIdentity(origId);
10622 }
10623
Jeff Brown4d94a762010-09-23 11:33:28 -070010624 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625 if (r.nextReceiver > 0) {
10626 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10627 if (curReceiver instanceof BroadcastFilter) {
10628 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010629 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010630 System.identityHashCode(r),
10631 r.intent.getAction(),
10632 r.nextReceiver - 1,
10633 System.identityHashCode(bf));
10634 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010635 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636 System.identityHashCode(r),
10637 r.intent.getAction(),
10638 r.nextReceiver - 1,
10639 ((ResolveInfo)curReceiver).toString());
10640 }
10641 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010642 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010643 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010644 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 System.identityHashCode(r),
10646 r.intent.getAction(),
10647 r.nextReceiver,
10648 "NONE");
10649 }
10650 }
10651
Jeff Brown4d94a762010-09-23 11:33:28 -070010652 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10653 if (! mPendingBroadcastTimeoutMessage) {
10654 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10655 mHandler.sendMessageAtTime(msg, timeoutTime);
10656 mPendingBroadcastTimeoutMessage = true;
10657 }
10658 }
10659
10660 private final void cancelBroadcastTimeoutLocked() {
10661 if (mPendingBroadcastTimeoutMessage) {
10662 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10663 mPendingBroadcastTimeoutMessage = false;
10664 }
10665 }
10666
10667 private final void broadcastTimeoutLocked(boolean fromMsg) {
10668 if (fromMsg) {
10669 mPendingBroadcastTimeoutMessage = false;
10670 }
10671
10672 if (mOrderedBroadcasts.size() == 0) {
10673 return;
10674 }
10675
10676 long now = SystemClock.uptimeMillis();
10677 BroadcastRecord r = mOrderedBroadcasts.get(0);
10678 if (fromMsg) {
10679 if (mDidDexOpt) {
10680 // Delay timeouts until dexopt finishes.
10681 mDidDexOpt = false;
10682 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10683 setBroadcastTimeoutLocked(timeoutTime);
10684 return;
10685 }
10686 if (! mProcessesReady) {
10687 // Only process broadcast timeouts if the system is ready. That way
10688 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10689 // to do heavy lifting for system up.
10690 return;
10691 }
10692
10693 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10694 if (timeoutTime > now) {
10695 // We can observe premature timeouts because we do not cancel and reset the
10696 // broadcast timeout message after each receiver finishes. Instead, we set up
10697 // an initial timeout then kick it down the road a little further as needed
10698 // when it expires.
10699 if (DEBUG_BROADCAST) Slog.v(TAG,
10700 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10701 + timeoutTime);
10702 setBroadcastTimeoutLocked(timeoutTime);
10703 return;
10704 }
10705 }
10706
10707 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10708 + ", started " + (now - r.receiverTime) + "ms ago");
10709 r.receiverTime = now;
10710 r.anrCount++;
10711
10712 // Current receiver has passed its expiration date.
10713 if (r.nextReceiver <= 0) {
10714 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10715 return;
10716 }
10717
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010718 ProcessRecord app = null;
10719 String anrMessage = null;
10720
Jeff Brown4d94a762010-09-23 11:33:28 -070010721 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10722 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10723 logBroadcastReceiverDiscardLocked(r);
10724 if (curReceiver instanceof BroadcastFilter) {
10725 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10726 if (bf.receiverList.pid != 0
10727 && bf.receiverList.pid != MY_PID) {
10728 synchronized (this.mPidsSelfLocked) {
10729 app = this.mPidsSelfLocked.get(
10730 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010733 } else {
10734 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010736
Jeff Brown4d94a762010-09-23 11:33:28 -070010737 if (app != null) {
10738 anrMessage = "Broadcast of " + r.intent.toString();
10739 }
10740
10741 if (mPendingBroadcast == r) {
10742 mPendingBroadcast = null;
10743 }
10744
10745 // Move on to the next receiver.
10746 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10747 r.resultExtras, r.resultAbort, true);
10748 scheduleBroadcastsLocked();
10749
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010750 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010751 // Post the ANR to the handler since we do not want to process ANRs while
10752 // potentially holding our lock.
10753 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 }
10756
10757 private final void processCurBroadcastLocked(BroadcastRecord r,
10758 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010759 if (DEBUG_BROADCAST) Slog.v(TAG,
10760 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 if (app.thread == null) {
10762 throw new RemoteException();
10763 }
10764 r.receiver = app.thread.asBinder();
10765 r.curApp = app;
10766 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010767 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768
10769 // Tell the application to launch this receiver.
10770 r.intent.setComponent(r.curComponent);
10771
10772 boolean started = false;
10773 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010774 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010775 "Delivering to component " + r.curComponent
10776 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010777 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10779 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010780 if (DEBUG_BROADCAST) Slog.v(TAG,
10781 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 started = true;
10783 } finally {
10784 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010785 if (DEBUG_BROADCAST) Slog.v(TAG,
10786 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 r.receiver = null;
10788 r.curApp = null;
10789 app.curReceiver = null;
10790 }
10791 }
10792
10793 }
10794
Jeff Brown4d94a762010-09-23 11:33:28 -070010795 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010796 Intent intent, int resultCode, String data, Bundle extras,
10797 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010798 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 if (app != null && app.thread != null) {
10800 // If we have an app thread, do the call through that so it is
10801 // correctly ordered with other one-way calls.
10802 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010803 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010804 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010805 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 }
10807 }
10808
Jeff Brown4d94a762010-09-23 11:33:28 -070010809 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 BroadcastFilter filter, boolean ordered) {
10811 boolean skip = false;
10812 if (filter.requiredPermission != null) {
10813 int perm = checkComponentPermission(filter.requiredPermission,
10814 r.callingPid, r.callingUid, -1);
10815 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010816 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 + r.intent.toString()
10818 + " from " + r.callerPackage + " (pid="
10819 + r.callingPid + ", uid=" + r.callingUid + ")"
10820 + " requires " + filter.requiredPermission
10821 + " due to registered receiver " + filter);
10822 skip = true;
10823 }
10824 }
10825 if (r.requiredPermission != null) {
10826 int perm = checkComponentPermission(r.requiredPermission,
10827 filter.receiverList.pid, filter.receiverList.uid, -1);
10828 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010829 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 + r.intent.toString()
10831 + " to " + filter.receiverList.app
10832 + " (pid=" + filter.receiverList.pid
10833 + ", uid=" + filter.receiverList.uid + ")"
10834 + " requires " + r.requiredPermission
10835 + " due to sender " + r.callerPackage
10836 + " (uid " + r.callingUid + ")");
10837 skip = true;
10838 }
10839 }
10840
10841 if (!skip) {
10842 // If this is not being sent as an ordered broadcast, then we
10843 // don't want to touch the fields that keep track of the current
10844 // state of ordered broadcasts.
10845 if (ordered) {
10846 r.receiver = filter.receiverList.receiver.asBinder();
10847 r.curFilter = filter;
10848 filter.receiverList.curBroadcast = r;
10849 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010850 if (filter.receiverList.app != null) {
10851 // Bump hosting application to no longer be in background
10852 // scheduling class. Note that we can't do that if there
10853 // isn't an app... but we can only be in that case for
10854 // things that directly call the IActivityManager API, which
10855 // are already core system stuff so don't matter for this.
10856 r.curApp = filter.receiverList.app;
10857 filter.receiverList.app.curReceiver = r;
10858 updateOomAdjLocked();
10859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 }
10861 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010862 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010863 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010864 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010865 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010866 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010867 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010868 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010869 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010870 if (ordered) {
10871 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10872 }
10873 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010874 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 if (ordered) {
10876 r.receiver = null;
10877 r.curFilter = null;
10878 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010879 if (filter.receiverList.app != null) {
10880 filter.receiverList.app.curReceiver = null;
10881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 }
10883 }
10884 }
10885 }
10886
Dianne Hackborn12527f92009-11-11 17:39:50 -080010887 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10888 if (r.callingUid < 0) {
10889 // This was from a registerReceiver() call; ignore it.
10890 return;
10891 }
10892 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10893 MAX_BROADCAST_HISTORY-1);
10894 r.finishTime = SystemClock.uptimeMillis();
10895 mBroadcastHistory[0] = r;
10896 }
10897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 private final void processNextBroadcast(boolean fromMsg) {
10899 synchronized(this) {
10900 BroadcastRecord r;
10901
Joe Onorato8a9b2202010-02-26 18:56:32 -080010902 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010904 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905
10906 updateCpuStats();
10907
10908 if (fromMsg) {
10909 mBroadcastsScheduled = false;
10910 }
10911
10912 // First, deliver any non-serialized broadcasts right away.
10913 while (mParallelBroadcasts.size() > 0) {
10914 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010915 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010917 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010918 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 for (int i=0; i<N; i++) {
10920 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010921 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010922 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010924 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010926 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010927 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010928 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 }
10930
10931 // Now take care of the next serialized one...
10932
10933 // If we are waiting for a process to come up to handle the next
10934 // broadcast, then do nothing at this point. Just in case, we
10935 // check that the process we're waiting for still exists.
10936 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010937 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010938 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010939 + mPendingBroadcast.curApp);
10940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941
10942 boolean isDead;
10943 synchronized (mPidsSelfLocked) {
10944 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10945 }
10946 if (!isDead) {
10947 // It's still alive, so keep waiting
10948 return;
10949 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010950 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010952 mPendingBroadcast.state = BroadcastRecord.IDLE;
10953 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 mPendingBroadcast = null;
10955 }
10956 }
10957
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010958 boolean looped = false;
10959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 do {
10961 if (mOrderedBroadcasts.size() == 0) {
10962 // No more broadcasts pending, so all done!
10963 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010964 if (looped) {
10965 // If we had finished the last ordered broadcast, then
10966 // make sure all processes have correct oom and sched
10967 // adjustments.
10968 updateOomAdjLocked();
10969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 return;
10971 }
10972 r = mOrderedBroadcasts.get(0);
10973 boolean forceReceive = false;
10974
10975 // Ensure that even if something goes awry with the timeout
10976 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010977 // and continue to make progress.
10978 //
10979 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070010980 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010981 // one time heavy lifting after system upgrades and can take
10982 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010984 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010985 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 if ((numReceivers > 0) &&
10987 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010988 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 + " now=" + now
10990 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010991 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 + " intent=" + r.intent
10993 + " numReceivers=" + numReceivers
10994 + " nextReceiver=" + r.nextReceiver
10995 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070010996 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 forceReceive = true;
10998 r.state = BroadcastRecord.IDLE;
10999 }
11000 }
11001
11002 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011003 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 "processNextBroadcast() called when not idle (state="
11005 + r.state + ")");
11006 return;
11007 }
11008
11009 if (r.receivers == null || r.nextReceiver >= numReceivers
11010 || r.resultAbort || forceReceive) {
11011 // No more receivers for this broadcast! Send the final
11012 // result if requested...
11013 if (r.resultTo != null) {
11014 try {
11015 if (DEBUG_BROADCAST) {
11016 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011017 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 + " seq=" + seq + " app=" + r.callerApp);
11019 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011020 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011022 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011024 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 }
11026 }
11027
Joe Onorato8a9b2202010-02-26 18:56:32 -080011028 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011029 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030
Joe Onorato8a9b2202010-02-26 18:56:32 -080011031 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011032 + r);
11033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011034 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011035 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 mOrderedBroadcasts.remove(0);
11037 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011038 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011039 continue;
11040 }
11041 } while (r == null);
11042
11043 // Get the next receiver...
11044 int recIdx = r.nextReceiver++;
11045
11046 // Keep track of when this receiver started, and make sure there
11047 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011048 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011050 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051
Joe Onorato8a9b2202010-02-26 18:56:32 -080011052 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011053 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011054 }
11055 if (! mPendingBroadcastTimeoutMessage) {
11056 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011057 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011058 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11059 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 }
11061
11062 Object nextReceiver = r.receivers.get(recIdx);
11063 if (nextReceiver instanceof BroadcastFilter) {
11064 // Simple case: this is a registered receiver who gets
11065 // a direct call.
11066 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011067 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011068 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011070 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 if (r.receiver == null || !r.ordered) {
11072 // The receiver has already finished, so schedule to
11073 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011074 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11075 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 r.state = BroadcastRecord.IDLE;
11077 scheduleBroadcastsLocked();
11078 }
11079 return;
11080 }
11081
11082 // Hard case: need to instantiate the receiver, possibly
11083 // starting its application process to host it.
11084
11085 ResolveInfo info =
11086 (ResolveInfo)nextReceiver;
11087
11088 boolean skip = false;
11089 int perm = checkComponentPermission(info.activityInfo.permission,
11090 r.callingPid, r.callingUid,
11091 info.activityInfo.exported
11092 ? -1 : info.activityInfo.applicationInfo.uid);
11093 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011094 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 + r.intent.toString()
11096 + " from " + r.callerPackage + " (pid=" + r.callingPid
11097 + ", uid=" + r.callingUid + ")"
11098 + " requires " + info.activityInfo.permission
11099 + " due to receiver " + info.activityInfo.packageName
11100 + "/" + info.activityInfo.name);
11101 skip = true;
11102 }
11103 if (r.callingUid != Process.SYSTEM_UID &&
11104 r.requiredPermission != null) {
11105 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011106 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 checkPermission(r.requiredPermission,
11108 info.activityInfo.applicationInfo.packageName);
11109 } catch (RemoteException e) {
11110 perm = PackageManager.PERMISSION_DENIED;
11111 }
11112 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011113 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 + r.intent + " to "
11115 + info.activityInfo.applicationInfo.packageName
11116 + " requires " + r.requiredPermission
11117 + " due to sender " + r.callerPackage
11118 + " (uid " + r.callingUid + ")");
11119 skip = true;
11120 }
11121 }
11122 if (r.curApp != null && r.curApp.crashing) {
11123 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011124 if (DEBUG_BROADCAST) Slog.v(TAG,
11125 "Skipping deliver ordered " + r + " to " + r.curApp
11126 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 skip = true;
11128 }
11129
11130 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011131 if (DEBUG_BROADCAST) Slog.v(TAG,
11132 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133 r.receiver = null;
11134 r.curFilter = null;
11135 r.state = BroadcastRecord.IDLE;
11136 scheduleBroadcastsLocked();
11137 return;
11138 }
11139
11140 r.state = BroadcastRecord.APP_RECEIVE;
11141 String targetProcess = info.activityInfo.processName;
11142 r.curComponent = new ComponentName(
11143 info.activityInfo.applicationInfo.packageName,
11144 info.activityInfo.name);
11145 r.curReceiver = info.activityInfo;
11146
11147 // Is this receiver's application already running?
11148 ProcessRecord app = getProcessRecordLocked(targetProcess,
11149 info.activityInfo.applicationInfo.uid);
11150 if (app != null && app.thread != null) {
11151 try {
11152 processCurBroadcastLocked(r, app);
11153 return;
11154 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011155 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 + r.curComponent, e);
11157 }
11158
11159 // If a dead object exception was thrown -- fall through to
11160 // restart the application.
11161 }
11162
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011163 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011164 if (DEBUG_BROADCAST) Slog.v(TAG,
11165 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 if ((r.curApp=startProcessLocked(targetProcess,
11167 info.activityInfo.applicationInfo, true,
11168 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011169 "broadcast", r.curComponent,
11170 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11171 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 // Ah, this recipient is unavailable. Finish it if necessary,
11173 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011174 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 + info.activityInfo.applicationInfo.packageName + "/"
11176 + info.activityInfo.applicationInfo.uid + " for broadcast "
11177 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011178 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11180 r.resultExtras, r.resultAbort, true);
11181 scheduleBroadcastsLocked();
11182 r.state = BroadcastRecord.IDLE;
11183 return;
11184 }
11185
11186 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011187 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 }
11189 }
11190
11191 // =========================================================
11192 // INSTRUMENTATION
11193 // =========================================================
11194
11195 public boolean startInstrumentation(ComponentName className,
11196 String profileFile, int flags, Bundle arguments,
11197 IInstrumentationWatcher watcher) {
11198 // Refuse possible leaked file descriptors
11199 if (arguments != null && arguments.hasFileDescriptors()) {
11200 throw new IllegalArgumentException("File descriptors passed in Bundle");
11201 }
11202
11203 synchronized(this) {
11204 InstrumentationInfo ii = null;
11205 ApplicationInfo ai = null;
11206 try {
11207 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011208 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011210 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 } catch (PackageManager.NameNotFoundException e) {
11212 }
11213 if (ii == null) {
11214 reportStartInstrumentationFailure(watcher, className,
11215 "Unable to find instrumentation info for: " + className);
11216 return false;
11217 }
11218 if (ai == null) {
11219 reportStartInstrumentationFailure(watcher, className,
11220 "Unable to find instrumentation target package: " + ii.targetPackage);
11221 return false;
11222 }
11223
11224 int match = mContext.getPackageManager().checkSignatures(
11225 ii.targetPackage, ii.packageName);
11226 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11227 String msg = "Permission Denial: starting instrumentation "
11228 + className + " from pid="
11229 + Binder.getCallingPid()
11230 + ", uid=" + Binder.getCallingPid()
11231 + " not allowed because package " + ii.packageName
11232 + " does not have a signature matching the target "
11233 + ii.targetPackage;
11234 reportStartInstrumentationFailure(watcher, className, msg);
11235 throw new SecurityException(msg);
11236 }
11237
11238 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011239 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 ProcessRecord app = addAppLocked(ai);
11241 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011242 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 app.instrumentationProfileFile = profileFile;
11244 app.instrumentationArguments = arguments;
11245 app.instrumentationWatcher = watcher;
11246 app.instrumentationResultClass = className;
11247 Binder.restoreCallingIdentity(origId);
11248 }
11249
11250 return true;
11251 }
11252
11253 /**
11254 * Report errors that occur while attempting to start Instrumentation. Always writes the
11255 * error to the logs, but if somebody is watching, send the report there too. This enables
11256 * the "am" command to report errors with more information.
11257 *
11258 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11259 * @param cn The component name of the instrumentation.
11260 * @param report The error report.
11261 */
11262 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11263 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011264 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011265 try {
11266 if (watcher != null) {
11267 Bundle results = new Bundle();
11268 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11269 results.putString("Error", report);
11270 watcher.instrumentationStatus(cn, -1, results);
11271 }
11272 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011273 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 }
11275 }
11276
11277 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11278 if (app.instrumentationWatcher != null) {
11279 try {
11280 // NOTE: IInstrumentationWatcher *must* be oneway here
11281 app.instrumentationWatcher.instrumentationFinished(
11282 app.instrumentationClass,
11283 resultCode,
11284 results);
11285 } catch (RemoteException e) {
11286 }
11287 }
11288 app.instrumentationWatcher = null;
11289 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011290 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 app.instrumentationProfileFile = null;
11292 app.instrumentationArguments = null;
11293
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011294 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 }
11296
11297 public void finishInstrumentation(IApplicationThread target,
11298 int resultCode, Bundle results) {
11299 // Refuse possible leaked file descriptors
11300 if (results != null && results.hasFileDescriptors()) {
11301 throw new IllegalArgumentException("File descriptors passed in Intent");
11302 }
11303
11304 synchronized(this) {
11305 ProcessRecord app = getRecordForAppLocked(target);
11306 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011307 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308 return;
11309 }
11310 final long origId = Binder.clearCallingIdentity();
11311 finishInstrumentationLocked(app, resultCode, results);
11312 Binder.restoreCallingIdentity(origId);
11313 }
11314 }
11315
11316 // =========================================================
11317 // CONFIGURATION
11318 // =========================================================
11319
11320 public ConfigurationInfo getDeviceConfigurationInfo() {
11321 ConfigurationInfo config = new ConfigurationInfo();
11322 synchronized (this) {
11323 config.reqTouchScreen = mConfiguration.touchscreen;
11324 config.reqKeyboardType = mConfiguration.keyboard;
11325 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011326 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11327 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11329 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011330 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11331 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11333 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011334 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011335 }
11336 return config;
11337 }
11338
11339 public Configuration getConfiguration() {
11340 Configuration ci;
11341 synchronized(this) {
11342 ci = new Configuration(mConfiguration);
11343 }
11344 return ci;
11345 }
11346
11347 public void updateConfiguration(Configuration values) {
11348 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11349 "updateConfiguration()");
11350
11351 synchronized(this) {
11352 if (values == null && mWindowManager != null) {
11353 // sentinel: fetch the current configuration from the window manager
11354 values = mWindowManager.computeNewConfiguration();
11355 }
11356
11357 final long origId = Binder.clearCallingIdentity();
11358 updateConfigurationLocked(values, null);
11359 Binder.restoreCallingIdentity(origId);
11360 }
11361 }
11362
11363 /**
11364 * Do either or both things: (1) change the current configuration, and (2)
11365 * make sure the given activity is running with the (now) current
11366 * configuration. Returns true if the activity has been left running, or
11367 * false if <var>starting</var> is being destroyed to match the new
11368 * configuration.
11369 */
11370 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011371 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 int changes = 0;
11373
11374 boolean kept = true;
11375
11376 if (values != null) {
11377 Configuration newConfig = new Configuration(mConfiguration);
11378 changes = newConfig.updateFrom(values);
11379 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011380 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011381 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 }
11383
Doug Zongker2bec3d42009-12-04 12:52:44 -080011384 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385
11386 if (values.locale != null) {
11387 saveLocaleLocked(values.locale,
11388 !values.locale.equals(mConfiguration.locale),
11389 values.userSetLocale);
11390 }
11391
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011392 mConfigurationSeq++;
11393 if (mConfigurationSeq <= 0) {
11394 mConfigurationSeq = 1;
11395 }
11396 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011399
11400 AttributeCache ac = AttributeCache.instance();
11401 if (ac != null) {
11402 ac.updateConfiguration(mConfiguration);
11403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011405 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11406 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11407 msg.obj = new Configuration(mConfiguration);
11408 mHandler.sendMessage(msg);
11409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011411 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11412 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011413 try {
11414 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011415 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011416 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011417 app.thread.scheduleConfigurationChanged(mConfiguration);
11418 }
11419 } catch (Exception e) {
11420 }
11421 }
11422 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011423 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11424 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011425 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11426 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011427 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11428 broadcastIntentLocked(null, null,
11429 new Intent(Intent.ACTION_LOCALE_CHANGED),
11430 null, null, 0, null, null,
11431 null, false, false, MY_PID, Process.SYSTEM_UID);
11432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 }
11434 }
11435
11436 if (changes != 0 && starting == null) {
11437 // If the configuration changed, and the caller is not already
11438 // in the process of starting an activity, then find the top
11439 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011440 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011441 }
11442
11443 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011444 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 if (kept) {
11446 // If this didn't result in the starting activity being
11447 // destroyed, then we need to make sure at this point that all
11448 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011449 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011450 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011451 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 }
11453 }
11454
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011455 if (values != null && mWindowManager != null) {
11456 mWindowManager.setNewConfiguration(mConfiguration);
11457 }
11458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 return kept;
11460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011461
11462 /**
11463 * Save the locale. You must be inside a synchronized (this) block.
11464 */
11465 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11466 if(isDiff) {
11467 SystemProperties.set("user.language", l.getLanguage());
11468 SystemProperties.set("user.region", l.getCountry());
11469 }
11470
11471 if(isPersist) {
11472 SystemProperties.set("persist.sys.language", l.getLanguage());
11473 SystemProperties.set("persist.sys.country", l.getCountry());
11474 SystemProperties.set("persist.sys.localevar", l.getVariant());
11475 }
11476 }
11477
11478 // =========================================================
11479 // LIFETIME MANAGEMENT
11480 // =========================================================
11481
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011482 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11483 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011484 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011485 // This adjustment has already been computed. If we are calling
11486 // from the top, we may have already computed our adjustment with
11487 // an earlier hidden adjustment that isn't really for us... if
11488 // so, use the new hidden adjustment.
11489 if (!recursed && app.hidden) {
11490 app.curAdj = hiddenAdj;
11491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 return app.curAdj;
11493 }
11494
11495 if (app.thread == null) {
11496 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011497 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 return (app.curAdj=EMPTY_APP_ADJ);
11499 }
11500
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011501 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11502 // The max adjustment doesn't allow this app to be anything
11503 // below foreground, so it is not worth doing work for it.
11504 app.adjType = "fixed";
11505 app.adjSeq = mAdjSeq;
11506 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011507 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011508 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11509 return (app.curAdj=app.maxAdj);
11510 }
11511
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011512 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011513 app.adjSource = null;
11514 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011515 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011516 app.empty = false;
11517 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518
The Android Open Source Project4df24232009-03-05 14:34:35 -080011519 // Determine the importance of the process, starting with most
11520 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011521 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011522 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011523 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011524 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 // The last app on the list is the foreground app.
11526 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011527 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011528 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011529 } else if (app.instrumentationClass != null) {
11530 // Don't want to kill running instrumentation.
11531 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011532 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011533 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 } else if (app.curReceiver != null ||
11535 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11536 // An app that is currently receiving a broadcast also
11537 // counts as being in the foreground.
11538 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011539 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011540 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 } else if (app.executingServices.size() > 0) {
11542 // An app that is currently executing a service callback also
11543 // counts as being in the foreground.
11544 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011545 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011546 app.adjType = "exec-service";
11547 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011548 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011549 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011550 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011551 app.adjType = "foreground-service";
11552 } else if (app.forcingToForeground != null) {
11553 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011554 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011555 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011556 app.adjType = "force-foreground";
11557 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011558 } else if (app == mHeavyWeightProcess) {
11559 // We don't want to kill the current heavy-weight process.
11560 adj = HEAVY_WEIGHT_APP_ADJ;
11561 schedGroup = Process.THREAD_GROUP_DEFAULT;
11562 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011563 } else if (app == mHomeProcess) {
11564 // This process is hosting what we currently consider to be the
11565 // home app, so we don't want to let it go into the background.
11566 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011567 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011568 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 } else if ((N=app.activities.size()) != 0) {
11570 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011571 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011573 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011574 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011575 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011577 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011579 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 adj = VISIBLE_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 = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 break;
11584 }
11585 }
11586 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011587 // A very not-needed process. If this is lower in the lru list,
11588 // we will push it in to the empty bucket.
11589 app.hidden = true;
11590 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011591 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011592 adj = hiddenAdj;
11593 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 }
11595
Joe Onorato8a9b2202010-02-26 18:56:32 -080011596 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011597
The Android Open Source Project4df24232009-03-05 14:34:35 -080011598 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 // there are applications dependent on our services or providers, but
11600 // this gives us a baseline and makes sure we don't get into an
11601 // infinite recursion.
11602 app.adjSeq = mAdjSeq;
11603 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604
Christopher Tate6fa95972009-06-05 18:43:55 -070011605 if (mBackupTarget != null && app == mBackupTarget.app) {
11606 // If possible we want to avoid killing apps while they're being backed up
11607 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011608 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011609 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011610 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011611 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011612 }
11613 }
11614
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011615 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11616 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 final long now = SystemClock.uptimeMillis();
11618 // This process is more important if the top activity is
11619 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011620 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011622 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011623 if (s.startRequested) {
11624 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11625 // This service has seen some activity within
11626 // recent memory, so we will keep its process ahead
11627 // of the background processes.
11628 if (adj > SECONDARY_SERVER_ADJ) {
11629 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011630 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011631 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 }
11633 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011634 // If we have let the service slide into the background
11635 // state, still have some text describing what it is doing
11636 // even though the service no longer has an impact.
11637 if (adj > SECONDARY_SERVER_ADJ) {
11638 app.adjType = "started-bg-services";
11639 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011640 // Don't kill this process because it is doing work; it
11641 // has said it is doing work.
11642 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011644 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11645 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011646 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647 = s.connections.values().iterator();
11648 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011649 ArrayList<ConnectionRecord> clist = kt.next();
11650 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11651 // XXX should compute this based on the max of
11652 // all connected clients.
11653 ConnectionRecord cr = clist.get(i);
11654 if (cr.binding.client == app) {
11655 // Binding to ourself is not interesting.
11656 continue;
11657 }
11658 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11659 ProcessRecord client = cr.binding.client;
11660 int myHiddenAdj = hiddenAdj;
11661 if (myHiddenAdj > client.hiddenAdj) {
11662 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11663 myHiddenAdj = client.hiddenAdj;
11664 } else {
11665 myHiddenAdj = VISIBLE_APP_ADJ;
11666 }
11667 }
11668 int clientAdj = computeOomAdjLocked(
11669 client, myHiddenAdj, TOP_APP, true);
11670 if (adj > clientAdj) {
11671 adj = clientAdj >= VISIBLE_APP_ADJ
11672 ? clientAdj : VISIBLE_APP_ADJ;
11673 if (!client.hidden) {
11674 app.hidden = false;
11675 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011676 if (client.keeping) {
11677 app.keeping = true;
11678 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011679 app.adjType = "service";
11680 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11681 .REASON_SERVICE_IN_USE;
11682 app.adjSource = cr.binding.client;
11683 app.adjTarget = s.name;
11684 }
11685 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11686 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11687 schedGroup = Process.THREAD_GROUP_DEFAULT;
11688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 }
11690 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011691 ActivityRecord a = cr.activity;
11692 //if (a != null) {
11693 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11694 //}
11695 if (a != null && adj > FOREGROUND_APP_ADJ &&
11696 (a.state == ActivityState.RESUMED
11697 || a.state == ActivityState.PAUSING)) {
11698 adj = FOREGROUND_APP_ADJ;
11699 schedGroup = Process.THREAD_GROUP_DEFAULT;
11700 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011701 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011702 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11703 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011704 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011705 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 }
11708 }
11709 }
11710 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011711
Dianne Hackborn287952c2010-09-22 22:34:31 -070011712 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011713 // would like to avoid killing it unless it would prevent the current
11714 // application from running. By default we put the process in
11715 // with the rest of the background processes; as we scan through
11716 // its services we may bump it up from there.
11717 if (adj > hiddenAdj) {
11718 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011719 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011720 app.adjType = "bg-services";
11721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 }
11723
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011724 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11725 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011726 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011727 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11728 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011729 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 if (cpr.clients.size() != 0) {
11731 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11732 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11733 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011734 if (client == app) {
11735 // Being our own client is not interesting.
11736 continue;
11737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 int myHiddenAdj = hiddenAdj;
11739 if (myHiddenAdj > client.hiddenAdj) {
11740 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11741 myHiddenAdj = client.hiddenAdj;
11742 } else {
11743 myHiddenAdj = FOREGROUND_APP_ADJ;
11744 }
11745 }
11746 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011747 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 if (adj > clientAdj) {
11749 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011750 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011751 if (!client.hidden) {
11752 app.hidden = false;
11753 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011754 if (client.keeping) {
11755 app.keeping = true;
11756 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011757 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011758 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11759 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011760 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011761 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011762 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011763 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11764 schedGroup = Process.THREAD_GROUP_DEFAULT;
11765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766 }
11767 }
11768 // If the provider has external (non-framework) process
11769 // dependencies, ensure that its adjustment is at least
11770 // FOREGROUND_APP_ADJ.
11771 if (cpr.externals != 0) {
11772 if (adj > FOREGROUND_APP_ADJ) {
11773 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011774 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011775 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011776 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011777 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011778 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 }
11780 }
11781 }
11782 }
11783
11784 app.curRawAdj = adj;
11785
Joe Onorato8a9b2202010-02-26 18:56:32 -080011786 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011787 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11788 if (adj > app.maxAdj) {
11789 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011790 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011791 schedGroup = Process.THREAD_GROUP_DEFAULT;
11792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011794 if (adj < HIDDEN_APP_MIN_ADJ) {
11795 app.keeping = true;
11796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797
11798 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011799 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 return adj;
11802 }
11803
11804 /**
11805 * Ask a given process to GC right now.
11806 */
11807 final void performAppGcLocked(ProcessRecord app) {
11808 try {
11809 app.lastRequestedGc = SystemClock.uptimeMillis();
11810 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011811 if (app.reportLowMemory) {
11812 app.reportLowMemory = false;
11813 app.thread.scheduleLowMemory();
11814 } else {
11815 app.thread.processInBackground();
11816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011817 }
11818 } catch (Exception e) {
11819 // whatever.
11820 }
11821 }
11822
11823 /**
11824 * Returns true if things are idle enough to perform GCs.
11825 */
Josh Bartel7f208742010-02-25 11:01:44 -060011826 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 return mParallelBroadcasts.size() == 0
11828 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011829 && (mSleeping || (mMainStack.mResumedActivity != null &&
11830 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011831 }
11832
11833 /**
11834 * Perform GCs on all processes that are waiting for it, but only
11835 * if things are idle.
11836 */
11837 final void performAppGcsLocked() {
11838 final int N = mProcessesToGc.size();
11839 if (N <= 0) {
11840 return;
11841 }
Josh Bartel7f208742010-02-25 11:01:44 -060011842 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 while (mProcessesToGc.size() > 0) {
11844 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011845 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011846 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11847 <= SystemClock.uptimeMillis()) {
11848 // To avoid spamming the system, we will GC processes one
11849 // at a time, waiting a few seconds between each.
11850 performAppGcLocked(proc);
11851 scheduleAppGcsLocked();
11852 return;
11853 } else {
11854 // It hasn't been long enough since we last GCed this
11855 // process... put it in the list to wait for its time.
11856 addProcessToGcListLocked(proc);
11857 break;
11858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 }
11860 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011861
11862 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863 }
11864 }
11865
11866 /**
11867 * If all looks good, perform GCs on all processes waiting for them.
11868 */
11869 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011870 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 performAppGcsLocked();
11872 return;
11873 }
11874 // Still not idle, wait some more.
11875 scheduleAppGcsLocked();
11876 }
11877
11878 /**
11879 * Schedule the execution of all pending app GCs.
11880 */
11881 final void scheduleAppGcsLocked() {
11882 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011883
11884 if (mProcessesToGc.size() > 0) {
11885 // Schedule a GC for the time to the next process.
11886 ProcessRecord proc = mProcessesToGc.get(0);
11887 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11888
11889 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11890 long now = SystemClock.uptimeMillis();
11891 if (when < (now+GC_TIMEOUT)) {
11892 when = now + GC_TIMEOUT;
11893 }
11894 mHandler.sendMessageAtTime(msg, when);
11895 }
11896 }
11897
11898 /**
11899 * Add a process to the array of processes waiting to be GCed. Keeps the
11900 * list in sorted order by the last GC time. The process can't already be
11901 * on the list.
11902 */
11903 final void addProcessToGcListLocked(ProcessRecord proc) {
11904 boolean added = false;
11905 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11906 if (mProcessesToGc.get(i).lastRequestedGc <
11907 proc.lastRequestedGc) {
11908 added = true;
11909 mProcessesToGc.add(i+1, proc);
11910 break;
11911 }
11912 }
11913 if (!added) {
11914 mProcessesToGc.add(0, proc);
11915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916 }
11917
11918 /**
11919 * Set up to ask a process to GC itself. This will either do it
11920 * immediately, or put it on the list of processes to gc the next
11921 * time things are idle.
11922 */
11923 final void scheduleAppGcLocked(ProcessRecord app) {
11924 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011925 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 return;
11927 }
11928 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011929 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 scheduleAppGcsLocked();
11931 }
11932 }
11933
Dianne Hackborn287952c2010-09-22 22:34:31 -070011934 final void checkExcessivePowerUsageLocked(boolean doKills) {
11935 updateCpuStatsNow();
11936
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011937 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011938 boolean doWakeKills = doKills;
11939 boolean doCpuKills = doKills;
11940 if (mLastPowerCheckRealtime == 0) {
11941 doWakeKills = false;
11942 }
11943 if (mLastPowerCheckUptime == 0) {
11944 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011945 }
11946 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011947 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011948 }
11949 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011950 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11951 final long curUptime = SystemClock.uptimeMillis();
11952 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11953 mLastPowerCheckRealtime = curRealtime;
11954 mLastPowerCheckUptime = curUptime;
11955 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11956 doWakeKills = false;
11957 }
11958 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11959 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011960 }
11961 int i = mLruProcesses.size();
11962 while (i > 0) {
11963 i--;
11964 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011965 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011966 long wtime;
11967 synchronized (stats) {
11968 wtime = stats.getProcessWakeTime(app.info.uid,
11969 app.pid, curRealtime);
11970 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011971 long wtimeUsed = wtime - app.lastWakeTime;
11972 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11973 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011974 StringBuilder sb = new StringBuilder(128);
11975 sb.append("Wake for ");
11976 app.toShortString(sb);
11977 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011978 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011979 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011980 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011981 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011982 sb.append((wtimeUsed*100)/realtimeSince);
11983 sb.append("%)");
11984 Slog.i(TAG, sb.toString());
11985 sb.setLength(0);
11986 sb.append("CPU for ");
11987 app.toShortString(sb);
11988 sb.append(": over ");
11989 TimeUtils.formatDuration(uptimeSince, sb);
11990 sb.append(" used ");
11991 TimeUtils.formatDuration(cputimeUsed, sb);
11992 sb.append(" (");
11993 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011994 sb.append("%)");
11995 Slog.i(TAG, sb.toString());
11996 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011997 // If a process has held a wake lock for more
11998 // than 50% of the time during this period,
11999 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012000 if (doWakeKills && realtimeSince > 0
12001 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12002 synchronized (stats) {
12003 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12004 realtimeSince, wtimeUsed);
12005 }
12006 Slog.w(TAG, "Excessive wake lock in " + app.processName
12007 + " (pid " + app.pid + "): held " + wtimeUsed
12008 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012009 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12010 app.processName, app.setAdj, "excessive wake lock");
12011 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012012 } else if (doCpuKills && uptimeSince > 0
12013 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12014 synchronized (stats) {
12015 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12016 uptimeSince, cputimeUsed);
12017 }
12018 Slog.w(TAG, "Excessive CPU in " + app.processName
12019 + " (pid " + app.pid + "): used " + cputimeUsed
12020 + " during " + uptimeSince);
12021 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12022 app.processName, app.setAdj, "excessive cpu");
12023 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012024 } else {
12025 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012026 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012027 }
12028 }
12029 }
12030 }
12031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012032 private final boolean updateOomAdjLocked(
12033 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12034 app.hiddenAdj = hiddenAdj;
12035
12036 if (app.thread == null) {
12037 return true;
12038 }
12039
Dianne Hackborn287952c2010-09-22 22:34:31 -070012040 final boolean wasKeeping = app.keeping;
12041
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012042 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012043
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012044 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 if (app.curRawAdj != app.setRawAdj) {
12046 if (app.curRawAdj > FOREGROUND_APP_ADJ
12047 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12048 // If this app is transitioning from foreground to
12049 // non-foreground, have it do a gc.
12050 scheduleAppGcLocked(app);
12051 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12052 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12053 // Likewise do a gc when an app is moving in to the
12054 // background (such as a service stopping).
12055 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012056 }
12057
12058 if (wasKeeping && !app.keeping) {
12059 // This app is no longer something we want to keep. Note
12060 // its current wake lock time to later know to kill it if
12061 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012062 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12063 synchronized (stats) {
12064 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12065 app.pid, SystemClock.elapsedRealtime());
12066 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012067 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 app.setRawAdj = app.curRawAdj;
12071 }
12072 if (adj != app.setAdj) {
12073 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012074 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 TAG, "Set app " + app.processName +
12076 " oom adj to " + adj);
12077 app.setAdj = adj;
12078 } else {
12079 return false;
12080 }
12081 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012082 if (app.setSchedGroup != app.curSchedGroup) {
12083 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012084 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012085 "Setting process group of " + app.processName
12086 + " to " + app.curSchedGroup);
12087 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012088 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012089 try {
12090 Process.setProcessGroup(app.pid, app.curSchedGroup);
12091 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012092 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012093 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012094 e.printStackTrace();
12095 } finally {
12096 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012097 }
12098 }
12099 if (false) {
12100 if (app.thread != null) {
12101 try {
12102 app.thread.setSchedulingGroup(app.curSchedGroup);
12103 } catch (RemoteException e) {
12104 }
12105 }
12106 }
12107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 }
12109
12110 return true;
12111 }
12112
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012113 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012114 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012115 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012116 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012117 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012118 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012119 }
12120 }
12121 return resumedActivity;
12122 }
12123
12124 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012125 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12127 int curAdj = app.curAdj;
12128 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12129 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12130
12131 mAdjSeq++;
12132
12133 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12134 if (res) {
12135 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12136 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12137 if (nowHidden != wasHidden) {
12138 // Changed to/from hidden state, so apps after it in the LRU
12139 // list may also be changed.
12140 updateOomAdjLocked();
12141 }
12142 }
12143 return res;
12144 }
12145
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012146 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012147 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012148 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012149 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12150
12151 if (false) {
12152 RuntimeException e = new RuntimeException();
12153 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012154 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012155 }
12156
12157 mAdjSeq++;
12158
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012159 // Let's determine how many processes we have running vs.
12160 // how many slots we have for background processes; we may want
12161 // to put multiple processes in a slot of there are enough of
12162 // them.
12163 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12164 int factor = (mLruProcesses.size()-4)/numSlots;
12165 if (factor < 1) factor = 1;
12166 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012167 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 // First try updating the OOM adjustment for each of the
12170 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012171 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012172 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12173 while (i > 0) {
12174 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012175 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012176 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012177 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012178 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012179 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012180 step++;
12181 if (step >= factor) {
12182 step = 0;
12183 curHiddenAdj++;
12184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012186 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012187 if (!app.killedBackground) {
12188 numHidden++;
12189 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012190 Slog.i(TAG, "No longer want " + app.processName
12191 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012192 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12193 app.processName, app.setAdj, "too many background");
12194 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012195 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012196 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012197 }
12198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 } else {
12200 didOomAdj = false;
12201 }
12202 }
12203
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012204 // If we return false, we will fall back on killing processes to
12205 // have a fixed limit. Do this if a limit has been requested; else
12206 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12208 }
12209
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012210 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012211 synchronized (this) {
12212 int i;
12213
12214 // First remove any unused application processes whose package
12215 // has been removed.
12216 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12217 final ProcessRecord app = mRemovedProcesses.get(i);
12218 if (app.activities.size() == 0
12219 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012220 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012221 TAG, "Exiting empty application process "
12222 + app.processName + " ("
12223 + (app.thread != null ? app.thread.asBinder() : null)
12224 + ")\n");
12225 if (app.pid > 0 && app.pid != MY_PID) {
12226 Process.killProcess(app.pid);
12227 } else {
12228 try {
12229 app.thread.scheduleExit();
12230 } catch (Exception e) {
12231 // Ignore exceptions.
12232 }
12233 }
12234 cleanUpApplicationRecordLocked(app, false, -1);
12235 mRemovedProcesses.remove(i);
12236
12237 if (app.persistent) {
12238 if (app.persistent) {
12239 addAppLocked(app.info);
12240 }
12241 }
12242 }
12243 }
12244
12245 // Now try updating the OOM adjustment for each of the
12246 // application processes based on their current state.
12247 // If the setOomAdj() API is not supported, then go with our
12248 // back-up plan...
12249 if (!updateOomAdjLocked()) {
12250
12251 // Count how many processes are running services.
12252 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012253 for (i=mLruProcesses.size()-1; i>=0; i--) {
12254 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255
12256 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012257 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 // Don't count processes holding services against our
12259 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012260 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012261 TAG, "Not trimming app " + app + " with services: "
12262 + app.services);
12263 numServiceProcs++;
12264 }
12265 }
12266
12267 int curMaxProcs = mProcessLimit;
12268 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12269 if (mAlwaysFinishActivities) {
12270 curMaxProcs = 1;
12271 }
12272 curMaxProcs += numServiceProcs;
12273
12274 // Quit as many processes as we can to get down to the desired
12275 // process count. First remove any processes that no longer
12276 // have activites running in them.
12277 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012278 i<mLruProcesses.size()
12279 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012281 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012282 // Quit an application only if it is not currently
12283 // running any activities.
12284 if (!app.persistent && app.activities.size() == 0
12285 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012286 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012287 TAG, "Exiting empty application process "
12288 + app.processName + " ("
12289 + (app.thread != null ? app.thread.asBinder() : null)
12290 + ")\n");
12291 if (app.pid > 0 && app.pid != MY_PID) {
12292 Process.killProcess(app.pid);
12293 } else {
12294 try {
12295 app.thread.scheduleExit();
12296 } catch (Exception e) {
12297 // Ignore exceptions.
12298 }
12299 }
12300 // todo: For now we assume the application is not buggy
12301 // or evil, and will quit as a result of our request.
12302 // Eventually we need to drive this off of the death
12303 // notification, and kill the process if it takes too long.
12304 cleanUpApplicationRecordLocked(app, false, i);
12305 i--;
12306 }
12307 }
12308
12309 // If we still have too many processes, now from the least
12310 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012311 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012312 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012313 " of " + curMaxProcs + " processes");
12314 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012315 i<mLruProcesses.size()
12316 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012317 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012318 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012319 // Quit the application only if we have a state saved for
12320 // all of its activities.
12321 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012322 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012323 int NUMA = app.activities.size();
12324 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012325 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012326 TAG, "Looking to quit " + app.processName);
12327 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012328 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012329 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 TAG, " " + r.intent.getComponent().flattenToShortString()
12331 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12332 canQuit = (r.haveState || !r.stateNotNeeded)
12333 && !r.visible && r.stopped;
12334 }
12335 if (canQuit) {
12336 // Finish all of the activities, and then the app itself.
12337 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012338 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012339 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012340 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 }
12342 r.resultTo = null;
12343 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012344 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 + app.processName + " ("
12346 + (app.thread != null ? app.thread.asBinder() : null)
12347 + ")\n");
12348 if (app.pid > 0 && app.pid != MY_PID) {
12349 Process.killProcess(app.pid);
12350 } else {
12351 try {
12352 app.thread.scheduleExit();
12353 } catch (Exception e) {
12354 // Ignore exceptions.
12355 }
12356 }
12357 // todo: For now we assume the application is not buggy
12358 // or evil, and will quit as a result of our request.
12359 // Eventually we need to drive this off of the death
12360 // notification, and kill the process if it takes too long.
12361 cleanUpApplicationRecordLocked(app, false, i);
12362 i--;
12363 //dump();
12364 }
12365 }
12366
12367 }
12368
12369 int curMaxActivities = MAX_ACTIVITIES;
12370 if (mAlwaysFinishActivities) {
12371 curMaxActivities = 1;
12372 }
12373
12374 // Finally, if there are too many activities now running, try to
12375 // finish as many as we can to get back down to the limit.
12376 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012377 i<mMainStack.mLRUActivities.size()
12378 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012380 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012381 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382
12383 // We can finish this one if we have its icicle saved and
12384 // it is not persistent.
12385 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012386 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012387 final int origSize = mMainStack.mLRUActivities.size();
12388 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012389
12390 // This will remove it from the LRU list, so keep
12391 // our index at the same value. Note that this check to
12392 // see if the size changes is just paranoia -- if
12393 // something unexpected happens, we don't want to end up
12394 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012395 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012396 i--;
12397 }
12398 }
12399 }
12400 }
12401 }
12402
12403 /** This method sends the specified signal to each of the persistent apps */
12404 public void signalPersistentProcesses(int sig) throws RemoteException {
12405 if (sig != Process.SIGNAL_USR1) {
12406 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12407 }
12408
12409 synchronized (this) {
12410 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12411 != PackageManager.PERMISSION_GRANTED) {
12412 throw new SecurityException("Requires permission "
12413 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12414 }
12415
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012416 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12417 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 if (r.thread != null && r.persistent) {
12419 Process.sendSignal(r.pid, sig);
12420 }
12421 }
12422 }
12423 }
12424
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012425 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012426 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012427
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012428 try {
12429 synchronized (this) {
12430 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12431 // its own permission.
12432 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12433 != PackageManager.PERMISSION_GRANTED) {
12434 throw new SecurityException("Requires permission "
12435 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012436 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012437
12438 if (start && fd == null) {
12439 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012440 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012441
12442 ProcessRecord proc = null;
12443 try {
12444 int pid = Integer.parseInt(process);
12445 synchronized (mPidsSelfLocked) {
12446 proc = mPidsSelfLocked.get(pid);
12447 }
12448 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012449 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012450
12451 if (proc == null) {
12452 HashMap<String, SparseArray<ProcessRecord>> all
12453 = mProcessNames.getMap();
12454 SparseArray<ProcessRecord> procs = all.get(process);
12455 if (procs != null && procs.size() > 0) {
12456 proc = procs.valueAt(0);
12457 }
12458 }
12459
12460 if (proc == null || proc.thread == null) {
12461 throw new IllegalArgumentException("Unknown process: " + process);
12462 }
12463
12464 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12465 if (isSecure) {
12466 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12467 throw new SecurityException("Process not debuggable: " + proc);
12468 }
12469 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012470
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012471 proc.thread.profilerControl(start, path, fd);
12472 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012473 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012474 }
12475 } catch (RemoteException e) {
12476 throw new IllegalStateException("Process disappeared");
12477 } finally {
12478 if (fd != null) {
12479 try {
12480 fd.close();
12481 } catch (IOException e) {
12482 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012483 }
12484 }
12485 }
12486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012487 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12488 public void monitor() {
12489 synchronized (this) { }
12490 }
12491}