blob: a881bc4dd5aa609757204ecb3127801a3182d5c2 [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;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004388 } else {
4389 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4390 perm.readOwners.add(owner);
4391 owner.addReadPermission(perm);
4392 }
4393 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4394 perm.writeOwners.add(owner);
4395 owner.addWritePermission(perm);
4396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398 }
4399
Dianne Hackborn39792d22010-08-19 18:01:52 -07004400 void grantUriPermissionLocked(int callingUid,
4401 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4402 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4403 if (targetUid < 0) {
4404 return;
4405 }
4406
4407 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4408 }
4409
4410 /**
4411 * Like checkGrantUriPermissionLocked, but takes an Intent.
4412 */
4413 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4414 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004415 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004416 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004417 + " from " + intent + "; flags=0x"
4418 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004421 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 }
4423 Uri data = intent.getData();
4424 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004425 return -1;
4426 }
4427 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4428 intent.getFlags());
4429 }
4430
4431 /**
4432 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4433 */
4434 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4435 String targetPkg, Intent intent, UriPermissionOwner owner) {
4436 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4437 intent.getFlags(), owner);
4438 }
4439
4440 void grantUriPermissionFromIntentLocked(int callingUid,
4441 String targetPkg, Intent intent, UriPermissionOwner owner) {
4442 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4443 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 return;
4445 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004446
4447 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 }
4449
4450 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4451 Uri uri, int modeFlags) {
4452 synchronized(this) {
4453 final ProcessRecord r = getRecordForAppLocked(caller);
4454 if (r == null) {
4455 throw new SecurityException("Unable to find app for caller "
4456 + caller
4457 + " when granting permission to uri " + uri);
4458 }
4459 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004460 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 }
4462 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004463 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 }
4465
4466 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4467 null);
4468 }
4469 }
4470
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004471 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4473 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4474 HashMap<Uri, UriPermission> perms
4475 = mGrantedUriPermissions.get(perm.uid);
4476 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004477 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004478 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 perms.remove(perm.uri);
4480 if (perms.size() == 0) {
4481 mGrantedUriPermissions.remove(perm.uid);
4482 }
4483 }
4484 }
4485 }
4486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4488 int modeFlags) {
4489 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4490 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4491 if (modeFlags == 0) {
4492 return;
4493 }
4494
Joe Onorato8a9b2202010-02-26 18:56:32 -08004495 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004496 "Revoking all granted permissions to " + uri);
4497
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004498 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499
4500 final String authority = uri.getAuthority();
4501 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004502 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 if (cpr != null) {
4504 pi = cpr.info;
4505 } else {
4506 try {
4507 pi = pm.resolveContentProvider(authority,
4508 PackageManager.GET_URI_PERMISSION_PATTERNS);
4509 } catch (RemoteException ex) {
4510 }
4511 }
4512 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004513 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 return;
4515 }
4516
4517 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004518 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 // Right now, if you are not the original owner of the permission,
4520 // you are not allowed to revoke it.
4521 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4522 throw new SecurityException("Uid " + callingUid
4523 + " does not have permission to uri " + uri);
4524 //}
4525 }
4526
4527 // Go through all of the permissions and remove any that match.
4528 final List<String> SEGMENTS = uri.getPathSegments();
4529 if (SEGMENTS != null) {
4530 final int NS = SEGMENTS.size();
4531 int N = mGrantedUriPermissions.size();
4532 for (int i=0; i<N; i++) {
4533 HashMap<Uri, UriPermission> perms
4534 = mGrantedUriPermissions.valueAt(i);
4535 Iterator<UriPermission> it = perms.values().iterator();
4536 toploop:
4537 while (it.hasNext()) {
4538 UriPermission perm = it.next();
4539 Uri targetUri = perm.uri;
4540 if (!authority.equals(targetUri.getAuthority())) {
4541 continue;
4542 }
4543 List<String> targetSegments = targetUri.getPathSegments();
4544 if (targetSegments == null) {
4545 continue;
4546 }
4547 if (targetSegments.size() < NS) {
4548 continue;
4549 }
4550 for (int j=0; j<NS; j++) {
4551 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4552 continue toploop;
4553 }
4554 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004555 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004556 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004557 perm.clearModes(modeFlags);
4558 if (perm.modeFlags == 0) {
4559 it.remove();
4560 }
4561 }
4562 if (perms.size() == 0) {
4563 mGrantedUriPermissions.remove(
4564 mGrantedUriPermissions.keyAt(i));
4565 N--;
4566 i--;
4567 }
4568 }
4569 }
4570 }
4571
4572 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4573 int modeFlags) {
4574 synchronized(this) {
4575 final ProcessRecord r = getRecordForAppLocked(caller);
4576 if (r == null) {
4577 throw new SecurityException("Unable to find app for caller "
4578 + caller
4579 + " when revoking permission to uri " + uri);
4580 }
4581 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004582 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 return;
4584 }
4585
4586 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4587 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4588 if (modeFlags == 0) {
4589 return;
4590 }
4591
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004592 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593
4594 final String authority = uri.getAuthority();
4595 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004596 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 if (cpr != null) {
4598 pi = cpr.info;
4599 } else {
4600 try {
4601 pi = pm.resolveContentProvider(authority,
4602 PackageManager.GET_URI_PERMISSION_PATTERNS);
4603 } catch (RemoteException ex) {
4604 }
4605 }
4606 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004607 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 return;
4609 }
4610
4611 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4612 }
4613 }
4614
Dianne Hackborn7e269642010-08-25 19:50:20 -07004615 @Override
4616 public IBinder newUriPermissionOwner(String name) {
4617 synchronized(this) {
4618 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4619 return owner.getExternalTokenLocked();
4620 }
4621 }
4622
4623 @Override
4624 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4625 Uri uri, int modeFlags) {
4626 synchronized(this) {
4627 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4628 if (owner == null) {
4629 throw new IllegalArgumentException("Unknown owner: " + token);
4630 }
4631 if (fromUid != Binder.getCallingUid()) {
4632 if (Binder.getCallingUid() != Process.myUid()) {
4633 // Only system code can grant URI permissions on behalf
4634 // of other users.
4635 throw new SecurityException("nice try");
4636 }
4637 }
4638 if (targetPkg == null) {
4639 throw new IllegalArgumentException("null target");
4640 }
4641 if (uri == null) {
4642 throw new IllegalArgumentException("null uri");
4643 }
4644
4645 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4646 }
4647 }
4648
4649 @Override
4650 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4651 synchronized(this) {
4652 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4653 if (owner == null) {
4654 throw new IllegalArgumentException("Unknown owner: " + token);
4655 }
4656
4657 if (uri == null) {
4658 owner.removeUriPermissionsLocked(mode);
4659 } else {
4660 owner.removeUriPermissionLocked(uri, mode);
4661 }
4662 }
4663 }
4664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4666 synchronized (this) {
4667 ProcessRecord app =
4668 who != null ? getRecordForAppLocked(who) : null;
4669 if (app == null) return;
4670
4671 Message msg = Message.obtain();
4672 msg.what = WAIT_FOR_DEBUGGER_MSG;
4673 msg.obj = app;
4674 msg.arg1 = waiting ? 1 : 0;
4675 mHandler.sendMessage(msg);
4676 }
4677 }
4678
4679 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4680 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004681 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004683 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 }
4685
4686 // =========================================================
4687 // TASK MANAGEMENT
4688 // =========================================================
4689
4690 public List getTasks(int maxNum, int flags,
4691 IThumbnailReceiver receiver) {
4692 ArrayList list = new ArrayList();
4693
4694 PendingThumbnailsRecord pending = null;
4695 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004696 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697
4698 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004699 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4701 + ", receiver=" + receiver);
4702
4703 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4704 != PackageManager.PERMISSION_GRANTED) {
4705 if (receiver != null) {
4706 // If the caller wants to wait for pending thumbnails,
4707 // it ain't gonna get them.
4708 try {
4709 receiver.finished();
4710 } catch (RemoteException ex) {
4711 }
4712 }
4713 String msg = "Permission Denial: getTasks() from pid="
4714 + Binder.getCallingPid()
4715 + ", uid=" + Binder.getCallingUid()
4716 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004717 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 throw new SecurityException(msg);
4719 }
4720
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004721 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004722 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004723 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004724 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 CharSequence topDescription = null;
4726 TaskRecord curTask = null;
4727 int numActivities = 0;
4728 int numRunning = 0;
4729 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004730 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004732 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733
4734 // Initialize state for next task if needed.
4735 if (top == null ||
4736 (top.state == ActivityState.INITIALIZING
4737 && top.task == r.task)) {
4738 top = r;
4739 topDescription = r.description;
4740 curTask = r.task;
4741 numActivities = numRunning = 0;
4742 }
4743
4744 // Add 'r' into the current task.
4745 numActivities++;
4746 if (r.app != null && r.app.thread != null) {
4747 numRunning++;
4748 }
4749 if (topDescription == null) {
4750 topDescription = r.description;
4751 }
4752
Joe Onorato8a9b2202010-02-26 18:56:32 -08004753 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 TAG, r.intent.getComponent().flattenToShortString()
4755 + ": task=" + r.task);
4756
4757 // If the next one is a different task, generate a new
4758 // TaskInfo entry for what we have.
4759 if (next == null || next.task != curTask) {
4760 ActivityManager.RunningTaskInfo ci
4761 = new ActivityManager.RunningTaskInfo();
4762 ci.id = curTask.taskId;
4763 ci.baseActivity = r.intent.getComponent();
4764 ci.topActivity = top.intent.getComponent();
4765 ci.thumbnail = top.thumbnail;
4766 ci.description = topDescription;
4767 ci.numActivities = numActivities;
4768 ci.numRunning = numRunning;
4769 //System.out.println(
4770 // "#" + maxNum + ": " + " descr=" + ci.description);
4771 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004772 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 TAG, "State=" + top.state + "Idle=" + top.idle
4774 + " app=" + top.app
4775 + " thr=" + (top.app != null ? top.app.thread : null));
4776 if (top.state == ActivityState.RESUMED
4777 || top.state == ActivityState.PAUSING) {
4778 if (top.idle && top.app != null
4779 && top.app.thread != null) {
4780 topRecord = top;
4781 topThumbnail = top.app.thread;
4782 } else {
4783 top.thumbnailNeeded = true;
4784 }
4785 }
4786 if (pending == null) {
4787 pending = new PendingThumbnailsRecord(receiver);
4788 }
4789 pending.pendingRecords.add(top);
4790 }
4791 list.add(ci);
4792 maxNum--;
4793 top = null;
4794 }
4795 }
4796
4797 if (pending != null) {
4798 mPendingThumbnails.add(pending);
4799 }
4800 }
4801
Joe Onorato8a9b2202010-02-26 18:56:32 -08004802 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803
4804 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004805 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 try {
4807 topThumbnail.requestThumbnail(topRecord);
4808 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004809 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004810 sendPendingThumbnail(null, topRecord, null, null, true);
4811 }
4812 }
4813
4814 if (pending == null && receiver != null) {
4815 // In this case all thumbnails were available and the client
4816 // is being asked to be told when the remaining ones come in...
4817 // which is unusually, since the top-most currently running
4818 // activity should never have a canned thumbnail! Oh well.
4819 try {
4820 receiver.finished();
4821 } catch (RemoteException ex) {
4822 }
4823 }
4824
4825 return list;
4826 }
4827
4828 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4829 int flags) {
4830 synchronized (this) {
4831 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4832 "getRecentTasks()");
4833
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004834 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 final int N = mRecentTasks.size();
4837 ArrayList<ActivityManager.RecentTaskInfo> res
4838 = new ArrayList<ActivityManager.RecentTaskInfo>(
4839 maxNum < N ? maxNum : N);
4840 for (int i=0; i<N && maxNum > 0; i++) {
4841 TaskRecord tr = mRecentTasks.get(i);
4842 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4843 || (tr.intent == null)
4844 || ((tr.intent.getFlags()
4845 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4846 ActivityManager.RecentTaskInfo rti
4847 = new ActivityManager.RecentTaskInfo();
4848 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4849 rti.baseIntent = new Intent(
4850 tr.intent != null ? tr.intent : tr.affinityIntent);
4851 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004852
4853 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4854 // Check whether this activity is currently available.
4855 try {
4856 if (rti.origActivity != null) {
4857 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4858 continue;
4859 }
4860 } else if (rti.baseIntent != null) {
4861 if (pm.queryIntentActivities(rti.baseIntent,
4862 null, 0) == null) {
4863 continue;
4864 }
4865 }
4866 } catch (RemoteException e) {
4867 // Will never happen.
4868 }
4869 }
4870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 res.add(rti);
4872 maxNum--;
4873 }
4874 }
4875 return res;
4876 }
4877 }
4878
4879 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4880 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004881 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 TaskRecord jt = startTask;
4883
4884 // First look backwards
4885 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004886 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 if (r.task != jt) {
4888 jt = r.task;
4889 if (affinity.equals(jt.affinity)) {
4890 return j;
4891 }
4892 }
4893 }
4894
4895 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004896 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 jt = startTask;
4898 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004899 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 if (r.task != jt) {
4901 if (affinity.equals(jt.affinity)) {
4902 return j;
4903 }
4904 jt = r.task;
4905 }
4906 }
4907
4908 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004909 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 return N-1;
4911 }
4912
4913 return -1;
4914 }
4915
4916 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004917 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 */
4919 public void moveTaskToFront(int task) {
4920 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4921 "moveTaskToFront()");
4922
4923 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004924 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4925 Binder.getCallingUid(), "Task to front")) {
4926 return;
4927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 final long origId = Binder.clearCallingIdentity();
4929 try {
4930 int N = mRecentTasks.size();
4931 for (int i=0; i<N; i++) {
4932 TaskRecord tr = mRecentTasks.get(i);
4933 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004934 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 return;
4936 }
4937 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004938 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4939 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004941 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 return;
4943 }
4944 }
4945 } finally {
4946 Binder.restoreCallingIdentity(origId);
4947 }
4948 }
4949 }
4950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 public void moveTaskToBack(int task) {
4952 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4953 "moveTaskToBack()");
4954
4955 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004956 if (mMainStack.mResumedActivity != null
4957 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004958 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4959 Binder.getCallingUid(), "Task to back")) {
4960 return;
4961 }
4962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004964 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 Binder.restoreCallingIdentity(origId);
4966 }
4967 }
4968
4969 /**
4970 * Moves an activity, and all of the other activities within the same task, to the bottom
4971 * of the history stack. The activity's order within the task is unchanged.
4972 *
4973 * @param token A reference to the activity we wish to move
4974 * @param nonRoot If false then this only works if the activity is the root
4975 * of a task; if true it will work for any activity in a task.
4976 * @return Returns true if the move completed, false if not.
4977 */
4978 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4979 synchronized(this) {
4980 final long origId = Binder.clearCallingIdentity();
4981 int taskId = getTaskForActivityLocked(token, !nonRoot);
4982 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004983 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 }
4985 Binder.restoreCallingIdentity(origId);
4986 }
4987 return false;
4988 }
4989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 public void moveTaskBackwards(int task) {
4991 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4992 "moveTaskBackwards()");
4993
4994 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004995 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4996 Binder.getCallingUid(), "Task backwards")) {
4997 return;
4998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 final long origId = Binder.clearCallingIdentity();
5000 moveTaskBackwardsLocked(task);
5001 Binder.restoreCallingIdentity(origId);
5002 }
5003 }
5004
5005 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005006 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 }
5008
5009 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5010 synchronized(this) {
5011 return getTaskForActivityLocked(token, onlyRoot);
5012 }
5013 }
5014
5015 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005016 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 TaskRecord lastTask = null;
5018 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005019 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005020 if (r == token) {
5021 if (!onlyRoot || lastTask != r.task) {
5022 return r.task.taskId;
5023 }
5024 return -1;
5025 }
5026 lastTask = r.task;
5027 }
5028
5029 return -1;
5030 }
5031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 public void finishOtherInstances(IBinder token, ComponentName className) {
5033 synchronized(this) {
5034 final long origId = Binder.clearCallingIdentity();
5035
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005036 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 TaskRecord lastTask = null;
5038 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005039 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 if (r.realActivity.equals(className)
5041 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005042 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005043 null, "others")) {
5044 i--;
5045 N--;
5046 }
5047 }
5048 lastTask = r.task;
5049 }
5050
5051 Binder.restoreCallingIdentity(origId);
5052 }
5053 }
5054
5055 // =========================================================
5056 // THUMBNAILS
5057 // =========================================================
5058
5059 public void reportThumbnail(IBinder token,
5060 Bitmap thumbnail, CharSequence description) {
5061 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5062 final long origId = Binder.clearCallingIdentity();
5063 sendPendingThumbnail(null, token, thumbnail, description, true);
5064 Binder.restoreCallingIdentity(origId);
5065 }
5066
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005067 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 Bitmap thumbnail, CharSequence description, boolean always) {
5069 TaskRecord task = null;
5070 ArrayList receivers = null;
5071
5072 //System.out.println("Send pending thumbnail: " + r);
5073
5074 synchronized(this) {
5075 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005076 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 if (index < 0) {
5078 return;
5079 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005080 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 }
5082 if (thumbnail == null) {
5083 thumbnail = r.thumbnail;
5084 description = r.description;
5085 }
5086 if (thumbnail == null && !always) {
5087 // If there is no thumbnail, and this entry is not actually
5088 // going away, then abort for now and pick up the next
5089 // thumbnail we get.
5090 return;
5091 }
5092 task = r.task;
5093
5094 int N = mPendingThumbnails.size();
5095 int i=0;
5096 while (i<N) {
5097 PendingThumbnailsRecord pr =
5098 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5099 //System.out.println("Looking in " + pr.pendingRecords);
5100 if (pr.pendingRecords.remove(r)) {
5101 if (receivers == null) {
5102 receivers = new ArrayList();
5103 }
5104 receivers.add(pr);
5105 if (pr.pendingRecords.size() == 0) {
5106 pr.finished = true;
5107 mPendingThumbnails.remove(i);
5108 N--;
5109 continue;
5110 }
5111 }
5112 i++;
5113 }
5114 }
5115
5116 if (receivers != null) {
5117 final int N = receivers.size();
5118 for (int i=0; i<N; i++) {
5119 try {
5120 PendingThumbnailsRecord pr =
5121 (PendingThumbnailsRecord)receivers.get(i);
5122 pr.receiver.newThumbnail(
5123 task != null ? task.taskId : -1, thumbnail, description);
5124 if (pr.finished) {
5125 pr.receiver.finished();
5126 }
5127 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005128 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 }
5130 }
5131 }
5132 }
5133
5134 // =========================================================
5135 // CONTENT PROVIDERS
5136 // =========================================================
5137
5138 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5139 List providers = null;
5140 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005141 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005143 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005144 } catch (RemoteException ex) {
5145 }
5146 if (providers != null) {
5147 final int N = providers.size();
5148 for (int i=0; i<N; i++) {
5149 ProviderInfo cpi =
5150 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005151 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 if (cpr == null) {
5153 cpr = new ContentProviderRecord(cpi, app.info);
5154 mProvidersByClass.put(cpi.name, cpr);
5155 }
5156 app.pubProviders.put(cpi.name, cpr);
5157 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005158 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 }
5160 }
5161 return providers;
5162 }
5163
5164 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005165 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5167 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5168 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5169 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005170 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 return null;
5172 }
5173 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5174 cpi.exported ? -1 : cpi.applicationInfo.uid)
5175 == PackageManager.PERMISSION_GRANTED) {
5176 return null;
5177 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005178
5179 PathPermission[] pps = cpi.pathPermissions;
5180 if (pps != null) {
5181 int i = pps.length;
5182 while (i > 0) {
5183 i--;
5184 PathPermission pp = pps[i];
5185 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5186 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005187 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005188 return null;
5189 }
5190 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5191 cpi.exported ? -1 : cpi.applicationInfo.uid)
5192 == PackageManager.PERMISSION_GRANTED) {
5193 return null;
5194 }
5195 }
5196 }
5197
Dianne Hackbornb424b632010-08-18 15:59:05 -07005198 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5199 if (perms != null) {
5200 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5201 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5202 return null;
5203 }
5204 }
5205 }
5206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005207 String msg = "Permission Denial: opening provider " + cpi.name
5208 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5209 + ", uid=" + callingUid + ") requires "
5210 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005211 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 return msg;
5213 }
5214
5215 private final ContentProviderHolder getContentProviderImpl(
5216 IApplicationThread caller, String name) {
5217 ContentProviderRecord cpr;
5218 ProviderInfo cpi = null;
5219
5220 synchronized(this) {
5221 ProcessRecord r = null;
5222 if (caller != null) {
5223 r = getRecordForAppLocked(caller);
5224 if (r == null) {
5225 throw new SecurityException(
5226 "Unable to find app for caller " + caller
5227 + " (pid=" + Binder.getCallingPid()
5228 + ") when getting content provider " + name);
5229 }
5230 }
5231
5232 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005233 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 if (cpr != null) {
5235 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005236 String msg;
5237 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5238 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005239 }
5240
5241 if (r != null && cpr.canRunHere(r)) {
5242 // This provider has been published or is in the process
5243 // of being published... but it is also allowed to run
5244 // in the caller's process, so don't make a connection
5245 // and just let the caller instantiate its own instance.
5246 if (cpr.provider != null) {
5247 // don't give caller the provider object, it needs
5248 // to make its own.
5249 cpr = new ContentProviderRecord(cpr);
5250 }
5251 return cpr;
5252 }
5253
5254 final long origId = Binder.clearCallingIdentity();
5255
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005256 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 // return it right away.
5258 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005259 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005260 "Adding provider requested by "
5261 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005262 + cpr.info.processName);
5263 Integer cnt = r.conProviders.get(cpr);
5264 if (cnt == null) {
5265 r.conProviders.put(cpr, new Integer(1));
5266 } else {
5267 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005270 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5271 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005272 // make sure to count it as being accessed and thus
5273 // back up on the LRU list. This is good because
5274 // content providers are often expensive to start.
5275 updateLruProcessLocked(cpr.app, false, true);
5276 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005277 } else {
5278 cpr.externals++;
5279 }
5280
5281 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 updateOomAdjLocked(cpr.app);
5283 }
5284
5285 Binder.restoreCallingIdentity(origId);
5286
5287 } else {
5288 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005289 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005290 resolveContentProvider(name,
5291 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 } catch (RemoteException ex) {
5293 }
5294 if (cpi == null) {
5295 return null;
5296 }
5297
Dianne Hackbornb424b632010-08-18 15:59:05 -07005298 String msg;
5299 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5300 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005303 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005304 && !cpi.processName.equals("system")) {
5305 // If this content provider does not run in the system
5306 // process, and the system is not yet ready to run other
5307 // processes, then fail fast instead of hanging.
5308 throw new IllegalArgumentException(
5309 "Attempt to launch content provider before system ready");
5310 }
5311
Dianne Hackborn860755f2010-06-03 18:47:52 -07005312 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005313 final boolean firstClass = cpr == null;
5314 if (firstClass) {
5315 try {
5316 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005317 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 getApplicationInfo(
5319 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005320 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005322 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 + cpi.name);
5324 return null;
5325 }
5326 cpr = new ContentProviderRecord(cpi, ai);
5327 } catch (RemoteException ex) {
5328 // pm is in same process, this will never happen.
5329 }
5330 }
5331
5332 if (r != null && cpr.canRunHere(r)) {
5333 // If this is a multiprocess provider, then just return its
5334 // info and allow the caller to instantiate it. Only do
5335 // this if the provider is the same user as the caller's
5336 // process, or can run as root (so can be in any process).
5337 return cpr;
5338 }
5339
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005340 if (DEBUG_PROVIDER) {
5341 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005342 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005343 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 }
5345
5346 // This is single process, and our app is now connecting to it.
5347 // See if we are already in the process of launching this
5348 // provider.
5349 final int N = mLaunchingProviders.size();
5350 int i;
5351 for (i=0; i<N; i++) {
5352 if (mLaunchingProviders.get(i) == cpr) {
5353 break;
5354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 }
5356
5357 // If the provider is not already being launched, then get it
5358 // started.
5359 if (i >= N) {
5360 final long origId = Binder.clearCallingIdentity();
5361 ProcessRecord proc = startProcessLocked(cpi.processName,
5362 cpr.appInfo, false, 0, "content provider",
5363 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005364 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005366 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 + cpi.applicationInfo.packageName + "/"
5368 + cpi.applicationInfo.uid + " for provider "
5369 + name + ": process is bad");
5370 return null;
5371 }
5372 cpr.launchingApp = proc;
5373 mLaunchingProviders.add(cpr);
5374 Binder.restoreCallingIdentity(origId);
5375 }
5376
5377 // Make sure the provider is published (the same provider class
5378 // may be published under multiple names).
5379 if (firstClass) {
5380 mProvidersByClass.put(cpi.name, cpr);
5381 }
5382 mProvidersByName.put(name, cpr);
5383
5384 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005385 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005386 "Adding provider requested by "
5387 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005388 + cpr.info.processName);
5389 Integer cnt = r.conProviders.get(cpr);
5390 if (cnt == null) {
5391 r.conProviders.put(cpr, new Integer(1));
5392 } else {
5393 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 cpr.clients.add(r);
5396 } else {
5397 cpr.externals++;
5398 }
5399 }
5400 }
5401
5402 // Wait for the provider to be published...
5403 synchronized (cpr) {
5404 while (cpr.provider == null) {
5405 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005406 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005407 + cpi.applicationInfo.packageName + "/"
5408 + cpi.applicationInfo.uid + " for provider "
5409 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005410 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 cpi.applicationInfo.packageName,
5412 cpi.applicationInfo.uid, name);
5413 return null;
5414 }
5415 try {
5416 cpr.wait();
5417 } catch (InterruptedException ex) {
5418 }
5419 }
5420 }
5421 return cpr;
5422 }
5423
5424 public final ContentProviderHolder getContentProvider(
5425 IApplicationThread caller, String name) {
5426 if (caller == null) {
5427 String msg = "null IApplicationThread when getting content provider "
5428 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005429 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 throw new SecurityException(msg);
5431 }
5432
5433 return getContentProviderImpl(caller, name);
5434 }
5435
5436 private ContentProviderHolder getContentProviderExternal(String name) {
5437 return getContentProviderImpl(null, name);
5438 }
5439
5440 /**
5441 * Drop a content provider from a ProcessRecord's bookkeeping
5442 * @param cpr
5443 */
5444 public void removeContentProvider(IApplicationThread caller, String name) {
5445 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005446 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005448 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005449 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005450 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 return;
5452 }
5453 final ProcessRecord r = getRecordForAppLocked(caller);
5454 if (r == null) {
5455 throw new SecurityException(
5456 "Unable to find app for caller " + caller +
5457 " when removing content provider " + name);
5458 }
5459 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005460 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005461 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005462 + r.info.processName + " from process "
5463 + localCpr.appInfo.processName);
5464 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005466 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005467 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 return;
5469 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005470 Integer cnt = r.conProviders.get(localCpr);
5471 if (cnt == null || cnt.intValue() <= 1) {
5472 localCpr.clients.remove(r);
5473 r.conProviders.remove(localCpr);
5474 } else {
5475 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 }
5478 updateOomAdjLocked();
5479 }
5480 }
5481
5482 private void removeContentProviderExternal(String name) {
5483 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005484 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005485 if(cpr == null) {
5486 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005487 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 return;
5489 }
5490
5491 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005492 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 localCpr.externals--;
5494 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005495 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 }
5497 updateOomAdjLocked();
5498 }
5499 }
5500
5501 public final void publishContentProviders(IApplicationThread caller,
5502 List<ContentProviderHolder> providers) {
5503 if (providers == null) {
5504 return;
5505 }
5506
5507 synchronized(this) {
5508 final ProcessRecord r = getRecordForAppLocked(caller);
5509 if (r == null) {
5510 throw new SecurityException(
5511 "Unable to find app for caller " + caller
5512 + " (pid=" + Binder.getCallingPid()
5513 + ") when publishing content providers");
5514 }
5515
5516 final long origId = Binder.clearCallingIdentity();
5517
5518 final int N = providers.size();
5519 for (int i=0; i<N; i++) {
5520 ContentProviderHolder src = providers.get(i);
5521 if (src == null || src.info == null || src.provider == null) {
5522 continue;
5523 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005524 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 if (dst != null) {
5526 mProvidersByClass.put(dst.info.name, dst);
5527 String names[] = dst.info.authority.split(";");
5528 for (int j = 0; j < names.length; j++) {
5529 mProvidersByName.put(names[j], dst);
5530 }
5531
5532 int NL = mLaunchingProviders.size();
5533 int j;
5534 for (j=0; j<NL; j++) {
5535 if (mLaunchingProviders.get(j) == dst) {
5536 mLaunchingProviders.remove(j);
5537 j--;
5538 NL--;
5539 }
5540 }
5541 synchronized (dst) {
5542 dst.provider = src.provider;
5543 dst.app = r;
5544 dst.notifyAll();
5545 }
5546 updateOomAdjLocked(r);
5547 }
5548 }
5549
5550 Binder.restoreCallingIdentity(origId);
5551 }
5552 }
5553
5554 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005555 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005556 synchronized (mSelf) {
5557 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5558 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005559 if (providers != null) {
5560 for (int i=providers.size()-1; i>=0; i--) {
5561 ProviderInfo pi = (ProviderInfo)providers.get(i);
5562 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5563 Slog.w(TAG, "Not installing system proc provider " + pi.name
5564 + ": not system .apk");
5565 providers.remove(i);
5566 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005567 }
5568 }
5569 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005570 if (providers != null) {
5571 mSystemThread.installSystemProviders(providers);
5572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 }
5574
Dianne Hackborn8313fc72010-09-26 18:34:53 -07005575 /**
5576 * Allows app to retrieve the MIME type of a URI without having permission
5577 * to access its content provider.
5578 *
5579 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5580 *
5581 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5582 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5583 */
5584 public String getProviderMimeType(Uri uri) {
5585 final String name = uri.getAuthority();
5586 final long ident = Binder.clearCallingIdentity();
5587 ContentProviderHolder holder = null;
5588
5589 try {
5590 holder = getContentProviderExternal(name);
5591 if (holder != null) {
5592 return holder.provider.getType(uri);
5593 }
5594 } catch (RemoteException e) {
5595 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5596 return null;
5597 } finally {
5598 if (holder != null) {
5599 removeContentProviderExternal(name);
5600 }
5601 Binder.restoreCallingIdentity(ident);
5602 }
5603
5604 return null;
5605 }
5606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 // =========================================================
5608 // GLOBAL MANAGEMENT
5609 // =========================================================
5610
5611 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5612 ApplicationInfo info, String customProcess) {
5613 String proc = customProcess != null ? customProcess : info.processName;
5614 BatteryStatsImpl.Uid.Proc ps = null;
5615 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5616 synchronized (stats) {
5617 ps = stats.getProcessStatsLocked(info.uid, proc);
5618 }
5619 return new ProcessRecord(ps, thread, info, proc);
5620 }
5621
5622 final ProcessRecord addAppLocked(ApplicationInfo info) {
5623 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5624
5625 if (app == null) {
5626 app = newProcessRecordLocked(null, info, null);
5627 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005628 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 }
5630
5631 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5632 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5633 app.persistent = true;
5634 app.maxAdj = CORE_SERVER_ADJ;
5635 }
5636 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5637 mPersistentStartingProcesses.add(app);
5638 startProcessLocked(app, "added application", app.processName);
5639 }
5640
5641 return app;
5642 }
5643
5644 public void unhandledBack() {
5645 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5646 "unhandledBack()");
5647
5648 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005649 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005650 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 TAG, "Performing unhandledBack(): stack size = " + count);
5652 if (count > 1) {
5653 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005654 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5656 Binder.restoreCallingIdentity(origId);
5657 }
5658 }
5659 }
5660
5661 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5662 String name = uri.getAuthority();
5663 ContentProviderHolder cph = getContentProviderExternal(name);
5664 ParcelFileDescriptor pfd = null;
5665 if (cph != null) {
5666 // We record the binder invoker's uid in thread-local storage before
5667 // going to the content provider to open the file. Later, in the code
5668 // that handles all permissions checks, we look for this uid and use
5669 // that rather than the Activity Manager's own uid. The effect is that
5670 // we do the check against the caller's permissions even though it looks
5671 // to the content provider like the Activity Manager itself is making
5672 // the request.
5673 sCallerIdentity.set(new Identity(
5674 Binder.getCallingPid(), Binder.getCallingUid()));
5675 try {
5676 pfd = cph.provider.openFile(uri, "r");
5677 } catch (FileNotFoundException e) {
5678 // do nothing; pfd will be returned null
5679 } finally {
5680 // Ensure that whatever happens, we clean up the identity state
5681 sCallerIdentity.remove();
5682 }
5683
5684 // We've got the fd now, so we're done with the provider.
5685 removeContentProviderExternal(name);
5686 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005687 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 }
5689 return pfd;
5690 }
5691
5692 public void goingToSleep() {
5693 synchronized(this) {
5694 mSleeping = true;
5695 mWindowManager.setEventDispatching(false);
5696
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005697 if (mMainStack.mResumedActivity != null) {
5698 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005702
5703 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005704 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005705 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5706 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005707 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005708 }
5709 }
5710
Dianne Hackborn55280a92009-05-07 15:53:46 -07005711 public boolean shutdown(int timeout) {
5712 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5713 != PackageManager.PERMISSION_GRANTED) {
5714 throw new SecurityException("Requires permission "
5715 + android.Manifest.permission.SHUTDOWN);
5716 }
5717
5718 boolean timedout = false;
5719
5720 synchronized(this) {
5721 mShuttingDown = true;
5722 mWindowManager.setEventDispatching(false);
5723
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005724 if (mMainStack.mResumedActivity != null) {
5725 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005726 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005727 while (mMainStack.mResumedActivity != null
5728 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005729 long delay = endTime - System.currentTimeMillis();
5730 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005731 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005732 timedout = true;
5733 break;
5734 }
5735 try {
5736 this.wait();
5737 } catch (InterruptedException e) {
5738 }
5739 }
5740 }
5741 }
5742
5743 mUsageStatsService.shutdown();
5744 mBatteryStatsService.shutdown();
5745
5746 return timedout;
5747 }
5748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 public void wakingUp() {
5750 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005751 if (mMainStack.mGoingToSleep.isHeld()) {
5752 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 }
5754 mWindowManager.setEventDispatching(true);
5755 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005756 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 }
5758 }
5759
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005760 public void stopAppSwitches() {
5761 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5762 != PackageManager.PERMISSION_GRANTED) {
5763 throw new SecurityException("Requires permission "
5764 + android.Manifest.permission.STOP_APP_SWITCHES);
5765 }
5766
5767 synchronized(this) {
5768 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5769 + APP_SWITCH_DELAY_TIME;
5770 mDidAppSwitch = false;
5771 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5772 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5773 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5774 }
5775 }
5776
5777 public void resumeAppSwitches() {
5778 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5779 != PackageManager.PERMISSION_GRANTED) {
5780 throw new SecurityException("Requires permission "
5781 + android.Manifest.permission.STOP_APP_SWITCHES);
5782 }
5783
5784 synchronized(this) {
5785 // Note that we don't execute any pending app switches... we will
5786 // let those wait until either the timeout, or the next start
5787 // activity request.
5788 mAppSwitchesAllowedTime = 0;
5789 }
5790 }
5791
5792 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5793 String name) {
5794 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5795 return true;
5796 }
5797
5798 final int perm = checkComponentPermission(
5799 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5800 callingUid, -1);
5801 if (perm == PackageManager.PERMISSION_GRANTED) {
5802 return true;
5803 }
5804
Joe Onorato8a9b2202010-02-26 18:56:32 -08005805 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005806 return false;
5807 }
5808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 public void setDebugApp(String packageName, boolean waitForDebugger,
5810 boolean persistent) {
5811 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5812 "setDebugApp()");
5813
5814 // Note that this is not really thread safe if there are multiple
5815 // callers into it at the same time, but that's not a situation we
5816 // care about.
5817 if (persistent) {
5818 final ContentResolver resolver = mContext.getContentResolver();
5819 Settings.System.putString(
5820 resolver, Settings.System.DEBUG_APP,
5821 packageName);
5822 Settings.System.putInt(
5823 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5824 waitForDebugger ? 1 : 0);
5825 }
5826
5827 synchronized (this) {
5828 if (!persistent) {
5829 mOrigDebugApp = mDebugApp;
5830 mOrigWaitForDebugger = mWaitForDebugger;
5831 }
5832 mDebugApp = packageName;
5833 mWaitForDebugger = waitForDebugger;
5834 mDebugTransient = !persistent;
5835 if (packageName != null) {
5836 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005837 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 Binder.restoreCallingIdentity(origId);
5839 }
5840 }
5841 }
5842
5843 public void setAlwaysFinish(boolean enabled) {
5844 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5845 "setAlwaysFinish()");
5846
5847 Settings.System.putInt(
5848 mContext.getContentResolver(),
5849 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5850
5851 synchronized (this) {
5852 mAlwaysFinishActivities = enabled;
5853 }
5854 }
5855
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005856 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005858 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005860 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 }
5862 }
5863
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005864 public boolean isUserAMonkey() {
5865 // For now the fact that there is a controller implies
5866 // we have a monkey.
5867 synchronized (this) {
5868 return mController != null;
5869 }
5870 }
5871
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005872 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005873 synchronized (this) {
5874 mWatchers.register(watcher);
5875 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005876 }
5877
5878 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005879 synchronized (this) {
5880 mWatchers.unregister(watcher);
5881 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005882 }
5883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 public final void enterSafeMode() {
5885 synchronized(this) {
5886 // It only makes sense to do this before the system is ready
5887 // and started launching other packages.
5888 if (!mSystemReady) {
5889 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005890 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005891 } catch (RemoteException e) {
5892 }
5893
5894 View v = LayoutInflater.from(mContext).inflate(
5895 com.android.internal.R.layout.safe_mode, null);
5896 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown2d3f1592010-10-15 00:54:27 -07005897 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5899 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5900 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5901 lp.format = v.getBackground().getOpacity();
5902 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5903 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5904 ((WindowManager)mContext.getSystemService(
5905 Context.WINDOW_SERVICE)).addView(v, lp);
5906 }
5907 }
5908 }
5909
5910 public void noteWakeupAlarm(IIntentSender sender) {
5911 if (!(sender instanceof PendingIntentRecord)) {
5912 return;
5913 }
5914 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5915 synchronized (stats) {
5916 if (mBatteryStatsService.isOnBattery()) {
5917 mBatteryStatsService.enforceCallingPermission();
5918 PendingIntentRecord rec = (PendingIntentRecord)sender;
5919 int MY_UID = Binder.getCallingUid();
5920 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5921 BatteryStatsImpl.Uid.Pkg pkg =
5922 stats.getPackageStatsLocked(uid, rec.key.packageName);
5923 pkg.incWakeupsLocked();
5924 }
5925 }
5926 }
5927
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005928 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005930 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005932 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 // XXX Note: don't acquire main activity lock here, because the window
5934 // manager calls in with its locks held.
5935
5936 boolean killed = false;
5937 synchronized (mPidsSelfLocked) {
5938 int[] types = new int[pids.length];
5939 int worstType = 0;
5940 for (int i=0; i<pids.length; i++) {
5941 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5942 if (proc != null) {
5943 int type = proc.setAdj;
5944 types[i] = type;
5945 if (type > worstType) {
5946 worstType = type;
5947 }
5948 }
5949 }
5950
5951 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5952 // then constrain it so we will kill all hidden procs.
5953 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5954 worstType = HIDDEN_APP_MIN_ADJ;
5955 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005956 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 for (int i=0; i<pids.length; i++) {
5958 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5959 if (proc == null) {
5960 continue;
5961 }
5962 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005963 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005964 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005965 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5966 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005967 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005968 proc.killedBackground = true;
5969 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 }
5971 }
5972 }
5973 return killed;
5974 }
5975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 public final void startRunning(String pkg, String cls, String action,
5977 String data) {
5978 synchronized(this) {
5979 if (mStartRunning) {
5980 return;
5981 }
5982 mStartRunning = true;
5983 mTopComponent = pkg != null && cls != null
5984 ? new ComponentName(pkg, cls) : null;
5985 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5986 mTopData = data;
5987 if (!mSystemReady) {
5988 return;
5989 }
5990 }
5991
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005992 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 }
5994
5995 private void retrieveSettings() {
5996 final ContentResolver resolver = mContext.getContentResolver();
5997 String debugApp = Settings.System.getString(
5998 resolver, Settings.System.DEBUG_APP);
5999 boolean waitForDebugger = Settings.System.getInt(
6000 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6001 boolean alwaysFinishActivities = Settings.System.getInt(
6002 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6003
6004 Configuration configuration = new Configuration();
6005 Settings.System.getConfiguration(resolver, configuration);
6006
6007 synchronized (this) {
6008 mDebugApp = mOrigDebugApp = debugApp;
6009 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6010 mAlwaysFinishActivities = alwaysFinishActivities;
6011 // This happens before any activities are started, so we can
6012 // change mConfiguration in-place.
6013 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006014 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006015 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006016 }
6017 }
6018
6019 public boolean testIsSystemReady() {
6020 // no need to synchronize(this) just to read & return the value
6021 return mSystemReady;
6022 }
6023
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006024 private static File getCalledPreBootReceiversFile() {
6025 File dataDir = Environment.getDataDirectory();
6026 File systemDir = new File(dataDir, "system");
6027 File fname = new File(systemDir, "called_pre_boots.dat");
6028 return fname;
6029 }
6030
6031 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6032 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6033 File file = getCalledPreBootReceiversFile();
6034 FileInputStream fis = null;
6035 try {
6036 fis = new FileInputStream(file);
6037 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6038 int vers = dis.readInt();
6039 String codename = dis.readUTF();
6040 if (vers == android.os.Build.VERSION.SDK_INT
6041 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6042 int num = dis.readInt();
6043 while (num > 0) {
6044 num--;
6045 String pkg = dis.readUTF();
6046 String cls = dis.readUTF();
6047 lastDoneReceivers.add(new ComponentName(pkg, cls));
6048 }
6049 }
6050 } catch (FileNotFoundException e) {
6051 } catch (IOException e) {
6052 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6053 } finally {
6054 if (fis != null) {
6055 try {
6056 fis.close();
6057 } catch (IOException e) {
6058 }
6059 }
6060 }
6061 return lastDoneReceivers;
6062 }
6063
6064 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6065 File file = getCalledPreBootReceiversFile();
6066 FileOutputStream fos = null;
6067 DataOutputStream dos = null;
6068 try {
6069 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6070 fos = new FileOutputStream(file);
6071 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6072 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6073 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6074 dos.writeInt(list.size());
6075 for (int i=0; i<list.size(); i++) {
6076 dos.writeUTF(list.get(i).getPackageName());
6077 dos.writeUTF(list.get(i).getClassName());
6078 }
6079 } catch (IOException e) {
6080 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6081 file.delete();
6082 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006083 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006084 if (dos != null) {
6085 try {
6086 dos.close();
6087 } catch (IOException e) {
6088 // TODO Auto-generated catch block
6089 e.printStackTrace();
6090 }
6091 }
6092 }
6093 }
6094
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006095 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006096 // In the simulator, startRunning will never have been called, which
6097 // normally sets a few crucial variables. Do it here instead.
6098 if (!Process.supportsProcesses()) {
6099 mStartRunning = true;
6100 mTopAction = Intent.ACTION_MAIN;
6101 }
6102
6103 synchronized(this) {
6104 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006105 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 return;
6107 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006108
6109 // Check to see if there are any update receivers to run.
6110 if (!mDidUpdate) {
6111 if (mWaitingUpdate) {
6112 return;
6113 }
6114 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6115 List<ResolveInfo> ris = null;
6116 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006117 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006118 intent, null, 0);
6119 } catch (RemoteException e) {
6120 }
6121 if (ris != null) {
6122 for (int i=ris.size()-1; i>=0; i--) {
6123 if ((ris.get(i).activityInfo.applicationInfo.flags
6124 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6125 ris.remove(i);
6126 }
6127 }
6128 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006129
6130 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6131
6132 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006133 for (int i=0; i<ris.size(); i++) {
6134 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006135 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6136 if (lastDoneReceivers.contains(comp)) {
6137 ris.remove(i);
6138 i--;
6139 }
6140 }
6141
6142 for (int i=0; i<ris.size(); i++) {
6143 ActivityInfo ai = ris.get(i).activityInfo;
6144 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6145 doneReceivers.add(comp);
6146 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006147 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006148 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006149 finisher = new IIntentReceiver.Stub() {
6150 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006151 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006152 boolean sticky) {
6153 // The raw IIntentReceiver interface is called
6154 // with the AM lock held, so redispatch to
6155 // execute our code without the lock.
6156 mHandler.post(new Runnable() {
6157 public void run() {
6158 synchronized (ActivityManagerService.this) {
6159 mDidUpdate = true;
6160 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006161 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006162 systemReady(goingCallback);
6163 }
6164 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006165 }
6166 };
6167 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006168 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006169 broadcastIntentLocked(null, null, intent, null, finisher,
6170 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006171 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006172 mWaitingUpdate = true;
6173 }
6174 }
6175 }
6176 if (mWaitingUpdate) {
6177 return;
6178 }
6179 mDidUpdate = true;
6180 }
6181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 mSystemReady = true;
6183 if (!mStartRunning) {
6184 return;
6185 }
6186 }
6187
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006188 ArrayList<ProcessRecord> procsToKill = null;
6189 synchronized(mPidsSelfLocked) {
6190 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6191 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6192 if (!isAllowedWhileBooting(proc.info)){
6193 if (procsToKill == null) {
6194 procsToKill = new ArrayList<ProcessRecord>();
6195 }
6196 procsToKill.add(proc);
6197 }
6198 }
6199 }
6200
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006201 synchronized(this) {
6202 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006203 for (int i=procsToKill.size()-1; i>=0; i--) {
6204 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006205 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006206 removeProcessLocked(proc, true);
6207 }
6208 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006209
6210 // Now that we have cleaned up any update processes, we
6211 // are ready to start launching real processes and know that
6212 // we won't trample on them any more.
6213 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006214 }
6215
Joe Onorato8a9b2202010-02-26 18:56:32 -08006216 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006217 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 SystemClock.uptimeMillis());
6219
6220 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006221 // Make sure we have no pre-ready processes sitting around.
6222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6224 ResolveInfo ri = mContext.getPackageManager()
6225 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006226 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 CharSequence errorMsg = null;
6228 if (ri != null) {
6229 ActivityInfo ai = ri.activityInfo;
6230 ApplicationInfo app = ai.applicationInfo;
6231 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6232 mTopAction = Intent.ACTION_FACTORY_TEST;
6233 mTopData = null;
6234 mTopComponent = new ComponentName(app.packageName,
6235 ai.name);
6236 } else {
6237 errorMsg = mContext.getResources().getText(
6238 com.android.internal.R.string.factorytest_not_system);
6239 }
6240 } else {
6241 errorMsg = mContext.getResources().getText(
6242 com.android.internal.R.string.factorytest_no_action);
6243 }
6244 if (errorMsg != null) {
6245 mTopAction = null;
6246 mTopData = null;
6247 mTopComponent = null;
6248 Message msg = Message.obtain();
6249 msg.what = SHOW_FACTORY_ERROR_MSG;
6250 msg.getData().putCharSequence("msg", errorMsg);
6251 mHandler.sendMessage(msg);
6252 }
6253 }
6254 }
6255
6256 retrieveSettings();
6257
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006258 if (goingCallback != null) goingCallback.run();
6259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 synchronized (this) {
6261 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6262 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006263 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006264 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 if (apps != null) {
6266 int N = apps.size();
6267 int i;
6268 for (i=0; i<N; i++) {
6269 ApplicationInfo info
6270 = (ApplicationInfo)apps.get(i);
6271 if (info != null &&
6272 !info.packageName.equals("android")) {
6273 addAppLocked(info);
6274 }
6275 }
6276 }
6277 } catch (RemoteException ex) {
6278 // pm is in same process, this will never happen.
6279 }
6280 }
6281
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006282 // Start up initial activity.
6283 mBooting = true;
6284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006286 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 Message msg = Message.obtain();
6288 msg.what = SHOW_UID_ERROR_MSG;
6289 mHandler.sendMessage(msg);
6290 }
6291 } catch (RemoteException e) {
6292 }
6293
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006294 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006295 }
6296 }
6297
Dan Egnorb7f03672009-12-09 16:22:32 -08006298 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006299 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006301 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006302 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006303 startAppProblemLocked(app);
6304 app.stopFreezingAllLocked();
6305 return handleAppCrashLocked(app);
6306 }
6307
Dan Egnorb7f03672009-12-09 16:22:32 -08006308 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006309 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006310 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006311 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006312 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6313 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 startAppProblemLocked(app);
6315 app.stopFreezingAllLocked();
6316 }
6317
6318 /**
6319 * Generate a process error record, suitable for attachment to a ProcessRecord.
6320 *
6321 * @param app The ProcessRecord in which the error occurred.
6322 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6323 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006324 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 * @param shortMsg Short message describing the crash.
6326 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006327 * @param stackTrace Full crash stack trace, may be null.
6328 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 * @return Returns a fully-formed AppErrorStateInfo record.
6330 */
6331 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006332 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006333 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 report.condition = condition;
6336 report.processName = app.processName;
6337 report.pid = app.pid;
6338 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006339 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006340 report.shortMsg = shortMsg;
6341 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006342 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006343
6344 return report;
6345 }
6346
Dan Egnor42471dd2010-01-07 17:25:22 -08006347 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 synchronized (this) {
6349 app.crashing = false;
6350 app.crashingReport = null;
6351 app.notResponding = false;
6352 app.notRespondingReport = null;
6353 if (app.anrDialog == fromDialog) {
6354 app.anrDialog = null;
6355 }
6356 if (app.waitDialog == fromDialog) {
6357 app.waitDialog = null;
6358 }
6359 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006360 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006361 Slog.i(ActivityManagerService.TAG, "Killing "
6362 + app.processName + " (pid=" + app.pid + "): user's request");
6363 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6364 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 Process.killProcess(app.pid);
6366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 }
6368 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006369
Dan Egnorb7f03672009-12-09 16:22:32 -08006370 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 long now = SystemClock.uptimeMillis();
6372
6373 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6374 app.info.uid);
6375 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6376 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006377 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006379 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 app.info.processName, app.info.uid);
6381 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006382 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6383 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006385 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006387 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 }
6389 }
6390 if (!app.persistent) {
6391 // We don't want to start this process again until the user
6392 // explicitly does so... but for persistent process, we really
6393 // need to keep it running. If a persistent process is actually
6394 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006395 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 app.info.processName);
6397 mBadProcesses.put(app.info.processName, app.info.uid, now);
6398 app.bad = true;
6399 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6400 app.removed = true;
6401 removeProcessLocked(app, false);
6402 return false;
6403 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006404 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006405 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006406 if (r.app == app) {
6407 // If the top running activity is from this crashing
6408 // process, then terminate it to avoid getting in a loop.
6409 Slog.w(TAG, " Force finishing activity "
6410 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006411 int index = mMainStack.indexOfTokenLocked(r);
6412 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006413 Activity.RESULT_CANCELED, null, "crashed");
6414 // Also terminate an activities below it that aren't yet
6415 // stopped, to avoid a situation where one will get
6416 // re-start our crashing activity once it gets resumed again.
6417 index--;
6418 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006419 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006420 if (r.state == ActivityState.RESUMED
6421 || r.state == ActivityState.PAUSING
6422 || r.state == ActivityState.PAUSED) {
6423 if (!r.isHomeActivity) {
6424 Slog.w(TAG, " Force finishing activity "
6425 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006426 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006427 Activity.RESULT_CANCELED, null, "crashed");
6428 }
6429 }
6430 }
6431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006432 }
6433
6434 // Bump up the crash count of any services currently running in the proc.
6435 if (app.services.size() != 0) {
6436 // Any services running in the application need to be placed
6437 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006438 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006440 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 sr.crashCount++;
6442 }
6443 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006444
6445 // If the crashing process is what we consider to be the "home process" and it has been
6446 // replaced by a third-party app, clear the package preferred activities from packages
6447 // with a home activity running in the process to prevent a repeatedly crashing app
6448 // from blocking the user to manually clear the list.
6449 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6450 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6451 Iterator it = mHomeProcess.activities.iterator();
6452 while (it.hasNext()) {
Jean-Baptiste Queru1ca94792010-07-30 09:30:31 -07006453 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006454 if (r.isHomeActivity) {
6455 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6456 try {
6457 ActivityThread.getPackageManager()
6458 .clearPackagePreferredActivities(r.packageName);
6459 } catch (RemoteException c) {
6460 // pm is in same process, this will never happen.
6461 }
6462 }
6463 }
6464 }
6465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6467 return true;
6468 }
6469
6470 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006471 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6472 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006473 skipCurrentReceiverLocked(app);
6474 }
6475
6476 void skipCurrentReceiverLocked(ProcessRecord app) {
6477 boolean reschedule = false;
6478 BroadcastRecord r = app.curReceiver;
6479 if (r != null) {
6480 // The current broadcast is waiting for this app's receiver
6481 // to be finished. Looks like that's not going to happen, so
6482 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006483 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6485 r.resultExtras, r.resultAbort, true);
6486 reschedule = true;
6487 }
6488 r = mPendingBroadcast;
6489 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006490 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006492 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6494 r.resultExtras, r.resultAbort, true);
6495 reschedule = true;
6496 }
6497 if (reschedule) {
6498 scheduleBroadcastsLocked();
6499 }
6500 }
6501
Dan Egnor60d87622009-12-16 16:32:58 -08006502 /**
6503 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6504 * The application process will exit immediately after this call returns.
6505 * @param app object of the crashing app, null for the system server
6506 * @param crashInfo describing the exception
6507 */
6508 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6509 ProcessRecord r = findAppProcess(app);
6510
6511 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6512 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006513 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006514 crashInfo.exceptionClassName,
6515 crashInfo.exceptionMessage,
6516 crashInfo.throwFileName,
6517 crashInfo.throwLineNumber);
6518
Dan Egnor42471dd2010-01-07 17:25:22 -08006519 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006520
6521 crashApplication(r, crashInfo);
6522 }
6523
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006524 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006525 IBinder app,
6526 int violationMask,
6527 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006528 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006529
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006530 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006531 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006532 boolean logIt = true;
6533 synchronized (mAlreadyLoggedViolatedStacks) {
6534 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6535 logIt = false;
6536 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006537 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006538 // the relative pain numbers, without logging all
6539 // the stack traces repeatedly. We'd want to do
6540 // likewise in the client code, which also does
6541 // dup suppression, before the Binder call.
6542 } else {
6543 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6544 mAlreadyLoggedViolatedStacks.clear();
6545 }
6546 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6547 }
6548 }
6549 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006550 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006551 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006552 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006553
6554 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6555 AppErrorResult result = new AppErrorResult();
6556 synchronized (this) {
6557 final long origId = Binder.clearCallingIdentity();
6558
6559 Message msg = Message.obtain();
6560 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6561 HashMap<String, Object> data = new HashMap<String, Object>();
6562 data.put("result", result);
6563 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006564 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006565 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006566 msg.obj = data;
6567 mHandler.sendMessage(msg);
6568
6569 Binder.restoreCallingIdentity(origId);
6570 }
6571 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006572 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006573 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006574 }
6575
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006576 // Depending on the policy in effect, there could be a bunch of
6577 // these in quick succession so we try to batch these together to
6578 // minimize disk writes, number of dropbox entries, and maximize
6579 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006580 private void logStrictModeViolationToDropBox(
6581 ProcessRecord process,
6582 StrictMode.ViolationInfo info) {
6583 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006584 return;
6585 }
6586 final boolean isSystemApp = process == null ||
6587 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6588 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6589 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6590 final DropBoxManager dbox = (DropBoxManager)
6591 mContext.getSystemService(Context.DROPBOX_SERVICE);
6592
6593 // Exit early if the dropbox isn't configured to accept this report type.
6594 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6595
6596 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006597 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006598 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6599 synchronized (sb) {
6600 bufferWasEmpty = sb.length() == 0;
6601 appendDropBoxProcessHeaders(process, sb);
6602 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6603 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006604 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6605 if (info.violationNumThisLoop != 0) {
6606 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6607 }
6608 if (info != null && info.durationMillis != -1) {
6609 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006610 }
6611 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006612 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6613 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006614 }
6615 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006616
6617 // Only buffer up to ~64k. Various logging bits truncate
6618 // things at 128k.
6619 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006620 }
6621
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006622 // Flush immediately if the buffer's grown too large, or this
6623 // is a non-system app. Non-system apps are isolated with a
6624 // different tag & policy and not batched.
6625 //
6626 // Batching is useful during internal testing with
6627 // StrictMode settings turned up high. Without batching,
6628 // thousands of separate files could be created on boot.
6629 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006630 new Thread("Error dump: " + dropboxTag) {
6631 @Override
6632 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006633 String report;
6634 synchronized (sb) {
6635 report = sb.toString();
6636 sb.delete(0, sb.length());
6637 sb.trimToSize();
6638 }
6639 if (report.length() != 0) {
6640 dbox.addText(dropboxTag, report);
6641 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006642 }
6643 }.start();
6644 return;
6645 }
6646
6647 // System app batching:
6648 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006649 // An existing dropbox-writing thread is outstanding, so
6650 // we don't need to start it up. The existing thread will
6651 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006652 return;
6653 }
6654
6655 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6656 // (After this point, we shouldn't access AMS internal data structures.)
6657 new Thread("Error dump: " + dropboxTag) {
6658 @Override
6659 public void run() {
6660 // 5 second sleep to let stacks arrive and be batched together
6661 try {
6662 Thread.sleep(5000); // 5 seconds
6663 } catch (InterruptedException e) {}
6664
6665 String errorReport;
6666 synchronized (mStrictModeBuffer) {
6667 errorReport = mStrictModeBuffer.toString();
6668 if (errorReport.length() == 0) {
6669 return;
6670 }
6671 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6672 mStrictModeBuffer.trimToSize();
6673 }
6674 dbox.addText(dropboxTag, errorReport);
6675 }
6676 }.start();
6677 }
6678
Dan Egnor60d87622009-12-16 16:32:58 -08006679 /**
6680 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6681 * @param app object of the crashing app, null for the system server
6682 * @param tag reported by the caller
6683 * @param crashInfo describing the context of the error
6684 * @return true if the process should exit immediately (WTF is fatal)
6685 */
6686 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006687 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006688 ProcessRecord r = findAppProcess(app);
6689
6690 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6691 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006692 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006693 tag, crashInfo.exceptionMessage);
6694
Dan Egnor42471dd2010-01-07 17:25:22 -08006695 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006696
Doug Zongker43866e02010-01-07 12:09:54 -08006697 if (Settings.Secure.getInt(mContext.getContentResolver(),
6698 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006699 crashApplication(r, crashInfo);
6700 return true;
6701 } else {
6702 return false;
6703 }
6704 }
6705
6706 /**
6707 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6708 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6709 */
6710 private ProcessRecord findAppProcess(IBinder app) {
6711 if (app == null) {
6712 return null;
6713 }
6714
6715 synchronized (this) {
6716 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6717 final int NA = apps.size();
6718 for (int ia=0; ia<NA; ia++) {
6719 ProcessRecord p = apps.valueAt(ia);
6720 if (p.thread != null && p.thread.asBinder() == app) {
6721 return p;
6722 }
6723 }
6724 }
6725
Joe Onorato8a9b2202010-02-26 18:56:32 -08006726 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006727 return null;
6728 }
6729 }
6730
6731 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006732 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6733 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006734 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006735 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6736 // Note: ProcessRecord 'process' is guarded by the service
6737 // instance. (notably process.pkgList, which could otherwise change
6738 // concurrently during execution of this method)
6739 synchronized (this) {
6740 if (process == null || process.pid == MY_PID) {
6741 sb.append("Process: system_server\n");
6742 } else {
6743 sb.append("Process: ").append(process.processName).append("\n");
6744 }
6745 if (process == null) {
6746 return;
6747 }
Dan Egnora455d192010-03-12 08:52:28 -08006748 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006749 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006750 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6751 for (String pkg : process.pkgList) {
6752 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006753 try {
Dan Egnora455d192010-03-12 08:52:28 -08006754 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6755 if (pi != null) {
6756 sb.append(" v").append(pi.versionCode);
6757 if (pi.versionName != null) {
6758 sb.append(" (").append(pi.versionName).append(")");
6759 }
6760 }
6761 } catch (RemoteException e) {
6762 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006763 }
Dan Egnora455d192010-03-12 08:52:28 -08006764 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006765 }
Dan Egnora455d192010-03-12 08:52:28 -08006766 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006767 }
6768
6769 private static String processClass(ProcessRecord process) {
6770 if (process == null || process.pid == MY_PID) {
6771 return "system_server";
6772 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6773 return "system_app";
6774 } else {
6775 return "data_app";
6776 }
6777 }
6778
6779 /**
6780 * Write a description of an error (crash, WTF, ANR) to the drop box.
6781 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6782 * @param process which caused the error, null means the system server
6783 * @param activity which triggered the error, null if unknown
6784 * @param parent activity related to the error, null if unknown
6785 * @param subject line related to the error, null if absent
6786 * @param report in long form describing the error, null if absent
6787 * @param logFile to include in the report, null if none
6788 * @param crashInfo giving an application stack trace, null if absent
6789 */
6790 public void addErrorToDropBox(String eventType,
6791 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6792 final String report, final File logFile,
6793 final ApplicationErrorReport.CrashInfo crashInfo) {
6794 // NOTE -- this must never acquire the ActivityManagerService lock,
6795 // otherwise the watchdog may be prevented from resetting the system.
6796
6797 final String dropboxTag = processClass(process) + "_" + eventType;
6798 final DropBoxManager dbox = (DropBoxManager)
6799 mContext.getSystemService(Context.DROPBOX_SERVICE);
6800
6801 // Exit early if the dropbox isn't configured to accept this report type.
6802 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6803
6804 final StringBuilder sb = new StringBuilder(1024);
6805 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006806 if (activity != null) {
6807 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6808 }
6809 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6810 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6811 }
6812 if (parent != null && parent != activity) {
6813 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6814 }
6815 if (subject != null) {
6816 sb.append("Subject: ").append(subject).append("\n");
6817 }
6818 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006819 if (Debug.isDebuggerConnected()) {
6820 sb.append("Debugger: Connected\n");
6821 }
Dan Egnora455d192010-03-12 08:52:28 -08006822 sb.append("\n");
6823
6824 // Do the rest in a worker thread to avoid blocking the caller on I/O
6825 // (After this point, we shouldn't access AMS internal data structures.)
6826 Thread worker = new Thread("Error dump: " + dropboxTag) {
6827 @Override
6828 public void run() {
6829 if (report != null) {
6830 sb.append(report);
6831 }
6832 if (logFile != null) {
6833 try {
6834 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6835 } catch (IOException e) {
6836 Slog.e(TAG, "Error reading " + logFile, e);
6837 }
6838 }
6839 if (crashInfo != null && crashInfo.stackTrace != null) {
6840 sb.append(crashInfo.stackTrace);
6841 }
6842
6843 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6844 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6845 if (lines > 0) {
6846 sb.append("\n");
6847
6848 // Merge several logcat streams, and take the last N lines
6849 InputStreamReader input = null;
6850 try {
6851 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6852 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6853 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6854
6855 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6856 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6857 input = new InputStreamReader(logcat.getInputStream());
6858
6859 int num;
6860 char[] buf = new char[8192];
6861 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6862 } catch (IOException e) {
6863 Slog.e(TAG, "Error running logcat", e);
6864 } finally {
6865 if (input != null) try { input.close(); } catch (IOException e) {}
6866 }
6867 }
6868
6869 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006870 }
Dan Egnora455d192010-03-12 08:52:28 -08006871 };
6872
6873 if (process == null || process.pid == MY_PID) {
6874 worker.run(); // We may be about to die -- need to run this synchronously
6875 } else {
6876 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006877 }
6878 }
6879
6880 /**
6881 * Bring up the "unexpected error" dialog box for a crashing app.
6882 * Deal with edge cases (intercepts from instrumented applications,
6883 * ActivityController, error intent receivers, that sort of thing).
6884 * @param r the application crashing
6885 * @param crashInfo describing the failure
6886 */
6887 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006888 long timeMillis = System.currentTimeMillis();
6889 String shortMsg = crashInfo.exceptionClassName;
6890 String longMsg = crashInfo.exceptionMessage;
6891 String stackTrace = crashInfo.stackTrace;
6892 if (shortMsg != null && longMsg != null) {
6893 longMsg = shortMsg + ": " + longMsg;
6894 } else if (shortMsg != null) {
6895 longMsg = shortMsg;
6896 }
6897
Dan Egnor60d87622009-12-16 16:32:58 -08006898 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006899 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006900 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006901 try {
6902 String name = r != null ? r.processName : null;
6903 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006904 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006905 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006906 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 + " at watcher's request");
6908 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006909 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 }
6911 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006912 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 }
6914 }
6915
6916 final long origId = Binder.clearCallingIdentity();
6917
6918 // If this process is running instrumentation, finish it.
6919 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006920 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006922 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6923 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 Bundle info = new Bundle();
6925 info.putString("shortMsg", shortMsg);
6926 info.putString("longMsg", longMsg);
6927 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6928 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006929 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 }
6931
Dan Egnor60d87622009-12-16 16:32:58 -08006932 // If we can't identify the process or it's already exceeded its crash quota,
6933 // quit right away without showing a crash dialog.
6934 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006936 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 }
6938
6939 Message msg = Message.obtain();
6940 msg.what = SHOW_ERROR_MSG;
6941 HashMap data = new HashMap();
6942 data.put("result", result);
6943 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006944 msg.obj = data;
6945 mHandler.sendMessage(msg);
6946
6947 Binder.restoreCallingIdentity(origId);
6948 }
6949
6950 int res = result.get();
6951
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006952 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006953 synchronized (this) {
6954 if (r != null) {
6955 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6956 SystemClock.uptimeMillis());
6957 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006958 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006959 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006960 }
6961 }
6962
6963 if (appErrorIntent != null) {
6964 try {
6965 mContext.startActivity(appErrorIntent);
6966 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006967 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006971
6972 Intent createAppErrorIntentLocked(ProcessRecord r,
6973 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6974 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006975 if (report == null) {
6976 return null;
6977 }
6978 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6979 result.setComponent(r.errorReportReceiver);
6980 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6981 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6982 return result;
6983 }
6984
Dan Egnorb7f03672009-12-09 16:22:32 -08006985 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6986 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006987 if (r.errorReportReceiver == null) {
6988 return null;
6989 }
6990
6991 if (!r.crashing && !r.notResponding) {
6992 return null;
6993 }
6994
Dan Egnorb7f03672009-12-09 16:22:32 -08006995 ApplicationErrorReport report = new ApplicationErrorReport();
6996 report.packageName = r.info.packageName;
6997 report.installerPackageName = r.errorReportReceiver.getPackageName();
6998 report.processName = r.processName;
6999 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007000 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007001
Dan Egnorb7f03672009-12-09 16:22:32 -08007002 if (r.crashing) {
7003 report.type = ApplicationErrorReport.TYPE_CRASH;
7004 report.crashInfo = crashInfo;
7005 } else if (r.notResponding) {
7006 report.type = ApplicationErrorReport.TYPE_ANR;
7007 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007008
Dan Egnorb7f03672009-12-09 16:22:32 -08007009 report.anrInfo.activity = r.notRespondingReport.tag;
7010 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7011 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007012 }
7013
Dan Egnorb7f03672009-12-09 16:22:32 -08007014 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007015 }
7016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007017 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7018 // assume our apps are happy - lazy create the list
7019 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7020
7021 synchronized (this) {
7022
7023 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007024 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7025 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7027 // This one's in trouble, so we'll generate a report for it
7028 // crashes are higher priority (in case there's a crash *and* an anr)
7029 ActivityManager.ProcessErrorStateInfo report = null;
7030 if (app.crashing) {
7031 report = app.crashingReport;
7032 } else if (app.notResponding) {
7033 report = app.notRespondingReport;
7034 }
7035
7036 if (report != null) {
7037 if (errList == null) {
7038 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7039 }
7040 errList.add(report);
7041 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007042 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043 " crashing = " + app.crashing +
7044 " notResponding = " + app.notResponding);
7045 }
7046 }
7047 }
7048 }
7049
7050 return errList;
7051 }
7052
7053 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7054 // Lazy instantiation of list
7055 List<ActivityManager.RunningAppProcessInfo> runList = null;
7056 synchronized (this) {
7057 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007058 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7059 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7061 // Generate process state info for running application
7062 ActivityManager.RunningAppProcessInfo currApp =
7063 new ActivityManager.RunningAppProcessInfo(app.processName,
7064 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007065 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007066 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007067 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007068 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007069 if (app.persistent) {
7070 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007073 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7075 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7076 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007077 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7078 } else if (adj >= HOME_APP_ADJ) {
7079 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7080 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007081 } else if (adj >= SECONDARY_SERVER_ADJ) {
7082 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007083 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007084 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007085 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7086 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087 } else if (adj >= VISIBLE_APP_ADJ) {
7088 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7089 } else {
7090 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7091 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007092 currApp.importanceReasonCode = app.adjTypeCode;
7093 if (app.adjSource instanceof ProcessRecord) {
7094 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007095 } else if (app.adjSource instanceof ActivityRecord) {
7096 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007097 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7098 }
7099 if (app.adjTarget instanceof ComponentName) {
7100 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7101 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007102 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 // + " lru=" + currApp.lru);
7104 if (runList == null) {
7105 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7106 }
7107 runList.add(currApp);
7108 }
7109 }
7110 }
7111 return runList;
7112 }
7113
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007114 public List<ApplicationInfo> getRunningExternalApplications() {
7115 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7116 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7117 if (runningApps != null && runningApps.size() > 0) {
7118 Set<String> extList = new HashSet<String>();
7119 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7120 if (app.pkgList != null) {
7121 for (String pkg : app.pkgList) {
7122 extList.add(pkg);
7123 }
7124 }
7125 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007126 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007127 for (String pkg : extList) {
7128 try {
7129 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7130 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7131 retList.add(info);
7132 }
7133 } catch (RemoteException e) {
7134 }
7135 }
7136 }
7137 return retList;
7138 }
7139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 @Override
7141 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007142 if (checkCallingPermission(android.Manifest.permission.DUMP)
7143 != PackageManager.PERMISSION_GRANTED) {
7144 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7145 + Binder.getCallingPid()
7146 + ", uid=" + Binder.getCallingUid()
7147 + " without permission "
7148 + android.Manifest.permission.DUMP);
7149 return;
7150 }
7151
7152 boolean dumpAll = false;
7153
7154 int opti = 0;
7155 while (opti < args.length) {
7156 String opt = args[opti];
7157 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7158 break;
7159 }
7160 opti++;
7161 if ("-a".equals(opt)) {
7162 dumpAll = true;
7163 } else if ("-h".equals(opt)) {
7164 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007165 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007166 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007167 pw.println(" a[ctivities]: activity stack state");
7168 pw.println(" b[roadcasts]: broadcast state");
7169 pw.println(" i[ntents]: pending intent state");
7170 pw.println(" p[rocesses]: process state");
7171 pw.println(" o[om]: out of memory management");
7172 pw.println(" prov[iders]: content provider state");
7173 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007174 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007176 } else {
7177 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007179 }
7180
7181 // Is the caller requesting to dump a particular piece of data?
7182 if (opti < args.length) {
7183 String cmd = args[opti];
7184 opti++;
7185 if ("activities".equals(cmd) || "a".equals(cmd)) {
7186 synchronized (this) {
7187 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007189 return;
7190 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7191 synchronized (this) {
7192 dumpBroadcastsLocked(fd, pw, args, opti, true);
7193 }
7194 return;
7195 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7196 synchronized (this) {
7197 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7198 }
7199 return;
7200 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7201 synchronized (this) {
7202 dumpProcessesLocked(fd, pw, args, opti, true);
7203 }
7204 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007205 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7206 synchronized (this) {
7207 dumpOomLocked(fd, pw, args, opti, true);
7208 }
7209 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007210 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7211 synchronized (this) {
7212 dumpProvidersLocked(fd, pw, args, opti, true);
7213 }
7214 return;
7215 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007216 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007217 return;
7218 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7219 synchronized (this) {
7220 dumpServicesLocked(fd, pw, args, opti, true);
7221 }
7222 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007223 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007224 }
7225
7226 // No piece of data specified, dump everything.
7227 synchronized (this) {
7228 boolean needSep;
7229 if (dumpAll) {
7230 pw.println("Providers in Current Activity Manager State:");
7231 }
7232 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7233 if (needSep) {
7234 pw.println(" ");
7235 }
7236 if (dumpAll) {
7237 pw.println("-------------------------------------------------------------------------------");
7238 pw.println("Broadcasts in Current Activity Manager State:");
7239 }
7240 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7241 if (needSep) {
7242 pw.println(" ");
7243 }
7244 if (dumpAll) {
7245 pw.println("-------------------------------------------------------------------------------");
7246 pw.println("Services in Current Activity Manager State:");
7247 }
7248 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7249 if (needSep) {
7250 pw.println(" ");
7251 }
7252 if (dumpAll) {
7253 pw.println("-------------------------------------------------------------------------------");
7254 pw.println("PendingIntents in Current Activity Manager State:");
7255 }
7256 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7257 if (needSep) {
7258 pw.println(" ");
7259 }
7260 if (dumpAll) {
7261 pw.println("-------------------------------------------------------------------------------");
7262 pw.println("Activities in Current Activity Manager State:");
7263 }
7264 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7265 if (needSep) {
7266 pw.println(" ");
7267 }
7268 if (dumpAll) {
7269 pw.println("-------------------------------------------------------------------------------");
7270 pw.println("Processes in Current Activity Manager State:");
7271 }
7272 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7273 }
7274 }
7275
7276 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7277 int opti, boolean dumpAll, boolean needHeader) {
7278 if (needHeader) {
7279 pw.println(" Activity stack:");
7280 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007281 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007282 pw.println(" ");
7283 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007284 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7285 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007286 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007287 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007288 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007289 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007290 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007292 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007293 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007294 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007295 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 pw.println(" ");
7297 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007298 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007301 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007302 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7303 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007304 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007305 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007307 if (dumpAll && mRecentTasks.size() > 0) {
7308 pw.println(" ");
7309 pw.println("Recent tasks in Current Activity Manager State:");
7310
7311 final int N = mRecentTasks.size();
7312 for (int i=0; i<N; i++) {
7313 TaskRecord tr = mRecentTasks.get(i);
7314 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7315 pw.println(tr);
7316 mRecentTasks.get(i).dump(pw, " ");
7317 }
7318 }
7319
7320 pw.println(" ");
7321 pw.println(" mCurTask: " + mCurTask);
7322
7323 return true;
7324 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007325
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007326 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7327 int opti, boolean dumpAll) {
7328 boolean needSep = false;
7329 int numPers = 0;
7330
7331 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007332 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7333 final int NA = procs.size();
7334 for (int ia=0; ia<NA; ia++) {
7335 if (!needSep) {
7336 pw.println(" All known processes:");
7337 needSep = true;
7338 }
7339 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007340 pw.print(r.persistent ? " *PERS*" : " *APP*");
7341 pw.print(" UID "); pw.print(procs.keyAt(ia));
7342 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007343 r.dump(pw, " ");
7344 if (r.persistent) {
7345 numPers++;
7346 }
7347 }
7348 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007349 }
7350
7351 if (mLruProcesses.size() > 0) {
7352 if (needSep) pw.println(" ");
7353 needSep = true;
7354 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007355 dumpProcessOomList(pw, this, mLruProcesses, " ",
7356 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007357 needSep = true;
7358 }
7359
7360 synchronized (mPidsSelfLocked) {
7361 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 if (needSep) pw.println(" ");
7363 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 pw.println(" PID mappings:");
7365 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7366 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7367 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 }
7369 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007370 }
7371
7372 if (mForegroundProcesses.size() > 0) {
7373 if (needSep) pw.println(" ");
7374 needSep = true;
7375 pw.println(" Foreground Processes:");
7376 for (int i=0; i<mForegroundProcesses.size(); i++) {
7377 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7378 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007380 }
7381
7382 if (mPersistentStartingProcesses.size() > 0) {
7383 if (needSep) pw.println(" ");
7384 needSep = true;
7385 pw.println(" Persisent processes that are starting:");
7386 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007387 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390 if (mStartingProcesses.size() > 0) {
7391 if (needSep) pw.println(" ");
7392 needSep = true;
7393 pw.println(" Processes that are starting:");
7394 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007395 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007398 if (mRemovedProcesses.size() > 0) {
7399 if (needSep) pw.println(" ");
7400 needSep = true;
7401 pw.println(" Processes that are being removed:");
7402 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007403 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 }
7405
7406 if (mProcessesOnHold.size() > 0) {
7407 if (needSep) pw.println(" ");
7408 needSep = true;
7409 pw.println(" Processes that are on old until the system is ready:");
7410 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007411 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413
Dianne Hackborn287952c2010-09-22 22:34:31 -07007414 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007415
7416 if (mProcessCrashTimes.getMap().size() > 0) {
7417 if (needSep) pw.println(" ");
7418 needSep = true;
7419 pw.println(" Time since processes crashed:");
7420 long now = SystemClock.uptimeMillis();
7421 for (Map.Entry<String, SparseArray<Long>> procs
7422 : mProcessCrashTimes.getMap().entrySet()) {
7423 SparseArray<Long> uids = procs.getValue();
7424 final int N = uids.size();
7425 for (int i=0; i<N; i++) {
7426 pw.print(" Process "); pw.print(procs.getKey());
7427 pw.print(" uid "); pw.print(uids.keyAt(i));
7428 pw.print(": last crashed ");
7429 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007430 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007431 }
7432 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007435 if (mBadProcesses.getMap().size() > 0) {
7436 if (needSep) pw.println(" ");
7437 needSep = true;
7438 pw.println(" Bad processes:");
7439 for (Map.Entry<String, SparseArray<Long>> procs
7440 : mBadProcesses.getMap().entrySet()) {
7441 SparseArray<Long> uids = procs.getValue();
7442 final int N = uids.size();
7443 for (int i=0; i<N; i++) {
7444 pw.print(" Bad process "); pw.print(procs.getKey());
7445 pw.print(" uid "); pw.print(uids.keyAt(i));
7446 pw.print(": crashed at time ");
7447 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 }
7449 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007452 pw.println(" ");
7453 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007454 if (mHeavyWeightProcess != null) {
7455 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7456 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007457 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007458 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007459 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7460 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7461 || mOrigWaitForDebugger) {
7462 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7463 + " mDebugTransient=" + mDebugTransient
7464 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7465 }
7466 if (mAlwaysFinishActivities || mController != null) {
7467 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7468 + " mController=" + mController);
7469 }
7470 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007473 + " mProcessesReady=" + mProcessesReady
7474 + " mSystemReady=" + mSystemReady);
7475 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 + " mBooted=" + mBooted
7477 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007478 pw.print(" mLastPowerCheckRealtime=");
7479 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7480 pw.println("");
7481 pw.print(" mLastPowerCheckUptime=");
7482 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7483 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007484 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7485 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007486 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007488
7489 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007490 }
7491
Dianne Hackborn287952c2010-09-22 22:34:31 -07007492 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7493 int opti, boolean needSep, boolean dumpAll) {
7494 if (mProcessesToGc.size() > 0) {
7495 if (needSep) pw.println(" ");
7496 needSep = true;
7497 pw.println(" Processes that are waiting to GC:");
7498 long now = SystemClock.uptimeMillis();
7499 for (int i=0; i<mProcessesToGc.size(); i++) {
7500 ProcessRecord proc = mProcessesToGc.get(i);
7501 pw.print(" Process "); pw.println(proc);
7502 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7503 pw.print(", last gced=");
7504 pw.print(now-proc.lastRequestedGc);
7505 pw.print(" ms ago, last lowMem=");
7506 pw.print(now-proc.lastLowMemory);
7507 pw.println(" ms ago");
7508
7509 }
7510 }
7511 return needSep;
7512 }
7513
7514 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7515 int opti, boolean dumpAll) {
7516 boolean needSep = false;
7517
7518 if (mLruProcesses.size() > 0) {
7519 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7520
7521 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7522 @Override
7523 public int compare(ProcessRecord object1, ProcessRecord object2) {
7524 if (object1.setAdj != object2.setAdj) {
7525 return object1.setAdj > object2.setAdj ? -1 : 1;
7526 }
7527 if (object1.setSchedGroup != object2.setSchedGroup) {
7528 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7529 }
7530 if (object1.keeping != object2.keeping) {
7531 return object1.keeping ? -1 : 1;
7532 }
7533 if (object1.pid != object2.pid) {
7534 return object1.pid > object2.pid ? -1 : 1;
7535 }
7536 return 0;
7537 }
7538 };
7539
7540 Collections.sort(procs, comparator);
7541
7542 if (needSep) pw.println(" ");
7543 needSep = true;
7544 pw.println(" Process OOM control:");
7545 dumpProcessOomList(pw, this, procs, " ",
7546 "Proc", "PERS", true);
7547 needSep = true;
7548 }
7549
7550 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7551
7552 pw.println(" ");
7553 pw.println(" mHomeProcess: " + mHomeProcess);
7554 if (mHeavyWeightProcess != null) {
7555 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7556 }
7557
7558 return true;
7559 }
7560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 /**
7562 * There are three ways to call this:
7563 * - no service specified: dump all the services
7564 * - a flattened component name that matched an existing service was specified as the
7565 * first arg: dump that one service
7566 * - the first arg isn't the flattened component name of an existing service:
7567 * dump all services whose component contains the first arg as a substring
7568 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7570 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 String[] newArgs;
7572 String componentNameString;
7573 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007574 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 componentNameString = null;
7576 newArgs = EMPTY_STRING_ARRAY;
7577 r = null;
7578 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007579 componentNameString = args[opti];
7580 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007582 synchronized (this) {
7583 r = componentName != null ? mServices.get(componentName) : null;
7584 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007585 newArgs = new String[args.length - opti];
7586 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 }
7588
7589 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007590 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007592 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7593 synchronized (this) {
7594 for (ServiceRecord r1 : mServices.values()) {
7595 if (componentNameString == null
7596 || r1.name.flattenToString().contains(componentNameString)) {
7597 services.add(r1);
7598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 }
7600 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007601 for (int i=0; i<services.size(); i++) {
7602 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 }
7605 }
7606
7607 /**
7608 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7609 * there is a thread associated with the service.
7610 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007611 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7612 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007614 if (dumpAll) {
7615 synchronized (this) {
7616 pw.print(" * "); pw.println(r);
7617 r.dump(pw, " ");
7618 }
7619 pw.println("");
7620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007621 if (r.app != null && r.app.thread != null) {
7622 try {
7623 // flush anything that is already in the PrintWriter since the thread is going
7624 // to write to the file descriptor directly
7625 pw.flush();
7626 r.app.thread.dumpService(fd, r, args);
7627 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007628 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 } catch (RemoteException e) {
7630 pw.println("got a RemoteException while dumping the service");
7631 }
7632 }
7633 }
7634
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007635 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7636 int opti, boolean dumpAll) {
7637 boolean needSep = false;
7638
7639 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007640 if (mRegisteredReceivers.size() > 0) {
7641 pw.println(" ");
7642 pw.println(" Registered Receivers:");
7643 Iterator it = mRegisteredReceivers.values().iterator();
7644 while (it.hasNext()) {
7645 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007646 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647 r.dump(pw, " ");
7648 }
7649 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007651 pw.println(" ");
7652 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007653 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007654 needSep = true;
7655 }
7656
7657 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7658 || mPendingBroadcast != null) {
7659 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007663 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7664 pw.println(" Broadcast #" + i + ":");
7665 mParallelBroadcasts.get(i).dump(pw, " ");
7666 }
7667 if (mOrderedBroadcasts.size() > 0) {
7668 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007669 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007670 }
7671 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7672 pw.println(" Serialized Broadcast #" + i + ":");
7673 mOrderedBroadcasts.get(i).dump(pw, " ");
7674 }
7675 pw.println(" ");
7676 pw.println(" Pending broadcast:");
7677 if (mPendingBroadcast != null) {
7678 mPendingBroadcast.dump(pw, " ");
7679 } else {
7680 pw.println(" (null)");
7681 }
7682 needSep = true;
7683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007685 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007686 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007687 pw.println(" Historical broadcasts:");
7688 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7689 BroadcastRecord r = mBroadcastHistory[i];
7690 if (r == null) {
7691 break;
7692 }
7693 pw.println(" Historical Broadcast #" + i + ":");
7694 r.dump(pw, " ");
7695 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007696 needSep = true;
7697 }
7698
7699 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007700 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007701 pw.println(" Sticky broadcasts:");
7702 StringBuilder sb = new StringBuilder(128);
7703 for (Map.Entry<String, ArrayList<Intent>> ent
7704 : mStickyBroadcasts.entrySet()) {
7705 pw.print(" * Sticky action "); pw.print(ent.getKey());
7706 pw.println(":");
7707 ArrayList<Intent> intents = ent.getValue();
7708 final int N = intents.size();
7709 for (int i=0; i<N; i++) {
7710 sb.setLength(0);
7711 sb.append(" Intent: ");
7712 intents.get(i).toShortString(sb, true, false);
7713 pw.println(sb.toString());
7714 Bundle bundle = intents.get(i).getExtras();
7715 if (bundle != null) {
7716 pw.print(" ");
7717 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 }
7719 }
7720 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007721 needSep = true;
7722 }
7723
7724 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007726 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727 pw.println(" mHandler:");
7728 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007731
7732 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 }
7734
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007735 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7736 int opti, boolean dumpAll) {
7737 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007738
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007739 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 if (mServices.size() > 0) {
7741 pw.println(" Active services:");
7742 Iterator<ServiceRecord> it = mServices.values().iterator();
7743 while (it.hasNext()) {
7744 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007745 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 r.dump(pw, " ");
7747 }
7748 needSep = true;
7749 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007752 if (mPendingServices.size() > 0) {
7753 if (needSep) pw.println(" ");
7754 pw.println(" Pending services:");
7755 for (int i=0; i<mPendingServices.size(); i++) {
7756 ServiceRecord r = mPendingServices.get(i);
7757 pw.print(" * Pending "); pw.println(r);
7758 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007759 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007760 needSep = true;
7761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007763 if (mRestartingServices.size() > 0) {
7764 if (needSep) pw.println(" ");
7765 pw.println(" Restarting services:");
7766 for (int i=0; i<mRestartingServices.size(); i++) {
7767 ServiceRecord r = mRestartingServices.get(i);
7768 pw.print(" * Restarting "); pw.println(r);
7769 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007770 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007771 needSep = true;
7772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007774 if (mStoppingServices.size() > 0) {
7775 if (needSep) pw.println(" ");
7776 pw.println(" Stopping services:");
7777 for (int i=0; i<mStoppingServices.size(); i++) {
7778 ServiceRecord r = mStoppingServices.get(i);
7779 pw.print(" * Stopping "); pw.println(r);
7780 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007782 needSep = true;
7783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007784
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007785 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 if (mServiceConnections.size() > 0) {
7787 if (needSep) pw.println(" ");
7788 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007789 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 = mServiceConnections.values().iterator();
7791 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007792 ArrayList<ConnectionRecord> r = it.next();
7793 for (int i=0; i<r.size(); i++) {
7794 pw.print(" * "); pw.println(r.get(i));
7795 r.get(i).dump(pw, " ");
7796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007798 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 }
7800 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007801
7802 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 }
7804
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007805 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7806 int opti, boolean dumpAll) {
7807 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007809 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 if (mProvidersByClass.size() > 0) {
7811 if (needSep) pw.println(" ");
7812 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007813 Iterator<Map.Entry<String, ContentProviderRecord>> it
7814 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007816 Map.Entry<String, ContentProviderRecord> e = it.next();
7817 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007818 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 r.dump(pw, " ");
7820 }
7821 needSep = true;
7822 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007823
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007824 if (mProvidersByName.size() > 0) {
7825 pw.println(" ");
7826 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007827 Iterator<Map.Entry<String, ContentProviderRecord>> it
7828 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007829 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007830 Map.Entry<String, ContentProviderRecord> e = it.next();
7831 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007832 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7833 pw.println(r);
7834 }
7835 needSep = true;
7836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007838
7839 if (mLaunchingProviders.size() > 0) {
7840 if (needSep) pw.println(" ");
7841 pw.println(" Launching content providers:");
7842 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7843 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7844 pw.println(mLaunchingProviders.get(i));
7845 }
7846 needSep = true;
7847 }
7848
7849 if (mGrantedUriPermissions.size() > 0) {
7850 pw.println();
7851 pw.println("Granted Uri Permissions:");
7852 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7853 int uid = mGrantedUriPermissions.keyAt(i);
7854 HashMap<Uri, UriPermission> perms
7855 = mGrantedUriPermissions.valueAt(i);
7856 pw.print(" * UID "); pw.print(uid);
7857 pw.println(" holds:");
7858 for (UriPermission perm : perms.values()) {
7859 pw.print(" "); pw.println(perm);
7860 perm.dump(pw, " ");
7861 }
7862 }
7863 needSep = true;
7864 }
7865
7866 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
7868
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007869 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7870 int opti, boolean dumpAll) {
7871 boolean needSep = false;
7872
7873 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 if (this.mIntentSenderRecords.size() > 0) {
7875 Iterator<WeakReference<PendingIntentRecord>> it
7876 = mIntentSenderRecords.values().iterator();
7877 while (it.hasNext()) {
7878 WeakReference<PendingIntentRecord> ref = it.next();
7879 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007880 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007882 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 rec.dump(pw, " ");
7884 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007885 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 }
7887 }
7888 }
7889 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007890
7891 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
7893
7894 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007895 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 TaskRecord lastTask = null;
7897 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007898 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007899 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 if (lastTask != r.task) {
7901 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007902 pw.print(prefix);
7903 pw.print(full ? "* " : " ");
7904 pw.println(lastTask);
7905 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007906 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007909 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7910 pw.print(" #"); pw.print(i); pw.print(": ");
7911 pw.println(r);
7912 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007913 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 }
7916 }
7917
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007918 private static String buildOomTag(String prefix, String space, int val, int base) {
7919 if (val == base) {
7920 if (space == null) return prefix;
7921 return prefix + " ";
7922 }
7923 return prefix + "+" + Integer.toString(val-base);
7924 }
7925
7926 private static final int dumpProcessList(PrintWriter pw,
7927 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007928 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007930 final int N = list.size()-1;
7931 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007933 pw.println(String.format("%s%s #%2d: %s",
7934 prefix, (r.persistent ? persistentLabel : normalLabel),
7935 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 if (r.persistent) {
7937 numPers++;
7938 }
7939 }
7940 return numPers;
7941 }
7942
Dianne Hackborn287952c2010-09-22 22:34:31 -07007943 private static final void dumpProcessOomList(PrintWriter pw,
7944 ActivityManagerService service, List<ProcessRecord> list,
7945 String prefix, String normalLabel, String persistentLabel,
7946 boolean inclDetails) {
7947
7948 final long curRealtime = SystemClock.elapsedRealtime();
7949 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7950 final long curUptime = SystemClock.uptimeMillis();
7951 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7952
7953 final int N = list.size()-1;
7954 for (int i=N; i>=0; i--) {
7955 ProcessRecord r = list.get(i);
7956 String oomAdj;
7957 if (r.setAdj >= EMPTY_APP_ADJ) {
7958 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7959 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7960 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7961 } else if (r.setAdj >= HOME_APP_ADJ) {
7962 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7963 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7964 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7965 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7966 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7967 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7968 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7969 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7970 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7971 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7972 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7973 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7974 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7975 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7976 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7977 } else if (r.setAdj >= SYSTEM_ADJ) {
7978 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7979 } else {
7980 oomAdj = Integer.toString(r.setAdj);
7981 }
7982 String schedGroup;
7983 switch (r.setSchedGroup) {
7984 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7985 schedGroup = "B";
7986 break;
7987 case Process.THREAD_GROUP_DEFAULT:
7988 schedGroup = "F";
7989 break;
7990 default:
7991 schedGroup = Integer.toString(r.setSchedGroup);
7992 break;
7993 }
7994 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7995 prefix, (r.persistent ? persistentLabel : normalLabel),
7996 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
7997 if (r.adjSource != null || r.adjTarget != null) {
7998 pw.print(prefix);
7999 pw.print(" ");
8000 if (r.adjTarget instanceof ComponentName) {
8001 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8002 } else if (r.adjTarget != null) {
8003 pw.print(r.adjTarget.toString());
8004 } else {
8005 pw.print("{null}");
8006 }
8007 pw.print("<=");
8008 if (r.adjSource instanceof ProcessRecord) {
8009 pw.print("Proc{");
8010 pw.print(((ProcessRecord)r.adjSource).toShortString());
8011 pw.println("}");
8012 } else if (r.adjSource != null) {
8013 pw.println(r.adjSource.toString());
8014 } else {
8015 pw.println("{null}");
8016 }
8017 }
8018 if (inclDetails) {
8019 pw.print(prefix);
8020 pw.print(" ");
8021 pw.print("oom: max="); pw.print(r.maxAdj);
8022 pw.print(" hidden="); pw.print(r.hiddenAdj);
8023 pw.print(" curRaw="); pw.print(r.curRawAdj);
8024 pw.print(" setRaw="); pw.print(r.setRawAdj);
8025 pw.print(" cur="); pw.print(r.curAdj);
8026 pw.print(" set="); pw.println(r.setAdj);
8027 pw.print(prefix);
8028 pw.print(" ");
8029 pw.print("keeping="); pw.print(r.keeping);
8030 pw.print(" hidden="); pw.print(r.hidden);
8031 pw.print(" empty="); pw.println(r.empty);
8032
8033 if (!r.keeping) {
8034 if (r.lastWakeTime != 0) {
8035 long wtime;
8036 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8037 synchronized (stats) {
8038 wtime = stats.getProcessWakeTime(r.info.uid,
8039 r.pid, curRealtime);
8040 }
8041 long timeUsed = wtime - r.lastWakeTime;
8042 pw.print(prefix);
8043 pw.print(" ");
8044 pw.print("keep awake over ");
8045 TimeUtils.formatDuration(realtimeSince, pw);
8046 pw.print(" used ");
8047 TimeUtils.formatDuration(timeUsed, pw);
8048 pw.print(" (");
8049 pw.print((timeUsed*100)/realtimeSince);
8050 pw.println("%)");
8051 }
8052 if (r.lastCpuTime != 0) {
8053 long timeUsed = r.curCpuTime - r.lastCpuTime;
8054 pw.print(prefix);
8055 pw.print(" ");
8056 pw.print("run cpu over ");
8057 TimeUtils.formatDuration(uptimeSince, pw);
8058 pw.print(" used ");
8059 TimeUtils.formatDuration(timeUsed, pw);
8060 pw.print(" (");
8061 pw.print((timeUsed*100)/uptimeSince);
8062 pw.println("%)");
8063 }
8064 }
8065 }
8066 }
8067 }
8068
Dianne Hackborn472ad872010-04-07 17:31:48 -07008069 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008071 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 long uptime = SystemClock.uptimeMillis();
8073 long realtime = SystemClock.elapsedRealtime();
8074
8075 if (isCheckinRequest) {
8076 // short checkin version
8077 pw.println(uptime + "," + realtime);
8078 pw.flush();
8079 } else {
8080 pw.println("Applications Memory Usage (kB):");
8081 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8082 }
8083 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8084 ProcessRecord r = (ProcessRecord)list.get(i);
8085 if (r.thread != null) {
8086 if (!isCheckinRequest) {
8087 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8088 pw.flush();
8089 }
8090 try {
8091 r.thread.asBinder().dump(fd, args);
8092 } catch (RemoteException e) {
8093 if (!isCheckinRequest) {
8094 pw.println("Got RemoteException!");
8095 pw.flush();
8096 }
8097 }
8098 }
8099 }
8100 }
8101
8102 /**
8103 * Searches array of arguments for the specified string
8104 * @param args array of argument strings
8105 * @param value value to search for
8106 * @return true if the value is contained in the array
8107 */
8108 private static boolean scanArgs(String[] args, String value) {
8109 if (args != null) {
8110 for (String arg : args) {
8111 if (value.equals(arg)) {
8112 return true;
8113 }
8114 }
8115 }
8116 return false;
8117 }
8118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 private final void killServicesLocked(ProcessRecord app,
8120 boolean allowRestart) {
8121 // Report disconnected services.
8122 if (false) {
8123 // XXX we are letting the client link to the service for
8124 // death notifications.
8125 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008126 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008128 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008129 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008130 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 = r.connections.values().iterator();
8132 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008133 ArrayList<ConnectionRecord> cl = jt.next();
8134 for (int i=0; i<cl.size(); i++) {
8135 ConnectionRecord c = cl.get(i);
8136 if (c.binding.client != app) {
8137 try {
8138 //c.conn.connected(r.className, null);
8139 } catch (Exception e) {
8140 // todo: this should be asynchronous!
8141 Slog.w(TAG, "Exception thrown disconnected servce "
8142 + r.shortName
8143 + " from app " + app.processName, e);
8144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 }
8146 }
8147 }
8148 }
8149 }
8150 }
8151 }
8152
8153 // Clean up any connections this application has to other services.
8154 if (app.connections.size() > 0) {
8155 Iterator<ConnectionRecord> it = app.connections.iterator();
8156 while (it.hasNext()) {
8157 ConnectionRecord r = it.next();
8158 removeConnectionLocked(r, app, null);
8159 }
8160 }
8161 app.connections.clear();
8162
8163 if (app.services.size() != 0) {
8164 // Any services running in the application need to be placed
8165 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008166 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008168 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008169 synchronized (sr.stats.getBatteryStats()) {
8170 sr.stats.stopLaunchedLocked();
8171 }
8172 sr.app = null;
8173 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008174 if (mStoppingServices.remove(sr)) {
8175 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8176 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008177
8178 boolean hasClients = sr.bindings.size() > 0;
8179 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 Iterator<IntentBindRecord> bindings
8181 = sr.bindings.values().iterator();
8182 while (bindings.hasNext()) {
8183 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008184 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 + ": shouldUnbind=" + b.hasBound);
8186 b.binder = null;
8187 b.requested = b.received = b.hasBound = false;
8188 }
8189 }
8190
8191 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008192 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008194 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 sr.crashCount, sr.shortName, app.pid);
8196 bringDownServiceLocked(sr, true);
8197 } else if (!allowRestart) {
8198 bringDownServiceLocked(sr, true);
8199 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008200 boolean canceled = scheduleServiceRestartLocked(sr, true);
8201
8202 // Should the service remain running? Note that in the
8203 // extreme case of so many attempts to deliver a command
8204 // that it failed, that we also will stop it here.
8205 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8206 if (sr.pendingStarts.size() == 0) {
8207 sr.startRequested = false;
8208 if (!hasClients) {
8209 // Whoops, no reason to restart!
8210 bringDownServiceLocked(sr, true);
8211 }
8212 }
8213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008214 }
8215 }
8216
8217 if (!allowRestart) {
8218 app.services.clear();
8219 }
8220 }
8221
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008222 // Make sure we have no more records on the stopping list.
8223 int i = mStoppingServices.size();
8224 while (i > 0) {
8225 i--;
8226 ServiceRecord sr = mStoppingServices.get(i);
8227 if (sr.app == app) {
8228 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008229 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008230 }
8231 }
8232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008233 app.executingServices.clear();
8234 }
8235
8236 private final void removeDyingProviderLocked(ProcessRecord proc,
8237 ContentProviderRecord cpr) {
8238 synchronized (cpr) {
8239 cpr.launchingApp = null;
8240 cpr.notifyAll();
8241 }
8242
8243 mProvidersByClass.remove(cpr.info.name);
8244 String names[] = cpr.info.authority.split(";");
8245 for (int j = 0; j < names.length; j++) {
8246 mProvidersByName.remove(names[j]);
8247 }
8248
8249 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8250 while (cit.hasNext()) {
8251 ProcessRecord capp = cit.next();
8252 if (!capp.persistent && capp.thread != null
8253 && capp.pid != 0
8254 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008255 Slog.i(TAG, "Kill " + capp.processName
8256 + " (pid " + capp.pid + "): provider " + cpr.info.name
8257 + " in dying process " + proc.processName);
8258 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8259 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 Process.killProcess(capp.pid);
8261 }
8262 }
8263
8264 mLaunchingProviders.remove(cpr);
8265 }
8266
8267 /**
8268 * Main code for cleaning up a process when it has gone away. This is
8269 * called both as a result of the process dying, or directly when stopping
8270 * a process when running in single process mode.
8271 */
8272 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8273 boolean restarting, int index) {
8274 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008275 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008276 }
8277
Dianne Hackborn36124872009-10-08 16:22:03 -07008278 mProcessesToGc.remove(app);
8279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 // Dismiss any open dialogs.
8281 if (app.crashDialog != null) {
8282 app.crashDialog.dismiss();
8283 app.crashDialog = null;
8284 }
8285 if (app.anrDialog != null) {
8286 app.anrDialog.dismiss();
8287 app.anrDialog = null;
8288 }
8289 if (app.waitDialog != null) {
8290 app.waitDialog.dismiss();
8291 app.waitDialog = null;
8292 }
8293
8294 app.crashing = false;
8295 app.notResponding = false;
8296
8297 app.resetPackageList();
8298 app.thread = null;
8299 app.forcingToForeground = null;
8300 app.foregroundServices = false;
8301
8302 killServicesLocked(app, true);
8303
8304 boolean restart = false;
8305
8306 int NL = mLaunchingProviders.size();
8307
8308 // Remove published content providers.
8309 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008310 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008312 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 cpr.provider = null;
8314 cpr.app = null;
8315
8316 // See if someone is waiting for this provider... in which
8317 // case we don't remove it, but just let it restart.
8318 int i = 0;
8319 if (!app.bad) {
8320 for (; i<NL; i++) {
8321 if (mLaunchingProviders.get(i) == cpr) {
8322 restart = true;
8323 break;
8324 }
8325 }
8326 } else {
8327 i = NL;
8328 }
8329
8330 if (i >= NL) {
8331 removeDyingProviderLocked(app, cpr);
8332 NL = mLaunchingProviders.size();
8333 }
8334 }
8335 app.pubProviders.clear();
8336 }
8337
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008338 // Take care of any launching providers waiting for this process.
8339 if (checkAppInLaunchingProvidersLocked(app, false)) {
8340 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 // Unregister from connected content providers.
8344 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008345 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 while (it.hasNext()) {
8347 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8348 cpr.clients.remove(app);
8349 }
8350 app.conProviders.clear();
8351 }
8352
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008353 // At this point there may be remaining entries in mLaunchingProviders
8354 // where we were the only one waiting, so they are no longer of use.
8355 // Look for these and clean up if found.
8356 // XXX Commented out for now. Trying to figure out a way to reproduce
8357 // the actual situation to identify what is actually going on.
8358 if (false) {
8359 for (int i=0; i<NL; i++) {
8360 ContentProviderRecord cpr = (ContentProviderRecord)
8361 mLaunchingProviders.get(i);
8362 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8363 synchronized (cpr) {
8364 cpr.launchingApp = null;
8365 cpr.notifyAll();
8366 }
8367 }
8368 }
8369 }
8370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008371 skipCurrentReceiverLocked(app);
8372
8373 // Unregister any receivers.
8374 if (app.receivers.size() > 0) {
8375 Iterator<ReceiverList> it = app.receivers.iterator();
8376 while (it.hasNext()) {
8377 removeReceiverLocked(it.next());
8378 }
8379 app.receivers.clear();
8380 }
8381
Christopher Tate181fafa2009-05-14 11:12:14 -07008382 // If the app is undergoing backup, tell the backup manager about it
8383 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008384 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008385 try {
8386 IBackupManager bm = IBackupManager.Stub.asInterface(
8387 ServiceManager.getService(Context.BACKUP_SERVICE));
8388 bm.agentDisconnected(app.info.packageName);
8389 } catch (RemoteException e) {
8390 // can't happen; backup manager is local
8391 }
8392 }
8393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 // If the caller is restarting this app, then leave it in its
8395 // current lists and let the caller take care of it.
8396 if (restarting) {
8397 return;
8398 }
8399
8400 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008401 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008402 "Removing non-persistent process during cleanup: " + app);
8403 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008404 if (mHeavyWeightProcess == app) {
8405 mHeavyWeightProcess = null;
8406 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 } else if (!app.removed) {
8409 // This app is persistent, so we need to keep its record around.
8410 // If it is not already on the pending app list, add it there
8411 // and start a new process for it.
8412 app.thread = null;
8413 app.forcingToForeground = null;
8414 app.foregroundServices = false;
8415 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8416 mPersistentStartingProcesses.add(app);
8417 restart = true;
8418 }
8419 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008420 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8421 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 mProcessesOnHold.remove(app);
8423
The Android Open Source Project4df24232009-03-05 14:34:35 -08008424 if (app == mHomeProcess) {
8425 mHomeProcess = null;
8426 }
8427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 if (restart) {
8429 // We have components that still need to be running in the
8430 // process, so re-launch it.
8431 mProcessNames.put(app.processName, app.info.uid, app);
8432 startProcessLocked(app, "restart", app.processName);
8433 } else if (app.pid > 0 && app.pid != MY_PID) {
8434 // Goodbye!
8435 synchronized (mPidsSelfLocked) {
8436 mPidsSelfLocked.remove(app.pid);
8437 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8438 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008439 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008440 }
8441 }
8442
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008443 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8444 // Look through the content providers we are waiting to have launched,
8445 // and if any run in this process then either schedule a restart of
8446 // the process or kill the client waiting for it if this process has
8447 // gone bad.
8448 int NL = mLaunchingProviders.size();
8449 boolean restart = false;
8450 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008451 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008452 if (cpr.launchingApp == app) {
8453 if (!alwaysBad && !app.bad) {
8454 restart = true;
8455 } else {
8456 removeDyingProviderLocked(app, cpr);
8457 NL = mLaunchingProviders.size();
8458 }
8459 }
8460 }
8461 return restart;
8462 }
8463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464 // =========================================================
8465 // SERVICES
8466 // =========================================================
8467
8468 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8469 ActivityManager.RunningServiceInfo info =
8470 new ActivityManager.RunningServiceInfo();
8471 info.service = r.name;
8472 if (r.app != null) {
8473 info.pid = r.app.pid;
8474 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008475 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008476 info.process = r.processName;
8477 info.foreground = r.isForeground;
8478 info.activeSince = r.createTime;
8479 info.started = r.startRequested;
8480 info.clientCount = r.connections.size();
8481 info.crashCount = r.crashCount;
8482 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008483 if (r.isForeground) {
8484 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8485 }
8486 if (r.startRequested) {
8487 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8488 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008489 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008490 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8491 }
8492 if (r.app != null && r.app.persistent) {
8493 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8494 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008495
8496 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8497 for (int i=0; i<connl.size(); i++) {
8498 ConnectionRecord conn = connl.get(i);
8499 if (conn.clientLabel != 0) {
8500 info.clientPackage = conn.binding.client.info.packageName;
8501 info.clientLabel = conn.clientLabel;
8502 return info;
8503 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008504 }
8505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 return info;
8507 }
8508
8509 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8510 int flags) {
8511 synchronized (this) {
8512 ArrayList<ActivityManager.RunningServiceInfo> res
8513 = new ArrayList<ActivityManager.RunningServiceInfo>();
8514
8515 if (mServices.size() > 0) {
8516 Iterator<ServiceRecord> it = mServices.values().iterator();
8517 while (it.hasNext() && res.size() < maxNum) {
8518 res.add(makeRunningServiceInfoLocked(it.next()));
8519 }
8520 }
8521
8522 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8523 ServiceRecord r = mRestartingServices.get(i);
8524 ActivityManager.RunningServiceInfo info =
8525 makeRunningServiceInfoLocked(r);
8526 info.restarting = r.nextRestartTime;
8527 res.add(info);
8528 }
8529
8530 return res;
8531 }
8532 }
8533
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008534 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8535 synchronized (this) {
8536 ServiceRecord r = mServices.get(name);
8537 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008538 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8539 for (int i=0; i<conn.size(); i++) {
8540 if (conn.get(i).clientIntent != null) {
8541 return conn.get(i).clientIntent;
8542 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008543 }
8544 }
8545 }
8546 }
8547 return null;
8548 }
8549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 private final ServiceRecord findServiceLocked(ComponentName name,
8551 IBinder token) {
8552 ServiceRecord r = mServices.get(name);
8553 return r == token ? r : null;
8554 }
8555
8556 private final class ServiceLookupResult {
8557 final ServiceRecord record;
8558 final String permission;
8559
8560 ServiceLookupResult(ServiceRecord _record, String _permission) {
8561 record = _record;
8562 permission = _permission;
8563 }
8564 };
8565
8566 private ServiceLookupResult findServiceLocked(Intent service,
8567 String resolvedType) {
8568 ServiceRecord r = null;
8569 if (service.getComponent() != null) {
8570 r = mServices.get(service.getComponent());
8571 }
8572 if (r == null) {
8573 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8574 r = mServicesByIntent.get(filter);
8575 }
8576
8577 if (r == null) {
8578 try {
8579 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008580 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008581 service, resolvedType, 0);
8582 ServiceInfo sInfo =
8583 rInfo != null ? rInfo.serviceInfo : null;
8584 if (sInfo == null) {
8585 return null;
8586 }
8587
8588 ComponentName name = new ComponentName(
8589 sInfo.applicationInfo.packageName, sInfo.name);
8590 r = mServices.get(name);
8591 } catch (RemoteException ex) {
8592 // pm is in same process, this will never happen.
8593 }
8594 }
8595 if (r != null) {
8596 int callingPid = Binder.getCallingPid();
8597 int callingUid = Binder.getCallingUid();
8598 if (checkComponentPermission(r.permission,
8599 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8600 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008601 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008602 + " from pid=" + callingPid
8603 + ", uid=" + callingUid
8604 + " requires " + r.permission);
8605 return new ServiceLookupResult(null, r.permission);
8606 }
8607 return new ServiceLookupResult(r, null);
8608 }
8609 return null;
8610 }
8611
8612 private class ServiceRestarter implements Runnable {
8613 private ServiceRecord mService;
8614
8615 void setService(ServiceRecord service) {
8616 mService = service;
8617 }
8618
8619 public void run() {
8620 synchronized(ActivityManagerService.this) {
8621 performServiceRestartLocked(mService);
8622 }
8623 }
8624 }
8625
8626 private ServiceLookupResult retrieveServiceLocked(Intent service,
8627 String resolvedType, int callingPid, int callingUid) {
8628 ServiceRecord r = null;
8629 if (service.getComponent() != null) {
8630 r = mServices.get(service.getComponent());
8631 }
8632 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8633 r = mServicesByIntent.get(filter);
8634 if (r == null) {
8635 try {
8636 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008637 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008638 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 ServiceInfo sInfo =
8640 rInfo != null ? rInfo.serviceInfo : null;
8641 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008642 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 ": not found");
8644 return null;
8645 }
8646
8647 ComponentName name = new ComponentName(
8648 sInfo.applicationInfo.packageName, sInfo.name);
8649 r = mServices.get(name);
8650 if (r == null) {
8651 filter = new Intent.FilterComparison(service.cloneFilter());
8652 ServiceRestarter res = new ServiceRestarter();
8653 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8654 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8655 synchronized (stats) {
8656 ss = stats.getServiceStatsLocked(
8657 sInfo.applicationInfo.uid, sInfo.packageName,
8658 sInfo.name);
8659 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008660 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008661 res.setService(r);
8662 mServices.put(name, r);
8663 mServicesByIntent.put(filter, r);
8664
8665 // Make sure this component isn't in the pending list.
8666 int N = mPendingServices.size();
8667 for (int i=0; i<N; i++) {
8668 ServiceRecord pr = mPendingServices.get(i);
8669 if (pr.name.equals(name)) {
8670 mPendingServices.remove(i);
8671 i--;
8672 N--;
8673 }
8674 }
8675 }
8676 } catch (RemoteException ex) {
8677 // pm is in same process, this will never happen.
8678 }
8679 }
8680 if (r != null) {
8681 if (checkComponentPermission(r.permission,
8682 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8683 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008684 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008685 + " from pid=" + Binder.getCallingPid()
8686 + ", uid=" + Binder.getCallingUid()
8687 + " requires " + r.permission);
8688 return new ServiceLookupResult(null, r.permission);
8689 }
8690 return new ServiceLookupResult(r, null);
8691 }
8692 return null;
8693 }
8694
Dianne Hackborn287952c2010-09-22 22:34:31 -07008695 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8696 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8697 + why + " of " + r + " in app " + r.app);
8698 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8699 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008700 long now = SystemClock.uptimeMillis();
8701 if (r.executeNesting == 0 && r.app != null) {
8702 if (r.app.executingServices.size() == 0) {
8703 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8704 msg.obj = r.app;
8705 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8706 }
8707 r.app.executingServices.add(r);
8708 }
8709 r.executeNesting++;
8710 r.executingStart = now;
8711 }
8712
8713 private final void sendServiceArgsLocked(ServiceRecord r,
8714 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008715 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 if (N == 0) {
8717 return;
8718 }
8719
Dianne Hackborn39792d22010-08-19 18:01:52 -07008720 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008722 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008723 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8724 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008725 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008726 // If somehow we got a dummy start at the front, then
8727 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008728 continue;
8729 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008730 si.deliveredTime = SystemClock.uptimeMillis();
8731 r.deliveredStarts.add(si);
8732 si.deliveryCount++;
8733 if (si.targetPermissionUid >= 0) {
8734 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008735 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008736 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008737 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 if (!oomAdjusted) {
8739 oomAdjusted = true;
8740 updateOomAdjLocked(r.app);
8741 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008742 int flags = 0;
8743 if (si.deliveryCount > 0) {
8744 flags |= Service.START_FLAG_RETRY;
8745 }
8746 if (si.doneExecutingCount > 0) {
8747 flags |= Service.START_FLAG_REDELIVERY;
8748 }
8749 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008750 } catch (RemoteException e) {
8751 // Remote process gone... we'll let the normal cleanup take
8752 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008753 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008754 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008755 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008756 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 break;
8758 }
8759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008760 }
8761
8762 private final boolean requestServiceBindingLocked(ServiceRecord r,
8763 IntentBindRecord i, boolean rebind) {
8764 if (r.app == null || r.app.thread == null) {
8765 // If service is not currently running, can't yet bind.
8766 return false;
8767 }
8768 if ((!i.requested || rebind) && i.apps.size() > 0) {
8769 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008770 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8772 if (!rebind) {
8773 i.requested = true;
8774 }
8775 i.hasBound = true;
8776 i.doRebind = false;
8777 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008778 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 return false;
8780 }
8781 }
8782 return true;
8783 }
8784
8785 private final void requestServiceBindingsLocked(ServiceRecord r) {
8786 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8787 while (bindings.hasNext()) {
8788 IntentBindRecord i = bindings.next();
8789 if (!requestServiceBindingLocked(r, i, false)) {
8790 break;
8791 }
8792 }
8793 }
8794
8795 private final void realStartServiceLocked(ServiceRecord r,
8796 ProcessRecord app) throws RemoteException {
8797 if (app.thread == null) {
8798 throw new RemoteException();
8799 }
8800
8801 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008802 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803
8804 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008805 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008806 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807
8808 boolean created = false;
8809 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008810 mStringBuilder.setLength(0);
8811 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008812 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008814 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008815 synchronized (r.stats.getBatteryStats()) {
8816 r.stats.startLaunchedLocked();
8817 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008818 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008820 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 created = true;
8822 } finally {
8823 if (!created) {
8824 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008825 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008826 }
8827 }
8828
8829 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008830
8831 // If the service is in the started state, and there are no
8832 // pending arguments, then fake up one so its onStartCommand() will
8833 // be called.
8834 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8835 r.lastStartId++;
8836 if (r.lastStartId < 1) {
8837 r.lastStartId = 1;
8838 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008839 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008840 }
8841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008842 sendServiceArgsLocked(r, true);
8843 }
8844
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008845 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8846 boolean allowCancel) {
8847 boolean canceled = false;
8848
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008849 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008850 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008851 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008852
8853 // Any delivered but not yet finished starts should be put back
8854 // on the pending list.
8855 final int N = r.deliveredStarts.size();
8856 if (N > 0) {
8857 for (int i=N-1; i>=0; i--) {
8858 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008859 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008860 if (si.intent == null) {
8861 // We'll generate this again if needed.
8862 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8863 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8864 r.pendingStarts.add(0, si);
8865 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8866 dur *= 2;
8867 if (minDuration < dur) minDuration = dur;
8868 if (resetTime < dur) resetTime = dur;
8869 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008870 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008871 + r.name);
8872 canceled = true;
8873 }
8874 }
8875 r.deliveredStarts.clear();
8876 }
8877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008878 r.totalRestartCount++;
8879 if (r.restartDelay == 0) {
8880 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008881 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008882 } else {
8883 // If it has been a "reasonably long time" since the service
8884 // was started, then reset our restart duration back to
8885 // the beginning, so we don't infinitely increase the duration
8886 // on a service that just occasionally gets killed (which is
8887 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008888 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008889 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008890 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008891 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008892 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008893 if (r.restartDelay < minDuration) {
8894 r.restartDelay = minDuration;
8895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008896 }
8897 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008898
8899 r.nextRestartTime = now + r.restartDelay;
8900
8901 // Make sure that we don't end up restarting a bunch of services
8902 // all at the same time.
8903 boolean repeat;
8904 do {
8905 repeat = false;
8906 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8907 ServiceRecord r2 = mRestartingServices.get(i);
8908 if (r2 != r && r.nextRestartTime
8909 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8910 && r.nextRestartTime
8911 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8912 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8913 r.restartDelay = r.nextRestartTime - now;
8914 repeat = true;
8915 break;
8916 }
8917 }
8918 } while (repeat);
8919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 if (!mRestartingServices.contains(r)) {
8921 mRestartingServices.add(r);
8922 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008923
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008924 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008927 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008929 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008931 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 r.shortName, r.restartDelay);
8933
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008934 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 }
8936
8937 final void performServiceRestartLocked(ServiceRecord r) {
8938 if (!mRestartingServices.contains(r)) {
8939 return;
8940 }
8941 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8942 }
8943
8944 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8945 if (r.restartDelay == 0) {
8946 return false;
8947 }
8948 r.resetRestartCounter();
8949 mRestartingServices.remove(r);
8950 mHandler.removeCallbacks(r.restarter);
8951 return true;
8952 }
8953
8954 private final boolean bringUpServiceLocked(ServiceRecord r,
8955 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008956 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 //r.dump(" ");
8958
Dianne Hackborn36124872009-10-08 16:22:03 -07008959 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960 sendServiceArgsLocked(r, false);
8961 return true;
8962 }
8963
8964 if (!whileRestarting && r.restartDelay > 0) {
8965 // If waiting for a restart, then do nothing.
8966 return true;
8967 }
8968
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008969 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008971 // We are now bringing the service up, so no longer in the
8972 // restarting state.
8973 mRestartingServices.remove(r);
8974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 final String appName = r.processName;
8976 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8977 if (app != null && app.thread != null) {
8978 try {
8979 realStartServiceLocked(r, app);
8980 return true;
8981 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008982 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 }
8984
8985 // If a dead object exception was thrown -- fall through to
8986 // restart the application.
8987 }
8988
Dianne Hackborn36124872009-10-08 16:22:03 -07008989 // Not running -- get it started, and enqueue this service record
8990 // to be executed when the app comes up.
8991 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8992 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008993 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008994 + r.appInfo.packageName + "/"
8995 + r.appInfo.uid + " for service "
8996 + r.intent.getIntent() + ": process is bad");
8997 bringDownServiceLocked(r, true);
8998 return false;
8999 }
9000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 mPendingServices.add(r);
9003 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 return true;
9006 }
9007
9008 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009009 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010 //r.dump(" ");
9011
9012 // Does it still need to run?
9013 if (!force && r.startRequested) {
9014 return;
9015 }
9016 if (r.connections.size() > 0) {
9017 if (!force) {
9018 // XXX should probably keep a count of the number of auto-create
9019 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009020 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009021 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009022 ArrayList<ConnectionRecord> cr = it.next();
9023 for (int i=0; i<cr.size(); i++) {
9024 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9025 return;
9026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 }
9028 }
9029 }
9030
9031 // Report to all of the connections that the service is no longer
9032 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009033 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009035 ArrayList<ConnectionRecord> c = it.next();
9036 for (int i=0; i<c.size(); i++) {
9037 try {
9038 c.get(i).conn.connected(r.name, null);
9039 } catch (Exception e) {
9040 Slog.w(TAG, "Failure disconnecting service " + r.name +
9041 " to connection " + c.get(i).conn.asBinder() +
9042 " (in " + c.get(i).binding.client.processName + ")", e);
9043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 }
9045 }
9046 }
9047
9048 // Tell the service that it has been unbound.
9049 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9050 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9051 while (it.hasNext()) {
9052 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009053 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 + ": hasBound=" + ibr.hasBound);
9055 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9056 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009057 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 updateOomAdjLocked(r.app);
9059 ibr.hasBound = false;
9060 r.app.thread.scheduleUnbindService(r,
9061 ibr.intent.getIntent());
9062 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009063 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009064 + r.shortName, e);
9065 serviceDoneExecutingLocked(r, true);
9066 }
9067 }
9068 }
9069 }
9070
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009071 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009072 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 System.identityHashCode(r), r.shortName,
9074 (r.app != null) ? r.app.pid : -1);
9075
9076 mServices.remove(r.name);
9077 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009078 r.totalRestartCount = 0;
9079 unscheduleServiceRestartLocked(r);
9080
9081 // Also make sure it is not on the pending list.
9082 int N = mPendingServices.size();
9083 for (int i=0; i<N; i++) {
9084 if (mPendingServices.get(i) == r) {
9085 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009086 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 i--;
9088 N--;
9089 }
9090 }
9091
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009092 r.cancelNotification();
9093 r.isForeground = false;
9094 r.foregroundId = 0;
9095 r.foregroundNoti = null;
9096
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009097 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009098 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009099 r.pendingStarts.clear();
9100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 if (r.app != null) {
9102 synchronized (r.stats.getBatteryStats()) {
9103 r.stats.stopLaunchedLocked();
9104 }
9105 r.app.services.remove(r);
9106 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009108 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 mStoppingServices.add(r);
9110 updateOomAdjLocked(r.app);
9111 r.app.thread.scheduleStopService(r);
9112 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009113 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 + r.shortName, e);
9115 serviceDoneExecutingLocked(r, true);
9116 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009117 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009119 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009120 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 }
9122 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009123 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009124 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 }
Vairavan Srinivasan50b9b942010-12-23 13:51:48 -08009126
9127 if (r.bindings.size() > 0) {
9128 r.bindings.clear();
9129 }
9130
9131 if (r.restarter instanceof ServiceRestarter) {
9132 ((ServiceRestarter)r.restarter).setService(null);
9133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 }
9135
9136 ComponentName startServiceLocked(IApplicationThread caller,
9137 Intent service, String resolvedType,
9138 int callingPid, int callingUid) {
9139 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009140 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141 + " type=" + resolvedType + " args=" + service.getExtras());
9142
9143 if (caller != null) {
9144 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9145 if (callerApp == null) {
9146 throw new SecurityException(
9147 "Unable to find app for caller " + caller
9148 + " (pid=" + Binder.getCallingPid()
9149 + ") when starting service " + service);
9150 }
9151 }
9152
9153 ServiceLookupResult res =
9154 retrieveServiceLocked(service, resolvedType,
9155 callingPid, callingUid);
9156 if (res == null) {
9157 return null;
9158 }
9159 if (res.record == null) {
9160 return new ComponentName("!", res.permission != null
9161 ? res.permission : "private to package");
9162 }
9163 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009164 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9165 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009166 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009167 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168 }
9169 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009170 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171 r.lastStartId++;
9172 if (r.lastStartId < 1) {
9173 r.lastStartId = 1;
9174 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009175 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9176 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 r.lastActivity = SystemClock.uptimeMillis();
9178 synchronized (r.stats.getBatteryStats()) {
9179 r.stats.startRunningLocked();
9180 }
9181 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9182 return new ComponentName("!", "Service process is bad");
9183 }
9184 return r.name;
9185 }
9186 }
9187
9188 public ComponentName startService(IApplicationThread caller, Intent service,
9189 String resolvedType) {
9190 // Refuse possible leaked file descriptors
9191 if (service != null && service.hasFileDescriptors() == true) {
9192 throw new IllegalArgumentException("File descriptors passed in Intent");
9193 }
9194
9195 synchronized(this) {
9196 final int callingPid = Binder.getCallingPid();
9197 final int callingUid = Binder.getCallingUid();
9198 final long origId = Binder.clearCallingIdentity();
9199 ComponentName res = startServiceLocked(caller, service,
9200 resolvedType, callingPid, callingUid);
9201 Binder.restoreCallingIdentity(origId);
9202 return res;
9203 }
9204 }
9205
9206 ComponentName startServiceInPackage(int uid,
9207 Intent service, String resolvedType) {
9208 synchronized(this) {
9209 final long origId = Binder.clearCallingIdentity();
9210 ComponentName res = startServiceLocked(null, service,
9211 resolvedType, -1, uid);
9212 Binder.restoreCallingIdentity(origId);
9213 return res;
9214 }
9215 }
9216
9217 public int stopService(IApplicationThread caller, Intent service,
9218 String resolvedType) {
9219 // Refuse possible leaked file descriptors
9220 if (service != null && service.hasFileDescriptors() == true) {
9221 throw new IllegalArgumentException("File descriptors passed in Intent");
9222 }
9223
9224 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009225 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 + " type=" + resolvedType);
9227
9228 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9229 if (caller != null && callerApp == null) {
9230 throw new SecurityException(
9231 "Unable to find app for caller " + caller
9232 + " (pid=" + Binder.getCallingPid()
9233 + ") when stopping service " + service);
9234 }
9235
9236 // If this service is active, make sure it is stopped.
9237 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9238 if (r != null) {
9239 if (r.record != null) {
9240 synchronized (r.record.stats.getBatteryStats()) {
9241 r.record.stats.stopRunningLocked();
9242 }
9243 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009244 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 final long origId = Binder.clearCallingIdentity();
9246 bringDownServiceLocked(r.record, false);
9247 Binder.restoreCallingIdentity(origId);
9248 return 1;
9249 }
9250 return -1;
9251 }
9252 }
9253
9254 return 0;
9255 }
9256
9257 public IBinder peekService(Intent service, String resolvedType) {
9258 // Refuse possible leaked file descriptors
9259 if (service != null && service.hasFileDescriptors() == true) {
9260 throw new IllegalArgumentException("File descriptors passed in Intent");
9261 }
9262
9263 IBinder ret = null;
9264
9265 synchronized(this) {
9266 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9267
9268 if (r != null) {
9269 // r.record is null if findServiceLocked() failed the caller permission check
9270 if (r.record == null) {
9271 throw new SecurityException(
9272 "Permission Denial: Accessing service " + r.record.name
9273 + " from pid=" + Binder.getCallingPid()
9274 + ", uid=" + Binder.getCallingUid()
9275 + " requires " + r.permission);
9276 }
9277 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9278 if (ib != null) {
9279 ret = ib.binder;
9280 }
9281 }
9282 }
9283
9284 return ret;
9285 }
9286
9287 public boolean stopServiceToken(ComponentName className, IBinder token,
9288 int startId) {
9289 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009290 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 + " " + token + " startId=" + startId);
9292 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009293 if (r != null) {
9294 if (startId >= 0) {
9295 // Asked to only stop if done with all work. Note that
9296 // to avoid leaks, we will take this as dropping all
9297 // start items up to and including this one.
9298 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9299 if (si != null) {
9300 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009301 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9302 cur.removeUriPermissionsLocked();
9303 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009304 break;
9305 }
9306 }
9307 }
9308
9309 if (r.lastStartId != startId) {
9310 return false;
9311 }
9312
9313 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009314 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009315 + " is last, but have " + r.deliveredStarts.size()
9316 + " remaining args");
9317 }
9318 }
9319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 synchronized (r.stats.getBatteryStats()) {
9321 r.stats.stopRunningLocked();
9322 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009323 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 }
9325 final long origId = Binder.clearCallingIdentity();
9326 bringDownServiceLocked(r, false);
9327 Binder.restoreCallingIdentity(origId);
9328 return true;
9329 }
9330 }
9331 return false;
9332 }
9333
9334 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009335 int id, Notification notification, boolean removeNotification) {
9336 final long origId = Binder.clearCallingIdentity();
9337 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 synchronized(this) {
9339 ServiceRecord r = findServiceLocked(className, token);
9340 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009341 if (id != 0) {
9342 if (notification == null) {
9343 throw new IllegalArgumentException("null notification");
9344 }
9345 if (r.foregroundId != id) {
9346 r.cancelNotification();
9347 r.foregroundId = id;
9348 }
9349 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9350 r.foregroundNoti = notification;
9351 r.isForeground = true;
9352 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009353 if (r.app != null) {
9354 updateServiceForegroundLocked(r.app, true);
9355 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009356 } else {
9357 if (r.isForeground) {
9358 r.isForeground = false;
9359 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009360 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009361 updateServiceForegroundLocked(r.app, true);
9362 }
9363 }
9364 if (removeNotification) {
9365 r.cancelNotification();
9366 r.foregroundId = 0;
9367 r.foregroundNoti = null;
9368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 }
9370 }
9371 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009372 } finally {
9373 Binder.restoreCallingIdentity(origId);
9374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 }
9376
9377 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9378 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009379 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009380 if (sr.isForeground) {
9381 anyForeground = true;
9382 break;
9383 }
9384 }
9385 if (anyForeground != proc.foregroundServices) {
9386 proc.foregroundServices = anyForeground;
9387 if (oomAdj) {
9388 updateOomAdjLocked();
9389 }
9390 }
9391 }
9392
9393 public int bindService(IApplicationThread caller, IBinder token,
9394 Intent service, String resolvedType,
9395 IServiceConnection connection, int flags) {
9396 // Refuse possible leaked file descriptors
9397 if (service != null && service.hasFileDescriptors() == true) {
9398 throw new IllegalArgumentException("File descriptors passed in Intent");
9399 }
9400
9401 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009402 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403 + " type=" + resolvedType + " conn=" + connection.asBinder()
9404 + " flags=0x" + Integer.toHexString(flags));
9405 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9406 if (callerApp == null) {
9407 throw new SecurityException(
9408 "Unable to find app for caller " + caller
9409 + " (pid=" + Binder.getCallingPid()
9410 + ") when binding service " + service);
9411 }
9412
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009413 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009414 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009415 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009417 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009418 return 0;
9419 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009420 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 }
9422
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009423 int clientLabel = 0;
9424 PendingIntent clientIntent = null;
9425
9426 if (callerApp.info.uid == Process.SYSTEM_UID) {
9427 // Hacky kind of thing -- allow system stuff to tell us
9428 // what they are, so we can report this elsewhere for
9429 // others to know why certain services are running.
9430 try {
9431 clientIntent = (PendingIntent)service.getParcelableExtra(
9432 Intent.EXTRA_CLIENT_INTENT);
9433 } catch (RuntimeException e) {
9434 }
9435 if (clientIntent != null) {
9436 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9437 if (clientLabel != 0) {
9438 // There are no useful extras in the intent, trash them.
9439 // System code calling with this stuff just needs to know
9440 // this will happen.
9441 service = service.cloneFilter();
9442 }
9443 }
9444 }
9445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 ServiceLookupResult res =
9447 retrieveServiceLocked(service, resolvedType,
9448 Binder.getCallingPid(), Binder.getCallingUid());
9449 if (res == null) {
9450 return 0;
9451 }
9452 if (res.record == null) {
9453 return -1;
9454 }
9455 ServiceRecord s = res.record;
9456
9457 final long origId = Binder.clearCallingIdentity();
9458
9459 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009460 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009461 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 }
9463
9464 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9465 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009466 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009467
9468 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009469 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9470 if (clist == null) {
9471 clist = new ArrayList<ConnectionRecord>();
9472 s.connections.put(binder, clist);
9473 }
9474 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 b.connections.add(c);
9476 if (activity != null) {
9477 if (activity.connections == null) {
9478 activity.connections = new HashSet<ConnectionRecord>();
9479 }
9480 activity.connections.add(c);
9481 }
9482 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009483 clist = mServiceConnections.get(binder);
9484 if (clist == null) {
9485 clist = new ArrayList<ConnectionRecord>();
9486 mServiceConnections.put(binder, clist);
9487 }
9488 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489
9490 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9491 s.lastActivity = SystemClock.uptimeMillis();
9492 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9493 return 0;
9494 }
9495 }
9496
9497 if (s.app != null) {
9498 // This could have made the service more important.
9499 updateOomAdjLocked(s.app);
9500 }
9501
Joe Onorato8a9b2202010-02-26 18:56:32 -08009502 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 + ": received=" + b.intent.received
9504 + " apps=" + b.intent.apps.size()
9505 + " doRebind=" + b.intent.doRebind);
9506
9507 if (s.app != null && b.intent.received) {
9508 // Service is already running, so we can immediately
9509 // publish the connection.
9510 try {
9511 c.conn.connected(s.name, b.intent.binder);
9512 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009513 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009514 + " to connection " + c.conn.asBinder()
9515 + " (in " + c.binding.client.processName + ")", e);
9516 }
9517
9518 // If this is the first app connected back to this binding,
9519 // and the service had previously asked to be told when
9520 // rebound, then do so.
9521 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9522 requestServiceBindingLocked(s, b.intent, true);
9523 }
9524 } else if (!b.intent.requested) {
9525 requestServiceBindingLocked(s, b.intent, false);
9526 }
9527
9528 Binder.restoreCallingIdentity(origId);
9529 }
9530
9531 return 1;
9532 }
9533
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009534 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009535 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009536 IBinder binder = c.conn.asBinder();
9537 AppBindRecord b = c.binding;
9538 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009539 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9540 if (clist != null) {
9541 clist.remove(c);
9542 if (clist.size() == 0) {
9543 s.connections.remove(binder);
9544 }
9545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009546 b.connections.remove(c);
9547 if (c.activity != null && c.activity != skipAct) {
9548 if (c.activity.connections != null) {
9549 c.activity.connections.remove(c);
9550 }
9551 }
9552 if (b.client != skipApp) {
9553 b.client.connections.remove(c);
9554 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009555 clist = mServiceConnections.get(binder);
9556 if (clist != null) {
9557 clist.remove(c);
9558 if (clist.size() == 0) {
9559 mServiceConnections.remove(binder);
9560 }
9561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562
9563 if (b.connections.size() == 0) {
9564 b.intent.apps.remove(b.client);
9565 }
9566
Joe Onorato8a9b2202010-02-26 18:56:32 -08009567 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 + ": shouldUnbind=" + b.intent.hasBound);
9569 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9570 && b.intent.hasBound) {
9571 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009572 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 updateOomAdjLocked(s.app);
9574 b.intent.hasBound = false;
9575 // Assume the client doesn't want to know about a rebind;
9576 // we will deal with that later if it asks for one.
9577 b.intent.doRebind = false;
9578 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9579 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009580 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009581 serviceDoneExecutingLocked(s, true);
9582 }
9583 }
9584
9585 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9586 bringDownServiceLocked(s, false);
9587 }
9588 }
9589
9590 public boolean unbindService(IServiceConnection connection) {
9591 synchronized (this) {
9592 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009593 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009594 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9595 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009596 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 + connection.asBinder());
9598 return false;
9599 }
9600
9601 final long origId = Binder.clearCallingIdentity();
9602
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009603 while (clist.size() > 0) {
9604 ConnectionRecord r = clist.get(0);
9605 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009606
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009607 if (r.binding.service.app != null) {
9608 // This could have made the service less important.
9609 updateOomAdjLocked(r.binding.service.app);
9610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611 }
9612
9613 Binder.restoreCallingIdentity(origId);
9614 }
9615
9616 return true;
9617 }
9618
9619 public void publishService(IBinder token, Intent intent, IBinder service) {
9620 // Refuse possible leaked file descriptors
9621 if (intent != null && intent.hasFileDescriptors() == true) {
9622 throw new IllegalArgumentException("File descriptors passed in Intent");
9623 }
9624
9625 synchronized(this) {
9626 if (!(token instanceof ServiceRecord)) {
9627 throw new IllegalArgumentException("Invalid service token");
9628 }
9629 ServiceRecord r = (ServiceRecord)token;
9630
9631 final long origId = Binder.clearCallingIdentity();
9632
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009633 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 + " " + intent + ": " + service);
9635 if (r != null) {
9636 Intent.FilterComparison filter
9637 = new Intent.FilterComparison(intent);
9638 IntentBindRecord b = r.bindings.get(filter);
9639 if (b != null && !b.received) {
9640 b.binder = service;
9641 b.requested = true;
9642 b.received = true;
9643 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009644 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 = r.connections.values().iterator();
9646 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009647 ArrayList<ConnectionRecord> clist = it.next();
9648 for (int i=0; i<clist.size(); i++) {
9649 ConnectionRecord c = clist.get(i);
9650 if (!filter.equals(c.binding.intent.intent)) {
9651 if (DEBUG_SERVICE) Slog.v(
9652 TAG, "Not publishing to: " + c);
9653 if (DEBUG_SERVICE) Slog.v(
9654 TAG, "Bound intent: " + c.binding.intent.intent);
9655 if (DEBUG_SERVICE) Slog.v(
9656 TAG, "Published intent: " + intent);
9657 continue;
9658 }
9659 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9660 try {
9661 c.conn.connected(r.name, service);
9662 } catch (Exception e) {
9663 Slog.w(TAG, "Failure sending service " + r.name +
9664 " to connection " + c.conn.asBinder() +
9665 " (in " + c.binding.client.processName + ")", e);
9666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 }
9668 }
9669 }
9670 }
9671
9672 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9673
9674 Binder.restoreCallingIdentity(origId);
9675 }
9676 }
9677 }
9678
9679 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9680 // Refuse possible leaked file descriptors
9681 if (intent != null && intent.hasFileDescriptors() == true) {
9682 throw new IllegalArgumentException("File descriptors passed in Intent");
9683 }
9684
9685 synchronized(this) {
9686 if (!(token instanceof ServiceRecord)) {
9687 throw new IllegalArgumentException("Invalid service token");
9688 }
9689 ServiceRecord r = (ServiceRecord)token;
9690
9691 final long origId = Binder.clearCallingIdentity();
9692
9693 if (r != null) {
9694 Intent.FilterComparison filter
9695 = new Intent.FilterComparison(intent);
9696 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009697 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 + " at " + b + ": apps="
9699 + (b != null ? b.apps.size() : 0));
9700 if (b != null) {
9701 if (b.apps.size() > 0) {
9702 // Applications have already bound since the last
9703 // unbind, so just rebind right here.
9704 requestServiceBindingLocked(r, b, true);
9705 } else {
9706 // Note to tell the service the next time there is
9707 // a new client.
9708 b.doRebind = true;
9709 }
9710 }
9711
9712 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9713
9714 Binder.restoreCallingIdentity(origId);
9715 }
9716 }
9717 }
9718
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009719 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720 synchronized(this) {
9721 if (!(token instanceof ServiceRecord)) {
9722 throw new IllegalArgumentException("Invalid service token");
9723 }
9724 ServiceRecord r = (ServiceRecord)token;
9725 boolean inStopping = mStoppingServices.contains(token);
9726 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009728 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729 + " with incorrect token: given " + token
9730 + ", expected " + r);
9731 return;
9732 }
9733
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009734 if (type == 1) {
9735 // This is a call from a service start... take care of
9736 // book-keeping.
9737 r.callStart = true;
9738 switch (res) {
9739 case Service.START_STICKY_COMPATIBILITY:
9740 case Service.START_STICKY: {
9741 // We are done with the associated start arguments.
9742 r.findDeliveredStart(startId, true);
9743 // Don't stop if killed.
9744 r.stopIfKilled = false;
9745 break;
9746 }
9747 case Service.START_NOT_STICKY: {
9748 // We are done with the associated start arguments.
9749 r.findDeliveredStart(startId, true);
9750 if (r.lastStartId == startId) {
9751 // There is no more work, and this service
9752 // doesn't want to hang around if killed.
9753 r.stopIfKilled = true;
9754 }
9755 break;
9756 }
9757 case Service.START_REDELIVER_INTENT: {
9758 // We'll keep this item until they explicitly
9759 // call stop for it, but keep track of the fact
9760 // that it was delivered.
9761 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9762 if (si != null) {
9763 si.deliveryCount = 0;
9764 si.doneExecutingCount++;
9765 // Don't stop if killed.
9766 r.stopIfKilled = true;
9767 }
9768 break;
9769 }
9770 default:
9771 throw new IllegalArgumentException(
9772 "Unknown service start result: " + res);
9773 }
9774 if (res == Service.START_STICKY_COMPATIBILITY) {
9775 r.callStart = false;
9776 }
9777 }
9778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009779 final long origId = Binder.clearCallingIdentity();
9780 serviceDoneExecutingLocked(r, inStopping);
9781 Binder.restoreCallingIdentity(origId);
9782 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009783 Slog.w(TAG, "Done executing unknown service from pid "
9784 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 }
9786 }
9787 }
9788
9789 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009790 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9791 + ": nesting=" + r.executeNesting
9792 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009793 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 r.executeNesting--;
9795 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009796 if (DEBUG_SERVICE) Slog.v(TAG,
9797 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 r.app.executingServices.remove(r);
9799 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009800 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9801 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9803 }
9804 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009805 if (DEBUG_SERVICE) Slog.v(TAG,
9806 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807 mStoppingServices.remove(r);
Mattias Petersson5f619b72010-10-27 09:32:51 +02009808 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809 }
9810 updateOomAdjLocked(r.app);
9811 }
9812 }
9813
9814 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009815 String anrMessage = null;
9816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 synchronized(this) {
9818 if (proc.executingServices.size() == 0 || proc.thread == null) {
9819 return;
9820 }
9821 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9822 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9823 ServiceRecord timeout = null;
9824 long nextTime = 0;
9825 while (it.hasNext()) {
9826 ServiceRecord sr = it.next();
9827 if (sr.executingStart < maxTime) {
9828 timeout = sr;
9829 break;
9830 }
9831 if (sr.executingStart > nextTime) {
9832 nextTime = sr.executingStart;
9833 }
9834 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009835 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009836 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009837 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009838 } else {
9839 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9840 msg.obj = proc;
9841 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9842 }
9843 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009844
9845 if (anrMessage != null) {
9846 appNotResponding(proc, null, null, anrMessage);
9847 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009848 }
9849
9850 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009851 // BACKUP AND RESTORE
9852 // =========================================================
9853
9854 // Cause the target app to be launched if necessary and its backup agent
9855 // instantiated. The backup agent will invoke backupAgentCreated() on the
9856 // activity manager to announce its creation.
9857 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009858 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009859 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9860
9861 synchronized(this) {
9862 // !!! TODO: currently no check here that we're already bound
9863 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9864 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9865 synchronized (stats) {
9866 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9867 }
9868
9869 BackupRecord r = new BackupRecord(ss, app, backupMode);
9870 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9871 // startProcessLocked() returns existing proc's record if it's already running
9872 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009873 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009874 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009875 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009876 return false;
9877 }
9878
9879 r.app = proc;
9880 mBackupTarget = r;
9881 mBackupAppName = app.packageName;
9882
Christopher Tate6fa95972009-06-05 18:43:55 -07009883 // Try not to kill the process during backup
9884 updateOomAdjLocked(proc);
9885
Christopher Tate181fafa2009-05-14 11:12:14 -07009886 // If the process is already attached, schedule the creation of the backup agent now.
9887 // If it is not yet live, this will be done when it attaches to the framework.
9888 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009889 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009890 try {
9891 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9892 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009893 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009894 }
9895 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009896 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009897 }
9898 // Invariants: at this point, the target app process exists and the application
9899 // is either already running or in the process of coming up. mBackupTarget and
9900 // mBackupAppName describe the app, so that when it binds back to the AM we
9901 // know that it's scheduled for a backup-agent operation.
9902 }
9903
9904 return true;
9905 }
9906
9907 // A backup agent has just come up
9908 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009909 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009910 + " = " + agent);
9911
9912 synchronized(this) {
9913 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009914 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009915 return;
9916 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009917 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009918
Dianne Hackborn06740692010-09-22 22:46:21 -07009919 long oldIdent = Binder.clearCallingIdentity();
9920 try {
9921 IBackupManager bm = IBackupManager.Stub.asInterface(
9922 ServiceManager.getService(Context.BACKUP_SERVICE));
9923 bm.agentConnected(agentPackageName, agent);
9924 } catch (RemoteException e) {
9925 // can't happen; the backup manager service is local
9926 } catch (Exception e) {
9927 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9928 e.printStackTrace();
9929 } finally {
9930 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009931 }
9932 }
9933
9934 // done with this agent
9935 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009936 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009937 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009938 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009939 return;
9940 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009941
9942 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009943 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009944 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009945 return;
9946 }
9947
Christopher Tate181fafa2009-05-14 11:12:14 -07009948 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009949 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009950 return;
9951 }
9952
Christopher Tate6fa95972009-06-05 18:43:55 -07009953 ProcessRecord proc = mBackupTarget.app;
9954 mBackupTarget = null;
9955 mBackupAppName = null;
9956
9957 // Not backing this app up any more; reset its OOM adjustment
9958 updateOomAdjLocked(proc);
9959
Christopher Tatec7b31e32009-06-10 15:49:30 -07009960 // If the app crashed during backup, 'thread' will be null here
9961 if (proc.thread != null) {
9962 try {
9963 proc.thread.scheduleDestroyBackupAgent(appInfo);
9964 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009965 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009966 e.printStackTrace();
9967 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009968 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009969 }
9970 }
9971 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 // BROADCASTS
9973 // =========================================================
9974
Josh Bartel7f208742010-02-25 11:01:44 -06009975 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 List cur) {
9977 final ContentResolver resolver = mContext.getContentResolver();
9978 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9979 if (list == null) {
9980 return cur;
9981 }
9982 int N = list.size();
9983 for (int i=0; i<N; i++) {
9984 Intent intent = list.get(i);
9985 if (filter.match(resolver, intent, true, TAG) >= 0) {
9986 if (cur == null) {
9987 cur = new ArrayList<Intent>();
9988 }
9989 cur.add(intent);
9990 }
9991 }
9992 return cur;
9993 }
9994
9995 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009996 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 + mBroadcastsScheduled);
9998
9999 if (mBroadcastsScheduled) {
10000 return;
10001 }
10002 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10003 mBroadcastsScheduled = true;
10004 }
10005
10006 public Intent registerReceiver(IApplicationThread caller,
10007 IIntentReceiver receiver, IntentFilter filter, String permission) {
10008 synchronized(this) {
10009 ProcessRecord callerApp = null;
10010 if (caller != null) {
10011 callerApp = getRecordForAppLocked(caller);
10012 if (callerApp == null) {
10013 throw new SecurityException(
10014 "Unable to find app for caller " + caller
10015 + " (pid=" + Binder.getCallingPid()
10016 + ") when registering receiver " + receiver);
10017 }
10018 }
10019
10020 List allSticky = null;
10021
10022 // Look for any matching sticky broadcasts...
10023 Iterator actions = filter.actionsIterator();
10024 if (actions != null) {
10025 while (actions.hasNext()) {
10026 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010027 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010028 }
10029 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010030 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 }
10032
10033 // The first sticky in the list is returned directly back to
10034 // the client.
10035 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10036
Joe Onorato8a9b2202010-02-26 18:56:32 -080010037 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 + ": " + sticky);
10039
10040 if (receiver == null) {
10041 return sticky;
10042 }
10043
10044 ReceiverList rl
10045 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10046 if (rl == null) {
10047 rl = new ReceiverList(this, callerApp,
10048 Binder.getCallingPid(),
10049 Binder.getCallingUid(), receiver);
10050 if (rl.app != null) {
10051 rl.app.receivers.add(rl);
10052 } else {
10053 try {
10054 receiver.asBinder().linkToDeath(rl, 0);
10055 } catch (RemoteException e) {
10056 return sticky;
10057 }
10058 rl.linkedToDeath = true;
10059 }
10060 mRegisteredReceivers.put(receiver.asBinder(), rl);
10061 }
10062 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10063 rl.add(bf);
10064 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010065 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 }
10067 mReceiverResolver.addFilter(bf);
10068
10069 // Enqueue broadcasts for all existing stickies that match
10070 // this filter.
10071 if (allSticky != null) {
10072 ArrayList receivers = new ArrayList();
10073 receivers.add(bf);
10074
10075 int N = allSticky.size();
10076 for (int i=0; i<N; i++) {
10077 Intent intent = (Intent)allSticky.get(i);
10078 BroadcastRecord r = new BroadcastRecord(intent, null,
10079 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010080 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 if (mParallelBroadcasts.size() == 0) {
10082 scheduleBroadcastsLocked();
10083 }
10084 mParallelBroadcasts.add(r);
10085 }
10086 }
10087
10088 return sticky;
10089 }
10090 }
10091
10092 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010093 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094
10095 boolean doNext = false;
10096
10097 synchronized(this) {
10098 ReceiverList rl
10099 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10100 if (rl != null) {
10101 if (rl.curBroadcast != null) {
10102 BroadcastRecord r = rl.curBroadcast;
10103 doNext = finishReceiverLocked(
10104 receiver.asBinder(), r.resultCode, r.resultData,
10105 r.resultExtras, r.resultAbort, true);
10106 }
10107
10108 if (rl.app != null) {
10109 rl.app.receivers.remove(rl);
10110 }
10111 removeReceiverLocked(rl);
10112 if (rl.linkedToDeath) {
10113 rl.linkedToDeath = false;
10114 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10115 }
10116 }
10117 }
10118
10119 if (!doNext) {
10120 return;
10121 }
10122
10123 final long origId = Binder.clearCallingIdentity();
10124 processNextBroadcast(false);
10125 trimApplications();
10126 Binder.restoreCallingIdentity(origId);
10127 }
10128
10129 void removeReceiverLocked(ReceiverList rl) {
10130 mRegisteredReceivers.remove(rl.receiver.asBinder());
10131 int N = rl.size();
10132 for (int i=0; i<N; i++) {
10133 mReceiverResolver.removeFilter(rl.get(i));
10134 }
10135 }
10136
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010137 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10138 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10139 ProcessRecord r = mLruProcesses.get(i);
10140 if (r.thread != null) {
10141 try {
10142 r.thread.dispatchPackageBroadcast(cmd, packages);
10143 } catch (RemoteException ex) {
10144 }
10145 }
10146 }
10147 }
10148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010149 private final int broadcastIntentLocked(ProcessRecord callerApp,
10150 String callerPackage, Intent intent, String resolvedType,
10151 IIntentReceiver resultTo, int resultCode, String resultData,
10152 Bundle map, String requiredPermission,
10153 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10154 intent = new Intent(intent);
10155
Joe Onorato8a9b2202010-02-26 18:56:32 -080010156 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010157 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10158 + " ordered=" + ordered);
10159 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010160 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010161 }
10162
10163 // Handle special intents: if this broadcast is from the package
10164 // manager about a package being removed, we need to remove all of
10165 // its activities from the history stack.
10166 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10167 intent.getAction());
10168 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10169 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010170 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 || uidRemoved) {
10172 if (checkComponentPermission(
10173 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10174 callingPid, callingUid, -1)
10175 == PackageManager.PERMISSION_GRANTED) {
10176 if (uidRemoved) {
10177 final Bundle intentExtras = intent.getExtras();
10178 final int uid = intentExtras != null
10179 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10180 if (uid >= 0) {
10181 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10182 synchronized (bs) {
10183 bs.removeUidStatsLocked(uid);
10184 }
10185 }
10186 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010187 // If resources are unvailble just force stop all
10188 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010189 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010190 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10191 if (list != null && (list.length > 0)) {
10192 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010193 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010194 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010195 sendPackageBroadcastLocked(
10196 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010197 }
10198 } else {
10199 Uri data = intent.getData();
10200 String ssp;
10201 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10202 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10203 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010204 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010205 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010206 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10207 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10208 new String[] {ssp});
10209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210 }
10211 }
10212 }
10213 } else {
10214 String msg = "Permission Denial: " + intent.getAction()
10215 + " broadcast from " + callerPackage + " (pid=" + callingPid
10216 + ", uid=" + callingUid + ")"
10217 + " requires "
10218 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010219 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010220 throw new SecurityException(msg);
10221 }
10222 }
10223
10224 /*
10225 * If this is the time zone changed action, queue up a message that will reset the timezone
10226 * of all currently running processes. This message will get queued up before the broadcast
10227 * happens.
10228 */
10229 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10230 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10231 }
10232
Dianne Hackborn854060af2009-07-09 18:14:31 -070010233 /*
10234 * Prevent non-system code (defined here to be non-persistent
10235 * processes) from sending protected broadcasts.
10236 */
10237 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10238 || callingUid == Process.SHELL_UID || callingUid == 0) {
10239 // Always okay.
10240 } else if (callerApp == null || !callerApp.persistent) {
10241 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010242 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010243 intent.getAction())) {
10244 String msg = "Permission Denial: not allowed to send broadcast "
10245 + intent.getAction() + " from pid="
10246 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010247 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010248 throw new SecurityException(msg);
10249 }
10250 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010251 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010252 return BROADCAST_SUCCESS;
10253 }
10254 }
10255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 // Add to the sticky list if requested.
10257 if (sticky) {
10258 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10259 callingPid, callingUid)
10260 != PackageManager.PERMISSION_GRANTED) {
10261 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10262 + callingPid + ", uid=" + callingUid
10263 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010264 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010265 throw new SecurityException(msg);
10266 }
10267 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010268 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010269 + " and enforce permission " + requiredPermission);
10270 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10271 }
10272 if (intent.getComponent() != null) {
10273 throw new SecurityException(
10274 "Sticky broadcasts can't target a specific component");
10275 }
10276 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10277 if (list == null) {
10278 list = new ArrayList<Intent>();
10279 mStickyBroadcasts.put(intent.getAction(), list);
10280 }
10281 int N = list.size();
10282 int i;
10283 for (i=0; i<N; i++) {
10284 if (intent.filterEquals(list.get(i))) {
10285 // This sticky already exists, replace it.
10286 list.set(i, new Intent(intent));
10287 break;
10288 }
10289 }
10290 if (i >= N) {
10291 list.add(new Intent(intent));
10292 }
10293 }
10294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 // Figure out who all will receive this broadcast.
10296 List receivers = null;
10297 List<BroadcastFilter> registeredReceivers = null;
10298 try {
10299 if (intent.getComponent() != null) {
10300 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010301 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010302 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 if (ai != null) {
10304 receivers = new ArrayList();
10305 ResolveInfo ri = new ResolveInfo();
10306 ri.activityInfo = ai;
10307 receivers.add(ri);
10308 }
10309 } else {
10310 // Need to resolve the intent to interested receivers...
10311 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10312 == 0) {
10313 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010314 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010315 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010316 }
Mihai Preda074edef2009-05-18 17:13:31 +020010317 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010318 }
10319 } catch (RemoteException ex) {
10320 // pm is in same process, this will never happen.
10321 }
10322
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010323 final boolean replacePending =
10324 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10325
Joe Onorato8a9b2202010-02-26 18:56:32 -080010326 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010327 + " replacePending=" + replacePending);
10328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10330 if (!ordered && NR > 0) {
10331 // If we are not serializing this broadcast, then send the
10332 // registered receivers separately so they don't wait for the
10333 // components to be launched.
10334 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10335 callerPackage, callingPid, callingUid, requiredPermission,
10336 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010337 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010338 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 TAG, "Enqueueing parallel broadcast " + r
10340 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010341 boolean replaced = false;
10342 if (replacePending) {
10343 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10344 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010345 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010346 "***** DROPPING PARALLEL: " + intent);
10347 mParallelBroadcasts.set(i, r);
10348 replaced = true;
10349 break;
10350 }
10351 }
10352 }
10353 if (!replaced) {
10354 mParallelBroadcasts.add(r);
10355 scheduleBroadcastsLocked();
10356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 registeredReceivers = null;
10358 NR = 0;
10359 }
10360
10361 // Merge into one list.
10362 int ir = 0;
10363 if (receivers != null) {
10364 // A special case for PACKAGE_ADDED: do not allow the package
10365 // being added to see this broadcast. This prevents them from
10366 // using this as a back door to get run as soon as they are
10367 // installed. Maybe in the future we want to have a special install
10368 // broadcast or such for apps, but we'd like to deliberately make
10369 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010370 String skipPackages[] = null;
10371 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10372 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10373 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10374 Uri data = intent.getData();
10375 if (data != null) {
10376 String pkgName = data.getSchemeSpecificPart();
10377 if (pkgName != null) {
10378 skipPackages = new String[] { pkgName };
10379 }
10380 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010381 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010382 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010383 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010384 if (skipPackages != null && (skipPackages.length > 0)) {
10385 for (String skipPackage : skipPackages) {
10386 if (skipPackage != null) {
10387 int NT = receivers.size();
10388 for (int it=0; it<NT; it++) {
10389 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10390 if (curt.activityInfo.packageName.equals(skipPackage)) {
10391 receivers.remove(it);
10392 it--;
10393 NT--;
10394 }
10395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010396 }
10397 }
10398 }
10399
10400 int NT = receivers != null ? receivers.size() : 0;
10401 int it = 0;
10402 ResolveInfo curt = null;
10403 BroadcastFilter curr = null;
10404 while (it < NT && ir < NR) {
10405 if (curt == null) {
10406 curt = (ResolveInfo)receivers.get(it);
10407 }
10408 if (curr == null) {
10409 curr = registeredReceivers.get(ir);
10410 }
10411 if (curr.getPriority() >= curt.priority) {
10412 // Insert this broadcast record into the final list.
10413 receivers.add(it, curr);
10414 ir++;
10415 curr = null;
10416 it++;
10417 NT++;
10418 } else {
10419 // Skip to the next ResolveInfo in the final list.
10420 it++;
10421 curt = null;
10422 }
10423 }
10424 }
10425 while (ir < NR) {
10426 if (receivers == null) {
10427 receivers = new ArrayList();
10428 }
10429 receivers.add(registeredReceivers.get(ir));
10430 ir++;
10431 }
10432
10433 if ((receivers != null && receivers.size() > 0)
10434 || resultTo != null) {
10435 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10436 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010437 receivers, resultTo, resultCode, resultData, map, ordered,
10438 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010439 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 TAG, "Enqueueing ordered broadcast " + r
10441 + ": prev had " + mOrderedBroadcasts.size());
10442 if (DEBUG_BROADCAST) {
10443 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010444 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010445 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010446 boolean replaced = false;
10447 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010448 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010449 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010450 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010451 "***** DROPPING ORDERED: " + intent);
10452 mOrderedBroadcasts.set(i, r);
10453 replaced = true;
10454 break;
10455 }
10456 }
10457 }
10458 if (!replaced) {
10459 mOrderedBroadcasts.add(r);
10460 scheduleBroadcastsLocked();
10461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 }
10463
10464 return BROADCAST_SUCCESS;
10465 }
10466
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010467 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 // Refuse possible leaked file descriptors
10469 if (intent != null && intent.hasFileDescriptors() == true) {
10470 throw new IllegalArgumentException("File descriptors passed in Intent");
10471 }
10472
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010473 int flags = intent.getFlags();
10474
10475 if (!mProcessesReady) {
10476 // if the caller really truly claims to know what they're doing, go
10477 // ahead and allow the broadcast without launching any receivers
10478 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10479 intent = new Intent(intent);
10480 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10481 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10482 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10483 + " before boot completion");
10484 throw new IllegalStateException("Cannot broadcast before boot completed");
10485 }
10486 }
10487
10488 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10489 throw new IllegalArgumentException(
10490 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10491 }
10492
10493 return intent;
10494 }
10495
10496 public final int broadcastIntent(IApplicationThread caller,
10497 Intent intent, String resolvedType, IIntentReceiver resultTo,
10498 int resultCode, String resultData, Bundle map,
10499 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010501 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010503 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10504 final int callingPid = Binder.getCallingPid();
10505 final int callingUid = Binder.getCallingUid();
10506 final long origId = Binder.clearCallingIdentity();
10507 int res = broadcastIntentLocked(callerApp,
10508 callerApp != null ? callerApp.info.packageName : null,
10509 intent, resolvedType, resultTo,
10510 resultCode, resultData, map, requiredPermission, serialized,
10511 sticky, callingPid, callingUid);
10512 Binder.restoreCallingIdentity(origId);
10513 return res;
10514 }
10515 }
10516
10517 int broadcastIntentInPackage(String packageName, int uid,
10518 Intent intent, String resolvedType, IIntentReceiver resultTo,
10519 int resultCode, String resultData, Bundle map,
10520 String requiredPermission, boolean serialized, boolean sticky) {
10521 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010522 intent = verifyBroadcastLocked(intent);
10523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 final long origId = Binder.clearCallingIdentity();
10525 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10526 resultTo, resultCode, resultData, map, requiredPermission,
10527 serialized, sticky, -1, uid);
10528 Binder.restoreCallingIdentity(origId);
10529 return res;
10530 }
10531 }
10532
10533 public final void unbroadcastIntent(IApplicationThread caller,
10534 Intent intent) {
10535 // Refuse possible leaked file descriptors
10536 if (intent != null && intent.hasFileDescriptors() == true) {
10537 throw new IllegalArgumentException("File descriptors passed in Intent");
10538 }
10539
10540 synchronized(this) {
10541 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10542 != PackageManager.PERMISSION_GRANTED) {
10543 String msg = "Permission Denial: unbroadcastIntent() from pid="
10544 + Binder.getCallingPid()
10545 + ", uid=" + Binder.getCallingUid()
10546 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 throw new SecurityException(msg);
10549 }
10550 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10551 if (list != null) {
10552 int N = list.size();
10553 int i;
10554 for (i=0; i<N; i++) {
10555 if (intent.filterEquals(list.get(i))) {
10556 list.remove(i);
10557 break;
10558 }
10559 }
10560 }
10561 }
10562 }
10563
10564 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10565 String resultData, Bundle resultExtras, boolean resultAbort,
10566 boolean explicit) {
10567 if (mOrderedBroadcasts.size() == 0) {
10568 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010569 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 }
10571 return false;
10572 }
10573 BroadcastRecord r = mOrderedBroadcasts.get(0);
10574 if (r.receiver == null) {
10575 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010576 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010577 }
10578 return false;
10579 }
10580 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010581 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010582 return false;
10583 }
10584 int state = r.state;
10585 r.state = r.IDLE;
10586 if (state == r.IDLE) {
10587 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010588 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589 }
10590 }
10591 r.receiver = null;
10592 r.intent.setComponent(null);
10593 if (r.curApp != null) {
10594 r.curApp.curReceiver = null;
10595 }
10596 if (r.curFilter != null) {
10597 r.curFilter.receiverList.curBroadcast = null;
10598 }
10599 r.curFilter = null;
10600 r.curApp = null;
10601 r.curComponent = null;
10602 r.curReceiver = null;
10603 mPendingBroadcast = null;
10604
10605 r.resultCode = resultCode;
10606 r.resultData = resultData;
10607 r.resultExtras = resultExtras;
10608 r.resultAbort = resultAbort;
10609
10610 // We will process the next receiver right now if this is finishing
10611 // an app receiver (which is always asynchronous) or after we have
10612 // come back from calling a receiver.
10613 return state == BroadcastRecord.APP_RECEIVE
10614 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10615 }
10616
10617 public void finishReceiver(IBinder who, int resultCode, String resultData,
10618 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010619 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620
10621 // Refuse possible leaked file descriptors
10622 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10623 throw new IllegalArgumentException("File descriptors passed in Bundle");
10624 }
10625
10626 boolean doNext;
10627
10628 final long origId = Binder.clearCallingIdentity();
10629
10630 synchronized(this) {
10631 doNext = finishReceiverLocked(
10632 who, resultCode, resultData, resultExtras, resultAbort, true);
10633 }
10634
10635 if (doNext) {
10636 processNextBroadcast(false);
10637 }
10638 trimApplications();
10639
10640 Binder.restoreCallingIdentity(origId);
10641 }
10642
Jeff Brown4d94a762010-09-23 11:33:28 -070010643 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010644 if (r.nextReceiver > 0) {
10645 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10646 if (curReceiver instanceof BroadcastFilter) {
10647 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010648 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 System.identityHashCode(r),
10650 r.intent.getAction(),
10651 r.nextReceiver - 1,
10652 System.identityHashCode(bf));
10653 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010654 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 System.identityHashCode(r),
10656 r.intent.getAction(),
10657 r.nextReceiver - 1,
10658 ((ResolveInfo)curReceiver).toString());
10659 }
10660 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010661 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010662 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010663 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 System.identityHashCode(r),
10665 r.intent.getAction(),
10666 r.nextReceiver,
10667 "NONE");
10668 }
10669 }
10670
Jeff Brown4d94a762010-09-23 11:33:28 -070010671 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10672 if (! mPendingBroadcastTimeoutMessage) {
10673 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10674 mHandler.sendMessageAtTime(msg, timeoutTime);
10675 mPendingBroadcastTimeoutMessage = true;
10676 }
10677 }
10678
10679 private final void cancelBroadcastTimeoutLocked() {
10680 if (mPendingBroadcastTimeoutMessage) {
10681 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10682 mPendingBroadcastTimeoutMessage = false;
10683 }
10684 }
10685
10686 private final void broadcastTimeoutLocked(boolean fromMsg) {
10687 if (fromMsg) {
10688 mPendingBroadcastTimeoutMessage = false;
10689 }
10690
10691 if (mOrderedBroadcasts.size() == 0) {
10692 return;
10693 }
10694
10695 long now = SystemClock.uptimeMillis();
10696 BroadcastRecord r = mOrderedBroadcasts.get(0);
10697 if (fromMsg) {
10698 if (mDidDexOpt) {
10699 // Delay timeouts until dexopt finishes.
10700 mDidDexOpt = false;
10701 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10702 setBroadcastTimeoutLocked(timeoutTime);
10703 return;
10704 }
10705 if (! mProcessesReady) {
10706 // Only process broadcast timeouts if the system is ready. That way
10707 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10708 // to do heavy lifting for system up.
10709 return;
10710 }
10711
10712 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10713 if (timeoutTime > now) {
10714 // We can observe premature timeouts because we do not cancel and reset the
10715 // broadcast timeout message after each receiver finishes. Instead, we set up
10716 // an initial timeout then kick it down the road a little further as needed
10717 // when it expires.
10718 if (DEBUG_BROADCAST) Slog.v(TAG,
10719 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10720 + timeoutTime);
10721 setBroadcastTimeoutLocked(timeoutTime);
10722 return;
10723 }
10724 }
10725
10726 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10727 + ", started " + (now - r.receiverTime) + "ms ago");
10728 r.receiverTime = now;
10729 r.anrCount++;
10730
10731 // Current receiver has passed its expiration date.
10732 if (r.nextReceiver <= 0) {
10733 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10734 return;
10735 }
10736
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010737 ProcessRecord app = null;
10738 String anrMessage = null;
10739
Jeff Brown4d94a762010-09-23 11:33:28 -070010740 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10741 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10742 logBroadcastReceiverDiscardLocked(r);
10743 if (curReceiver instanceof BroadcastFilter) {
10744 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10745 if (bf.receiverList.pid != 0
10746 && bf.receiverList.pid != MY_PID) {
10747 synchronized (this.mPidsSelfLocked) {
10748 app = this.mPidsSelfLocked.get(
10749 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010752 } else {
10753 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010755
Jeff Brown4d94a762010-09-23 11:33:28 -070010756 if (app != null) {
10757 anrMessage = "Broadcast of " + r.intent.toString();
10758 }
10759
10760 if (mPendingBroadcast == r) {
10761 mPendingBroadcast = null;
10762 }
10763
10764 // Move on to the next receiver.
10765 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10766 r.resultExtras, r.resultAbort, true);
10767 scheduleBroadcastsLocked();
10768
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010769 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010770 // Post the ANR to the handler since we do not want to process ANRs while
10771 // potentially holding our lock.
10772 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 }
10775
10776 private final void processCurBroadcastLocked(BroadcastRecord r,
10777 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010778 if (DEBUG_BROADCAST) Slog.v(TAG,
10779 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010780 if (app.thread == null) {
10781 throw new RemoteException();
10782 }
10783 r.receiver = app.thread.asBinder();
10784 r.curApp = app;
10785 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010786 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787
10788 // Tell the application to launch this receiver.
10789 r.intent.setComponent(r.curComponent);
10790
10791 boolean started = false;
10792 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010793 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 "Delivering to component " + r.curComponent
10795 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010796 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10798 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010799 if (DEBUG_BROADCAST) Slog.v(TAG,
10800 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 started = true;
10802 } finally {
10803 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010804 if (DEBUG_BROADCAST) Slog.v(TAG,
10805 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 r.receiver = null;
10807 r.curApp = null;
10808 app.curReceiver = null;
10809 }
10810 }
10811
10812 }
10813
Jeff Brown4d94a762010-09-23 11:33:28 -070010814 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010815 Intent intent, int resultCode, String data, Bundle extras,
10816 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010817 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 if (app != null && app.thread != null) {
10819 // If we have an app thread, do the call through that so it is
10820 // correctly ordered with other one-way calls.
10821 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010822 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010824 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825 }
10826 }
10827
Jeff Brown4d94a762010-09-23 11:33:28 -070010828 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 BroadcastFilter filter, boolean ordered) {
10830 boolean skip = false;
10831 if (filter.requiredPermission != null) {
10832 int perm = checkComponentPermission(filter.requiredPermission,
10833 r.callingPid, r.callingUid, -1);
10834 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010835 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 + r.intent.toString()
10837 + " from " + r.callerPackage + " (pid="
10838 + r.callingPid + ", uid=" + r.callingUid + ")"
10839 + " requires " + filter.requiredPermission
10840 + " due to registered receiver " + filter);
10841 skip = true;
10842 }
10843 }
10844 if (r.requiredPermission != null) {
10845 int perm = checkComponentPermission(r.requiredPermission,
10846 filter.receiverList.pid, filter.receiverList.uid, -1);
10847 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010848 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 + r.intent.toString()
10850 + " to " + filter.receiverList.app
10851 + " (pid=" + filter.receiverList.pid
10852 + ", uid=" + filter.receiverList.uid + ")"
10853 + " requires " + r.requiredPermission
10854 + " due to sender " + r.callerPackage
10855 + " (uid " + r.callingUid + ")");
10856 skip = true;
10857 }
10858 }
10859
10860 if (!skip) {
10861 // If this is not being sent as an ordered broadcast, then we
10862 // don't want to touch the fields that keep track of the current
10863 // state of ordered broadcasts.
10864 if (ordered) {
10865 r.receiver = filter.receiverList.receiver.asBinder();
10866 r.curFilter = filter;
10867 filter.receiverList.curBroadcast = r;
10868 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010869 if (filter.receiverList.app != null) {
10870 // Bump hosting application to no longer be in background
10871 // scheduling class. Note that we can't do that if there
10872 // isn't an app... but we can only be in that case for
10873 // things that directly call the IActivityManager API, which
10874 // are already core system stuff so don't matter for this.
10875 r.curApp = filter.receiverList.app;
10876 filter.receiverList.app.curReceiver = r;
10877 updateOomAdjLocked();
10878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 }
10880 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010881 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010883 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010884 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010885 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010886 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010888 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010889 if (ordered) {
10890 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10891 }
10892 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010893 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 if (ordered) {
10895 r.receiver = null;
10896 r.curFilter = null;
10897 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010898 if (filter.receiverList.app != null) {
10899 filter.receiverList.app.curReceiver = null;
10900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010901 }
10902 }
10903 }
10904 }
10905
Dianne Hackborn12527f92009-11-11 17:39:50 -080010906 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10907 if (r.callingUid < 0) {
10908 // This was from a registerReceiver() call; ignore it.
10909 return;
10910 }
10911 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10912 MAX_BROADCAST_HISTORY-1);
10913 r.finishTime = SystemClock.uptimeMillis();
10914 mBroadcastHistory[0] = r;
10915 }
10916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 private final void processNextBroadcast(boolean fromMsg) {
10918 synchronized(this) {
10919 BroadcastRecord r;
10920
Joe Onorato8a9b2202010-02-26 18:56:32 -080010921 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010923 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924
10925 updateCpuStats();
10926
10927 if (fromMsg) {
10928 mBroadcastsScheduled = false;
10929 }
10930
10931 // First, deliver any non-serialized broadcasts right away.
10932 while (mParallelBroadcasts.size() > 0) {
10933 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010934 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010935 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010936 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010937 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 for (int i=0; i<N; i++) {
10939 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010940 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010941 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010943 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010945 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010946 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010947 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 }
10949
10950 // Now take care of the next serialized one...
10951
10952 // If we are waiting for a process to come up to handle the next
10953 // broadcast, then do nothing at this point. Just in case, we
10954 // check that the process we're waiting for still exists.
10955 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010956 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010957 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010958 + mPendingBroadcast.curApp);
10959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960
10961 boolean isDead;
10962 synchronized (mPidsSelfLocked) {
10963 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10964 }
10965 if (!isDead) {
10966 // It's still alive, so keep waiting
10967 return;
10968 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010969 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010971 mPendingBroadcast.state = BroadcastRecord.IDLE;
10972 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 mPendingBroadcast = null;
10974 }
10975 }
10976
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010977 boolean looped = false;
10978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 do {
10980 if (mOrderedBroadcasts.size() == 0) {
10981 // No more broadcasts pending, so all done!
10982 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010983 if (looped) {
10984 // If we had finished the last ordered broadcast, then
10985 // make sure all processes have correct oom and sched
10986 // adjustments.
10987 updateOomAdjLocked();
10988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 return;
10990 }
10991 r = mOrderedBroadcasts.get(0);
10992 boolean forceReceive = false;
10993
10994 // Ensure that even if something goes awry with the timeout
10995 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010996 // and continue to make progress.
10997 //
10998 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070010999 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011000 // one time heavy lifting after system upgrades and can take
11001 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011003 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011004 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 if ((numReceivers > 0) &&
11006 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 + " now=" + now
11009 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011010 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 + " intent=" + r.intent
11012 + " numReceivers=" + numReceivers
11013 + " nextReceiver=" + r.nextReceiver
11014 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011015 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 forceReceive = true;
11017 r.state = BroadcastRecord.IDLE;
11018 }
11019 }
11020
11021 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011022 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 "processNextBroadcast() called when not idle (state="
11024 + r.state + ")");
11025 return;
11026 }
11027
11028 if (r.receivers == null || r.nextReceiver >= numReceivers
11029 || r.resultAbort || forceReceive) {
11030 // No more receivers for this broadcast! Send the final
11031 // result if requested...
11032 if (r.resultTo != null) {
11033 try {
11034 if (DEBUG_BROADCAST) {
11035 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011036 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 + " seq=" + seq + " app=" + r.callerApp);
11038 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011039 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011041 r.resultData, r.resultExtras, false, false);
Johannes Carlsson58975912010-10-27 10:08:10 +020011042 // Set this to null so that the reference
11043 // (local and remote) isnt kept in the mBroadcastHistory.
11044 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011045 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011046 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 }
11048 }
11049
Joe Onorato8a9b2202010-02-26 18:56:32 -080011050 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011051 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052
Joe Onorato8a9b2202010-02-26 18:56:32 -080011053 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011054 + r);
11055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011057 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 mOrderedBroadcasts.remove(0);
11059 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011060 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 continue;
11062 }
11063 } while (r == null);
11064
11065 // Get the next receiver...
11066 int recIdx = r.nextReceiver++;
11067
11068 // Keep track of when this receiver started, and make sure there
11069 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011070 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011072 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073
Joe Onorato8a9b2202010-02-26 18:56:32 -080011074 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011075 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011076 }
11077 if (! mPendingBroadcastTimeoutMessage) {
11078 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011079 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011080 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11081 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011082 }
11083
11084 Object nextReceiver = r.receivers.get(recIdx);
11085 if (nextReceiver instanceof BroadcastFilter) {
11086 // Simple case: this is a registered receiver who gets
11087 // a direct call.
11088 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011089 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011090 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011092 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 if (r.receiver == null || !r.ordered) {
11094 // The receiver has already finished, so schedule to
11095 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011096 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11097 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 r.state = BroadcastRecord.IDLE;
11099 scheduleBroadcastsLocked();
11100 }
11101 return;
11102 }
11103
11104 // Hard case: need to instantiate the receiver, possibly
11105 // starting its application process to host it.
11106
11107 ResolveInfo info =
11108 (ResolveInfo)nextReceiver;
11109
11110 boolean skip = false;
11111 int perm = checkComponentPermission(info.activityInfo.permission,
11112 r.callingPid, r.callingUid,
11113 info.activityInfo.exported
11114 ? -1 : info.activityInfo.applicationInfo.uid);
11115 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011116 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 + r.intent.toString()
11118 + " from " + r.callerPackage + " (pid=" + r.callingPid
11119 + ", uid=" + r.callingUid + ")"
11120 + " requires " + info.activityInfo.permission
11121 + " due to receiver " + info.activityInfo.packageName
11122 + "/" + info.activityInfo.name);
11123 skip = true;
11124 }
11125 if (r.callingUid != Process.SYSTEM_UID &&
11126 r.requiredPermission != null) {
11127 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011128 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 checkPermission(r.requiredPermission,
11130 info.activityInfo.applicationInfo.packageName);
11131 } catch (RemoteException e) {
11132 perm = PackageManager.PERMISSION_DENIED;
11133 }
11134 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011135 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 + r.intent + " to "
11137 + info.activityInfo.applicationInfo.packageName
11138 + " requires " + r.requiredPermission
11139 + " due to sender " + r.callerPackage
11140 + " (uid " + r.callingUid + ")");
11141 skip = true;
11142 }
11143 }
11144 if (r.curApp != null && r.curApp.crashing) {
11145 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011146 if (DEBUG_BROADCAST) Slog.v(TAG,
11147 "Skipping deliver ordered " + r + " to " + r.curApp
11148 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 skip = true;
11150 }
11151
11152 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011153 if (DEBUG_BROADCAST) Slog.v(TAG,
11154 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 r.receiver = null;
11156 r.curFilter = null;
11157 r.state = BroadcastRecord.IDLE;
11158 scheduleBroadcastsLocked();
11159 return;
11160 }
11161
11162 r.state = BroadcastRecord.APP_RECEIVE;
11163 String targetProcess = info.activityInfo.processName;
11164 r.curComponent = new ComponentName(
11165 info.activityInfo.applicationInfo.packageName,
11166 info.activityInfo.name);
11167 r.curReceiver = info.activityInfo;
11168
11169 // Is this receiver's application already running?
11170 ProcessRecord app = getProcessRecordLocked(targetProcess,
11171 info.activityInfo.applicationInfo.uid);
11172 if (app != null && app.thread != null) {
11173 try {
11174 processCurBroadcastLocked(r, app);
11175 return;
11176 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011177 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178 + r.curComponent, e);
11179 }
11180
11181 // If a dead object exception was thrown -- fall through to
11182 // restart the application.
11183 }
11184
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011185 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011186 if (DEBUG_BROADCAST) Slog.v(TAG,
11187 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 if ((r.curApp=startProcessLocked(targetProcess,
11189 info.activityInfo.applicationInfo, true,
11190 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011191 "broadcast", r.curComponent,
11192 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11193 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 // Ah, this recipient is unavailable. Finish it if necessary,
11195 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011196 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 + info.activityInfo.applicationInfo.packageName + "/"
11198 + info.activityInfo.applicationInfo.uid + " for broadcast "
11199 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011200 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011201 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11202 r.resultExtras, r.resultAbort, true);
11203 scheduleBroadcastsLocked();
11204 r.state = BroadcastRecord.IDLE;
11205 return;
11206 }
11207
11208 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011209 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 }
11211 }
11212
11213 // =========================================================
11214 // INSTRUMENTATION
11215 // =========================================================
11216
11217 public boolean startInstrumentation(ComponentName className,
11218 String profileFile, int flags, Bundle arguments,
11219 IInstrumentationWatcher watcher) {
11220 // Refuse possible leaked file descriptors
11221 if (arguments != null && arguments.hasFileDescriptors()) {
11222 throw new IllegalArgumentException("File descriptors passed in Bundle");
11223 }
11224
11225 synchronized(this) {
11226 InstrumentationInfo ii = null;
11227 ApplicationInfo ai = null;
11228 try {
11229 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011230 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011232 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 } catch (PackageManager.NameNotFoundException e) {
11234 }
11235 if (ii == null) {
11236 reportStartInstrumentationFailure(watcher, className,
11237 "Unable to find instrumentation info for: " + className);
11238 return false;
11239 }
11240 if (ai == null) {
11241 reportStartInstrumentationFailure(watcher, className,
11242 "Unable to find instrumentation target package: " + ii.targetPackage);
11243 return false;
11244 }
11245
11246 int match = mContext.getPackageManager().checkSignatures(
11247 ii.targetPackage, ii.packageName);
11248 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11249 String msg = "Permission Denial: starting instrumentation "
11250 + className + " from pid="
11251 + Binder.getCallingPid()
11252 + ", uid=" + Binder.getCallingPid()
11253 + " not allowed because package " + ii.packageName
11254 + " does not have a signature matching the target "
11255 + ii.targetPackage;
11256 reportStartInstrumentationFailure(watcher, className, msg);
11257 throw new SecurityException(msg);
11258 }
11259
11260 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011261 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 ProcessRecord app = addAppLocked(ai);
11263 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011264 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011265 app.instrumentationProfileFile = profileFile;
11266 app.instrumentationArguments = arguments;
11267 app.instrumentationWatcher = watcher;
11268 app.instrumentationResultClass = className;
11269 Binder.restoreCallingIdentity(origId);
11270 }
11271
11272 return true;
11273 }
11274
11275 /**
11276 * Report errors that occur while attempting to start Instrumentation. Always writes the
11277 * error to the logs, but if somebody is watching, send the report there too. This enables
11278 * the "am" command to report errors with more information.
11279 *
11280 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11281 * @param cn The component name of the instrumentation.
11282 * @param report The error report.
11283 */
11284 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11285 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011286 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 try {
11288 if (watcher != null) {
11289 Bundle results = new Bundle();
11290 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11291 results.putString("Error", report);
11292 watcher.instrumentationStatus(cn, -1, results);
11293 }
11294 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011295 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 }
11297 }
11298
11299 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11300 if (app.instrumentationWatcher != null) {
11301 try {
11302 // NOTE: IInstrumentationWatcher *must* be oneway here
11303 app.instrumentationWatcher.instrumentationFinished(
11304 app.instrumentationClass,
11305 resultCode,
11306 results);
11307 } catch (RemoteException e) {
11308 }
11309 }
11310 app.instrumentationWatcher = null;
11311 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011312 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 app.instrumentationProfileFile = null;
11314 app.instrumentationArguments = null;
11315
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011316 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 }
11318
11319 public void finishInstrumentation(IApplicationThread target,
11320 int resultCode, Bundle results) {
11321 // Refuse possible leaked file descriptors
11322 if (results != null && results.hasFileDescriptors()) {
11323 throw new IllegalArgumentException("File descriptors passed in Intent");
11324 }
11325
11326 synchronized(this) {
11327 ProcessRecord app = getRecordForAppLocked(target);
11328 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011329 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011330 return;
11331 }
11332 final long origId = Binder.clearCallingIdentity();
11333 finishInstrumentationLocked(app, resultCode, results);
11334 Binder.restoreCallingIdentity(origId);
11335 }
11336 }
11337
11338 // =========================================================
11339 // CONFIGURATION
11340 // =========================================================
11341
11342 public ConfigurationInfo getDeviceConfigurationInfo() {
11343 ConfigurationInfo config = new ConfigurationInfo();
11344 synchronized (this) {
11345 config.reqTouchScreen = mConfiguration.touchscreen;
11346 config.reqKeyboardType = mConfiguration.keyboard;
11347 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011348 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11349 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11351 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011352 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11353 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11355 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011356 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 }
11358 return config;
11359 }
11360
11361 public Configuration getConfiguration() {
11362 Configuration ci;
11363 synchronized(this) {
11364 ci = new Configuration(mConfiguration);
11365 }
11366 return ci;
11367 }
11368
11369 public void updateConfiguration(Configuration values) {
11370 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11371 "updateConfiguration()");
11372
11373 synchronized(this) {
11374 if (values == null && mWindowManager != null) {
11375 // sentinel: fetch the current configuration from the window manager
11376 values = mWindowManager.computeNewConfiguration();
11377 }
11378
11379 final long origId = Binder.clearCallingIdentity();
11380 updateConfigurationLocked(values, null);
11381 Binder.restoreCallingIdentity(origId);
11382 }
11383 }
11384
11385 /**
11386 * Do either or both things: (1) change the current configuration, and (2)
11387 * make sure the given activity is running with the (now) current
11388 * configuration. Returns true if the activity has been left running, or
11389 * false if <var>starting</var> is being destroyed to match the new
11390 * configuration.
11391 */
11392 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011393 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 int changes = 0;
11395
11396 boolean kept = true;
11397
11398 if (values != null) {
11399 Configuration newConfig = new Configuration(mConfiguration);
11400 changes = newConfig.updateFrom(values);
11401 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011402 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011403 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 }
11405
Doug Zongker2bec3d42009-12-04 12:52:44 -080011406 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407
11408 if (values.locale != null) {
11409 saveLocaleLocked(values.locale,
11410 !values.locale.equals(mConfiguration.locale),
11411 values.userSetLocale);
11412 }
11413
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011414 mConfigurationSeq++;
11415 if (mConfigurationSeq <= 0) {
11416 mConfigurationSeq = 1;
11417 }
11418 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011420 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011421
11422 AttributeCache ac = AttributeCache.instance();
11423 if (ac != null) {
11424 ac.updateConfiguration(mConfiguration);
11425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011427 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11428 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11429 msg.obj = new Configuration(mConfiguration);
11430 mHandler.sendMessage(msg);
11431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011433 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11434 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011435 try {
11436 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011437 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011438 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439 app.thread.scheduleConfigurationChanged(mConfiguration);
11440 }
11441 } catch (Exception e) {
11442 }
11443 }
11444 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011445 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11446 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011447 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11448 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011449 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11450 broadcastIntentLocked(null, null,
11451 new Intent(Intent.ACTION_LOCALE_CHANGED),
11452 null, null, 0, null, null,
11453 null, false, false, MY_PID, Process.SYSTEM_UID);
11454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 }
11456 }
11457
11458 if (changes != 0 && starting == null) {
11459 // If the configuration changed, and the caller is not already
11460 // in the process of starting an activity, then find the top
11461 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011462 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 }
11464
11465 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011466 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 if (kept) {
11468 // If this didn't result in the starting activity being
11469 // destroyed, then we need to make sure at this point that all
11470 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011471 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011473 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 }
11475 }
11476
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011477 if (values != null && mWindowManager != null) {
11478 mWindowManager.setNewConfiguration(mConfiguration);
11479 }
11480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011481 return kept;
11482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483
11484 /**
11485 * Save the locale. You must be inside a synchronized (this) block.
11486 */
11487 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11488 if(isDiff) {
11489 SystemProperties.set("user.language", l.getLanguage());
11490 SystemProperties.set("user.region", l.getCountry());
11491 }
11492
11493 if(isPersist) {
11494 SystemProperties.set("persist.sys.language", l.getLanguage());
11495 SystemProperties.set("persist.sys.country", l.getCountry());
11496 SystemProperties.set("persist.sys.localevar", l.getVariant());
11497 }
11498 }
11499
11500 // =========================================================
11501 // LIFETIME MANAGEMENT
11502 // =========================================================
11503
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011504 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11505 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011507 // This adjustment has already been computed. If we are calling
11508 // from the top, we may have already computed our adjustment with
11509 // an earlier hidden adjustment that isn't really for us... if
11510 // so, use the new hidden adjustment.
11511 if (!recursed && app.hidden) {
11512 app.curAdj = hiddenAdj;
11513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 return app.curAdj;
11515 }
11516
11517 if (app.thread == null) {
11518 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011519 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 return (app.curAdj=EMPTY_APP_ADJ);
11521 }
11522
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011523 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11524 // The max adjustment doesn't allow this app to be anything
11525 // below foreground, so it is not worth doing work for it.
11526 app.adjType = "fixed";
11527 app.adjSeq = mAdjSeq;
11528 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011529 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011530 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11531 return (app.curAdj=app.maxAdj);
11532 }
11533
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011534 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011535 app.adjSource = null;
11536 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011537 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011538 app.empty = false;
11539 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011540
The Android Open Source Project4df24232009-03-05 14:34:35 -080011541 // Determine the importance of the process, starting with most
11542 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011544 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011546 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 // The last app on the list is the foreground app.
11548 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011549 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011550 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011551 } else if (app.instrumentationClass != null) {
11552 // Don't want to kill running instrumentation.
11553 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011554 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011555 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 } else if (app.curReceiver != null ||
11557 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11558 // An app that is currently receiving a broadcast also
11559 // counts as being in the foreground.
11560 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011561 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011562 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 } else if (app.executingServices.size() > 0) {
11564 // An app that is currently executing a service callback also
11565 // counts as being in the foreground.
11566 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011567 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011568 app.adjType = "exec-service";
11569 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011571 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011572 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011573 app.adjType = "foreground-service";
11574 } else if (app.forcingToForeground != null) {
11575 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011576 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011577 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011578 app.adjType = "force-foreground";
11579 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011580 } else if (app == mHeavyWeightProcess) {
11581 // We don't want to kill the current heavy-weight process.
11582 adj = HEAVY_WEIGHT_APP_ADJ;
11583 schedGroup = Process.THREAD_GROUP_DEFAULT;
11584 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011585 } else if (app == mHomeProcess) {
11586 // This process is hosting what we currently consider to be the
11587 // home app, so we don't want to let it go into the background.
11588 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011589 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011590 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011591 } else if ((N=app.activities.size()) != 0) {
11592 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011593 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011595 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011596 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011597 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011599 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011601 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011603 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011604 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011605 break;
11606 }
11607 }
11608 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011609 // A very not-needed process. If this is lower in the lru list,
11610 // we will push it in to the empty bucket.
11611 app.hidden = true;
11612 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011613 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011614 adj = hiddenAdj;
11615 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 }
11617
Joe Onorato8a9b2202010-02-26 18:56:32 -080011618 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011619
The Android Open Source Project4df24232009-03-05 14:34:35 -080011620 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 // there are applications dependent on our services or providers, but
11622 // this gives us a baseline and makes sure we don't get into an
11623 // infinite recursion.
11624 app.adjSeq = mAdjSeq;
11625 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011626
Christopher Tate6fa95972009-06-05 18:43:55 -070011627 if (mBackupTarget != null && app == mBackupTarget.app) {
11628 // If possible we want to avoid killing apps while they're being backed up
11629 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011630 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011631 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011632 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011633 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011634 }
11635 }
11636
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011637 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11638 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 final long now = SystemClock.uptimeMillis();
11640 // This process is more important if the top activity is
11641 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011642 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011644 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 if (s.startRequested) {
11646 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11647 // This service has seen some activity within
11648 // recent memory, so we will keep its process ahead
11649 // of the background processes.
11650 if (adj > SECONDARY_SERVER_ADJ) {
11651 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011652 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011653 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011654 }
11655 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011656 // If we have let the service slide into the background
11657 // state, still have some text describing what it is doing
11658 // even though the service no longer has an impact.
11659 if (adj > SECONDARY_SERVER_ADJ) {
11660 app.adjType = "started-bg-services";
11661 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011662 // Don't kill this process because it is doing work; it
11663 // has said it is doing work.
11664 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011666 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11667 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011668 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 = s.connections.values().iterator();
11670 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011671 ArrayList<ConnectionRecord> clist = kt.next();
11672 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11673 // XXX should compute this based on the max of
11674 // all connected clients.
11675 ConnectionRecord cr = clist.get(i);
11676 if (cr.binding.client == app) {
11677 // Binding to ourself is not interesting.
11678 continue;
11679 }
11680 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11681 ProcessRecord client = cr.binding.client;
11682 int myHiddenAdj = hiddenAdj;
11683 if (myHiddenAdj > client.hiddenAdj) {
11684 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11685 myHiddenAdj = client.hiddenAdj;
11686 } else {
11687 myHiddenAdj = VISIBLE_APP_ADJ;
11688 }
11689 }
11690 int clientAdj = computeOomAdjLocked(
11691 client, myHiddenAdj, TOP_APP, true);
11692 if (adj > clientAdj) {
11693 adj = clientAdj >= VISIBLE_APP_ADJ
11694 ? clientAdj : VISIBLE_APP_ADJ;
11695 if (!client.hidden) {
11696 app.hidden = false;
11697 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011698 if (client.keeping) {
11699 app.keeping = true;
11700 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011701 app.adjType = "service";
11702 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11703 .REASON_SERVICE_IN_USE;
11704 app.adjSource = cr.binding.client;
11705 app.adjTarget = s.name;
11706 }
11707 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11708 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11709 schedGroup = Process.THREAD_GROUP_DEFAULT;
11710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011711 }
11712 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011713 ActivityRecord a = cr.activity;
11714 //if (a != null) {
11715 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11716 //}
11717 if (a != null && adj > FOREGROUND_APP_ADJ &&
11718 (a.state == ActivityState.RESUMED
11719 || a.state == ActivityState.PAUSING)) {
11720 adj = FOREGROUND_APP_ADJ;
11721 schedGroup = Process.THREAD_GROUP_DEFAULT;
11722 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011723 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011724 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11725 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011726 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011727 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 }
11730 }
11731 }
11732 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011733
Dianne Hackborn287952c2010-09-22 22:34:31 -070011734 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011735 // would like to avoid killing it unless it would prevent the current
11736 // application from running. By default we put the process in
11737 // with the rest of the background processes; as we scan through
11738 // its services we may bump it up from there.
11739 if (adj > hiddenAdj) {
11740 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011741 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011742 app.adjType = "bg-services";
11743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011744 }
11745
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011746 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11747 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011748 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011749 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11750 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011751 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011752 if (cpr.clients.size() != 0) {
11753 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11754 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11755 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011756 if (client == app) {
11757 // Being our own client is not interesting.
11758 continue;
11759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011760 int myHiddenAdj = hiddenAdj;
11761 if (myHiddenAdj > client.hiddenAdj) {
11762 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11763 myHiddenAdj = client.hiddenAdj;
11764 } else {
11765 myHiddenAdj = FOREGROUND_APP_ADJ;
11766 }
11767 }
11768 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011769 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011770 if (adj > clientAdj) {
11771 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011772 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011773 if (!client.hidden) {
11774 app.hidden = false;
11775 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011776 if (client.keeping) {
11777 app.keeping = true;
11778 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011779 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011780 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11781 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011782 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011783 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011785 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11786 schedGroup = Process.THREAD_GROUP_DEFAULT;
11787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 }
11789 }
11790 // If the provider has external (non-framework) process
11791 // dependencies, ensure that its adjustment is at least
11792 // FOREGROUND_APP_ADJ.
11793 if (cpr.externals != 0) {
11794 if (adj > FOREGROUND_APP_ADJ) {
11795 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011796 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011797 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011798 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011799 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011800 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 }
11802 }
11803 }
11804 }
11805
11806 app.curRawAdj = adj;
11807
Joe Onorato8a9b2202010-02-26 18:56:32 -080011808 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11810 if (adj > app.maxAdj) {
11811 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011812 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011813 schedGroup = Process.THREAD_GROUP_DEFAULT;
11814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011816 if (adj < HIDDEN_APP_MIN_ADJ) {
11817 app.keeping = true;
11818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819
11820 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011821 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 return adj;
11824 }
11825
11826 /**
11827 * Ask a given process to GC right now.
11828 */
11829 final void performAppGcLocked(ProcessRecord app) {
11830 try {
11831 app.lastRequestedGc = SystemClock.uptimeMillis();
11832 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011833 if (app.reportLowMemory) {
11834 app.reportLowMemory = false;
11835 app.thread.scheduleLowMemory();
11836 } else {
11837 app.thread.processInBackground();
11838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 }
11840 } catch (Exception e) {
11841 // whatever.
11842 }
11843 }
11844
11845 /**
11846 * Returns true if things are idle enough to perform GCs.
11847 */
Josh Bartel7f208742010-02-25 11:01:44 -060011848 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011849 return mParallelBroadcasts.size() == 0
11850 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011851 && (mSleeping || (mMainStack.mResumedActivity != null &&
11852 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 }
11854
11855 /**
11856 * Perform GCs on all processes that are waiting for it, but only
11857 * if things are idle.
11858 */
11859 final void performAppGcsLocked() {
11860 final int N = mProcessesToGc.size();
11861 if (N <= 0) {
11862 return;
11863 }
Josh Bartel7f208742010-02-25 11:01:44 -060011864 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 while (mProcessesToGc.size() > 0) {
11866 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011867 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011868 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11869 <= SystemClock.uptimeMillis()) {
11870 // To avoid spamming the system, we will GC processes one
11871 // at a time, waiting a few seconds between each.
11872 performAppGcLocked(proc);
11873 scheduleAppGcsLocked();
11874 return;
11875 } else {
11876 // It hasn't been long enough since we last GCed this
11877 // process... put it in the list to wait for its time.
11878 addProcessToGcListLocked(proc);
11879 break;
11880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 }
11882 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011883
11884 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 }
11886 }
11887
11888 /**
11889 * If all looks good, perform GCs on all processes waiting for them.
11890 */
11891 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011892 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 performAppGcsLocked();
11894 return;
11895 }
11896 // Still not idle, wait some more.
11897 scheduleAppGcsLocked();
11898 }
11899
11900 /**
11901 * Schedule the execution of all pending app GCs.
11902 */
11903 final void scheduleAppGcsLocked() {
11904 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011905
11906 if (mProcessesToGc.size() > 0) {
11907 // Schedule a GC for the time to the next process.
11908 ProcessRecord proc = mProcessesToGc.get(0);
11909 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11910
11911 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11912 long now = SystemClock.uptimeMillis();
11913 if (when < (now+GC_TIMEOUT)) {
11914 when = now + GC_TIMEOUT;
11915 }
11916 mHandler.sendMessageAtTime(msg, when);
11917 }
11918 }
11919
11920 /**
11921 * Add a process to the array of processes waiting to be GCed. Keeps the
11922 * list in sorted order by the last GC time. The process can't already be
11923 * on the list.
11924 */
11925 final void addProcessToGcListLocked(ProcessRecord proc) {
11926 boolean added = false;
11927 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11928 if (mProcessesToGc.get(i).lastRequestedGc <
11929 proc.lastRequestedGc) {
11930 added = true;
11931 mProcessesToGc.add(i+1, proc);
11932 break;
11933 }
11934 }
11935 if (!added) {
11936 mProcessesToGc.add(0, proc);
11937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 }
11939
11940 /**
11941 * Set up to ask a process to GC itself. This will either do it
11942 * immediately, or put it on the list of processes to gc the next
11943 * time things are idle.
11944 */
11945 final void scheduleAppGcLocked(ProcessRecord app) {
11946 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011947 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 return;
11949 }
11950 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011951 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 scheduleAppGcsLocked();
11953 }
11954 }
11955
Dianne Hackborn287952c2010-09-22 22:34:31 -070011956 final void checkExcessivePowerUsageLocked(boolean doKills) {
11957 updateCpuStatsNow();
11958
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011959 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011960 boolean doWakeKills = doKills;
11961 boolean doCpuKills = doKills;
11962 if (mLastPowerCheckRealtime == 0) {
11963 doWakeKills = false;
11964 }
11965 if (mLastPowerCheckUptime == 0) {
11966 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011967 }
11968 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011969 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011970 }
11971 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011972 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11973 final long curUptime = SystemClock.uptimeMillis();
11974 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11975 mLastPowerCheckRealtime = curRealtime;
11976 mLastPowerCheckUptime = curUptime;
11977 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11978 doWakeKills = false;
11979 }
11980 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11981 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011982 }
11983 int i = mLruProcesses.size();
11984 while (i > 0) {
11985 i--;
11986 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011987 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011988 long wtime;
11989 synchronized (stats) {
11990 wtime = stats.getProcessWakeTime(app.info.uid,
11991 app.pid, curRealtime);
11992 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011993 long wtimeUsed = wtime - app.lastWakeTime;
11994 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11995 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011996 StringBuilder sb = new StringBuilder(128);
11997 sb.append("Wake for ");
11998 app.toShortString(sb);
11999 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012000 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012001 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012002 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012003 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012004 sb.append((wtimeUsed*100)/realtimeSince);
12005 sb.append("%)");
12006 Slog.i(TAG, sb.toString());
12007 sb.setLength(0);
12008 sb.append("CPU for ");
12009 app.toShortString(sb);
12010 sb.append(": over ");
12011 TimeUtils.formatDuration(uptimeSince, sb);
12012 sb.append(" used ");
12013 TimeUtils.formatDuration(cputimeUsed, sb);
12014 sb.append(" (");
12015 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012016 sb.append("%)");
12017 Slog.i(TAG, sb.toString());
12018 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012019 // If a process has held a wake lock for more
12020 // than 50% of the time during this period,
12021 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012022 if (doWakeKills && realtimeSince > 0
12023 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12024 synchronized (stats) {
12025 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12026 realtimeSince, wtimeUsed);
12027 }
12028 Slog.w(TAG, "Excessive wake lock in " + app.processName
12029 + " (pid " + app.pid + "): held " + wtimeUsed
12030 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012031 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12032 app.processName, app.setAdj, "excessive wake lock");
12033 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012034 } else if (doCpuKills && uptimeSince > 0
12035 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12036 synchronized (stats) {
12037 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12038 uptimeSince, cputimeUsed);
12039 }
12040 Slog.w(TAG, "Excessive CPU in " + app.processName
12041 + " (pid " + app.pid + "): used " + cputimeUsed
12042 + " during " + uptimeSince);
12043 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12044 app.processName, app.setAdj, "excessive cpu");
12045 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012046 } else {
12047 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012048 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012049 }
12050 }
12051 }
12052 }
12053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012054 private final boolean updateOomAdjLocked(
12055 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12056 app.hiddenAdj = hiddenAdj;
12057
12058 if (app.thread == null) {
12059 return true;
12060 }
12061
Dianne Hackborn287952c2010-09-22 22:34:31 -070012062 final boolean wasKeeping = app.keeping;
12063
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012064 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012065
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012066 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012067 if (app.curRawAdj != app.setRawAdj) {
12068 if (app.curRawAdj > FOREGROUND_APP_ADJ
12069 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12070 // If this app is transitioning from foreground to
12071 // non-foreground, have it do a gc.
12072 scheduleAppGcLocked(app);
12073 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12074 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12075 // Likewise do a gc when an app is moving in to the
12076 // background (such as a service stopping).
12077 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012078 }
12079
12080 if (wasKeeping && !app.keeping) {
12081 // This app is no longer something we want to keep. Note
12082 // its current wake lock time to later know to kill it if
12083 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012084 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12085 synchronized (stats) {
12086 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12087 app.pid, SystemClock.elapsedRealtime());
12088 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012089 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012090 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 app.setRawAdj = app.curRawAdj;
12093 }
12094 if (adj != app.setAdj) {
12095 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012096 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012097 TAG, "Set app " + app.processName +
12098 " oom adj to " + adj);
12099 app.setAdj = adj;
12100 } else {
12101 return false;
12102 }
12103 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012104 if (app.setSchedGroup != app.curSchedGroup) {
12105 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012106 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012107 "Setting process group of " + app.processName
12108 + " to " + app.curSchedGroup);
12109 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012110 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012111 try {
12112 Process.setProcessGroup(app.pid, app.curSchedGroup);
12113 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012114 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012115 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012116 e.printStackTrace();
12117 } finally {
12118 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012119 }
12120 }
12121 if (false) {
12122 if (app.thread != null) {
12123 try {
12124 app.thread.setSchedulingGroup(app.curSchedGroup);
12125 } catch (RemoteException e) {
12126 }
12127 }
12128 }
12129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012130 }
12131
12132 return true;
12133 }
12134
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012135 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012136 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012137 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012138 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012139 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012140 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012141 }
12142 }
12143 return resumedActivity;
12144 }
12145
12146 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012147 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012148 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12149 int curAdj = app.curAdj;
12150 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12151 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12152
12153 mAdjSeq++;
12154
12155 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12156 if (res) {
12157 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12158 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12159 if (nowHidden != wasHidden) {
12160 // Changed to/from hidden state, so apps after it in the LRU
12161 // list may also be changed.
12162 updateOomAdjLocked();
12163 }
12164 }
12165 return res;
12166 }
12167
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012168 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012170 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012171 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12172
12173 if (false) {
12174 RuntimeException e = new RuntimeException();
12175 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012176 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012177 }
12178
12179 mAdjSeq++;
12180
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012181 // Let's determine how many processes we have running vs.
12182 // how many slots we have for background processes; we may want
12183 // to put multiple processes in a slot of there are enough of
12184 // them.
12185 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12186 int factor = (mLruProcesses.size()-4)/numSlots;
12187 if (factor < 1) factor = 1;
12188 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012189 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012191 // First try updating the OOM adjustment for each of the
12192 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012193 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12195 while (i > 0) {
12196 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012197 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012198 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012200 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012201 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012202 step++;
12203 if (step >= factor) {
12204 step = 0;
12205 curHiddenAdj++;
12206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012208 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012209 if (!app.killedBackground) {
12210 numHidden++;
12211 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012212 Slog.i(TAG, "No longer want " + app.processName
12213 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012214 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12215 app.processName, app.setAdj, "too many background");
12216 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012217 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012218 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012219 }
12220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012221 } else {
12222 didOomAdj = false;
12223 }
12224 }
12225
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012226 // If we return false, we will fall back on killing processes to
12227 // have a fixed limit. Do this if a limit has been requested; else
12228 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12230 }
12231
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012232 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 synchronized (this) {
12234 int i;
12235
12236 // First remove any unused application processes whose package
12237 // has been removed.
12238 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12239 final ProcessRecord app = mRemovedProcesses.get(i);
12240 if (app.activities.size() == 0
12241 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012242 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012243 TAG, "Exiting empty application process "
12244 + app.processName + " ("
12245 + (app.thread != null ? app.thread.asBinder() : null)
12246 + ")\n");
12247 if (app.pid > 0 && app.pid != MY_PID) {
12248 Process.killProcess(app.pid);
12249 } else {
12250 try {
12251 app.thread.scheduleExit();
12252 } catch (Exception e) {
12253 // Ignore exceptions.
12254 }
12255 }
12256 cleanUpApplicationRecordLocked(app, false, -1);
12257 mRemovedProcesses.remove(i);
12258
12259 if (app.persistent) {
12260 if (app.persistent) {
12261 addAppLocked(app.info);
12262 }
12263 }
12264 }
12265 }
12266
12267 // Now try updating the OOM adjustment for each of the
12268 // application processes based on their current state.
12269 // If the setOomAdj() API is not supported, then go with our
12270 // back-up plan...
12271 if (!updateOomAdjLocked()) {
12272
12273 // Count how many processes are running services.
12274 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012275 for (i=mLruProcesses.size()-1; i>=0; i--) {
12276 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277
12278 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012279 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 // Don't count processes holding services against our
12281 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012282 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012283 TAG, "Not trimming app " + app + " with services: "
12284 + app.services);
12285 numServiceProcs++;
12286 }
12287 }
12288
12289 int curMaxProcs = mProcessLimit;
12290 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12291 if (mAlwaysFinishActivities) {
12292 curMaxProcs = 1;
12293 }
12294 curMaxProcs += numServiceProcs;
12295
12296 // Quit as many processes as we can to get down to the desired
12297 // process count. First remove any processes that no longer
12298 // have activites running in them.
12299 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012300 i<mLruProcesses.size()
12301 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012302 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012303 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012304 // Quit an application only if it is not currently
12305 // running any activities.
12306 if (!app.persistent && app.activities.size() == 0
12307 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012308 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012309 TAG, "Exiting empty application process "
12310 + app.processName + " ("
12311 + (app.thread != null ? app.thread.asBinder() : null)
12312 + ")\n");
12313 if (app.pid > 0 && app.pid != MY_PID) {
12314 Process.killProcess(app.pid);
12315 } else {
12316 try {
12317 app.thread.scheduleExit();
12318 } catch (Exception e) {
12319 // Ignore exceptions.
12320 }
12321 }
12322 // todo: For now we assume the application is not buggy
12323 // or evil, and will quit as a result of our request.
12324 // Eventually we need to drive this off of the death
12325 // notification, and kill the process if it takes too long.
12326 cleanUpApplicationRecordLocked(app, false, i);
12327 i--;
12328 }
12329 }
12330
12331 // If we still have too many processes, now from the least
12332 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012333 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012334 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012335 " of " + curMaxProcs + " processes");
12336 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012337 i<mLruProcesses.size()
12338 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012339 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012340 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 // Quit the application only if we have a state saved for
12342 // all of its activities.
12343 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012344 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 int NUMA = app.activities.size();
12346 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012347 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012348 TAG, "Looking to quit " + app.processName);
12349 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012350 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012351 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012352 TAG, " " + r.intent.getComponent().flattenToShortString()
12353 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12354 canQuit = (r.haveState || !r.stateNotNeeded)
12355 && !r.visible && r.stopped;
12356 }
12357 if (canQuit) {
12358 // Finish all of the activities, and then the app itself.
12359 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012360 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012361 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012362 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 }
12364 r.resultTo = null;
12365 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012366 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012367 + app.processName + " ("
12368 + (app.thread != null ? app.thread.asBinder() : null)
12369 + ")\n");
12370 if (app.pid > 0 && app.pid != MY_PID) {
12371 Process.killProcess(app.pid);
12372 } else {
12373 try {
12374 app.thread.scheduleExit();
12375 } catch (Exception e) {
12376 // Ignore exceptions.
12377 }
12378 }
12379 // todo: For now we assume the application is not buggy
12380 // or evil, and will quit as a result of our request.
12381 // Eventually we need to drive this off of the death
12382 // notification, and kill the process if it takes too long.
12383 cleanUpApplicationRecordLocked(app, false, i);
12384 i--;
12385 //dump();
12386 }
12387 }
12388
12389 }
12390
12391 int curMaxActivities = MAX_ACTIVITIES;
12392 if (mAlwaysFinishActivities) {
12393 curMaxActivities = 1;
12394 }
12395
12396 // Finally, if there are too many activities now running, try to
12397 // finish as many as we can to get back down to the limit.
12398 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012399 i<mMainStack.mLRUActivities.size()
12400 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012402 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012403 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012404
12405 // We can finish this one if we have its icicle saved and
12406 // it is not persistent.
12407 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012408 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012409 final int origSize = mMainStack.mLRUActivities.size();
12410 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411
12412 // This will remove it from the LRU list, so keep
12413 // our index at the same value. Note that this check to
12414 // see if the size changes is just paranoia -- if
12415 // something unexpected happens, we don't want to end up
12416 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012417 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 i--;
12419 }
12420 }
12421 }
12422 }
12423 }
12424
12425 /** This method sends the specified signal to each of the persistent apps */
12426 public void signalPersistentProcesses(int sig) throws RemoteException {
12427 if (sig != Process.SIGNAL_USR1) {
12428 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12429 }
12430
12431 synchronized (this) {
12432 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12433 != PackageManager.PERMISSION_GRANTED) {
12434 throw new SecurityException("Requires permission "
12435 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12436 }
12437
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012438 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12439 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 if (r.thread != null && r.persistent) {
12441 Process.sendSignal(r.pid, sig);
12442 }
12443 }
12444 }
12445 }
12446
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012447 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012448 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012449
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012450 try {
12451 synchronized (this) {
12452 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12453 // its own permission.
12454 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12455 != PackageManager.PERMISSION_GRANTED) {
12456 throw new SecurityException("Requires permission "
12457 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012458 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012459
12460 if (start && fd == null) {
12461 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012462 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012463
12464 ProcessRecord proc = null;
12465 try {
12466 int pid = Integer.parseInt(process);
12467 synchronized (mPidsSelfLocked) {
12468 proc = mPidsSelfLocked.get(pid);
12469 }
12470 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012471 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012472
12473 if (proc == null) {
12474 HashMap<String, SparseArray<ProcessRecord>> all
12475 = mProcessNames.getMap();
12476 SparseArray<ProcessRecord> procs = all.get(process);
12477 if (procs != null && procs.size() > 0) {
12478 proc = procs.valueAt(0);
12479 }
12480 }
12481
12482 if (proc == null || proc.thread == null) {
12483 throw new IllegalArgumentException("Unknown process: " + process);
12484 }
12485
12486 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12487 if (isSecure) {
12488 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12489 throw new SecurityException("Process not debuggable: " + proc);
12490 }
12491 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012492
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012493 proc.thread.profilerControl(start, path, fd);
12494 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012495 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012496 }
12497 } catch (RemoteException e) {
12498 throw new IllegalStateException("Process disappeared");
12499 } finally {
12500 if (fd != null) {
12501 try {
12502 fd.close();
12503 } catch (IOException e) {
12504 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012505 }
12506 }
12507 }
12508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12510 public void monitor() {
12511 synchronized (this) { }
12512 }
12513}