blob: 768d99067fa2b0a8178ad13d1c344f51ba7e4e4d [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
Dianne Hackbornf26fd992011-04-08 18:14:09 -070047import android.app.IThumbnailRetriever;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070049import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070050import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.ComponentName;
57import android.content.ContentResolver;
58import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020059import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.Intent;
61import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070062import android.content.IIntentReceiver;
63import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070064import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.ActivityInfo;
66import android.content.pm.ApplicationInfo;
67import android.content.pm.ConfigurationInfo;
68import android.content.pm.IPackageDataObserver;
69import android.content.pm.IPackageManager;
70import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080071import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070073import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.content.pm.ProviderInfo;
75import android.content.pm.ResolveInfo;
76import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070077import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.content.res.Configuration;
79import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070080import android.net.Proxy;
81import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.net.Uri;
83import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070086import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080087import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080089import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.FileUtils;
91import android.os.Handler;
92import android.os.IBinder;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070093import android.os.IInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.IPermissionController;
95import android.os.Looper;
96import android.os.Message;
97import android.os.Parcel;
98import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700100import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.RemoteException;
102import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700103import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.os.SystemClock;
105import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800108import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800109import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.util.PrintWriterPrinter;
111import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700112import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import android.view.Gravity;
114import android.view.LayoutInflater;
115import android.view.View;
116import android.view.WindowManager;
117import android.view.WindowManagerPolicy;
118
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700119import java.io.BufferedInputStream;
120import java.io.BufferedOutputStream;
121import java.io.DataInputStream;
122import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.File;
124import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700125import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700127import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200128import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800129import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130import java.io.PrintWriter;
131import java.lang.IllegalStateException;
132import java.lang.ref.WeakReference;
133import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700134import java.util.Collections;
135import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136import java.util.HashMap;
137import java.util.HashSet;
138import java.util.Iterator;
139import java.util.List;
140import java.util.Locale;
141import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700142import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700143import java.util.concurrent.atomic.AtomicBoolean;
144import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700146public final class ActivityManagerService extends ActivityManagerNative
147 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final String TAG = "ActivityManager";
149 static final boolean DEBUG = false;
Joe Onorato43a17652011-04-06 19:22:23 -0700150 static final boolean localLOGV = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final boolean DEBUG_SWITCH = localLOGV || false;
152 static final boolean DEBUG_TASKS = localLOGV || false;
153 static final boolean DEBUG_PAUSE = localLOGV || false;
154 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
155 static final boolean DEBUG_TRANSITION = localLOGV || false;
156 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700157 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700159 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean DEBUG_VISBILITY = localLOGV || false;
161 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700162 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800163 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700165 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700166 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700167 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700168 static final boolean DEBUG_POWER = localLOGV || false;
169 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 static final boolean VALIDATE_TOKENS = false;
171 static final boolean SHOW_ACTIVITY_START_TIME = true;
172
173 // Control over CPU and battery monitoring.
174 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
175 static final boolean MONITOR_CPU_USAGE = true;
176 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
177 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
178 static final boolean MONITOR_THREAD_CPU_USAGE = false;
179
Dianne Hackborn1655be42009-05-08 14:29:01 -0700180 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700181 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800184 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
186 // This is the maximum number of application processes we would like
187 // to have running. Due to the asynchronous nature of things, we can
188 // temporarily go beyond this limit.
189 static final int MAX_PROCESSES = 2;
190
191 // Set to false to leave processes running indefinitely, relying on
192 // the kernel killing them as resources are required.
193 static final boolean ENFORCE_PROCESS_LIMIT = false;
194
195 // This is the maximum number of activities that we would like to have
196 // running at a given time.
197 static final int MAX_ACTIVITIES = 20;
198
199 // Maximum number of recent tasks that we can remember.
200 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700201
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700202 // Amount of time after a call to stopAppSwitches() during which we will
203 // prevent further untrusted switches from happening.
204 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
206 // How long we wait for a launched process to attach to the activity manager
207 // before we decide it's never going to come up for real.
208 static final int PROC_START_TIMEOUT = 10*1000;
209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 // How long to wait after going idle before forcing apps to GC.
211 static final int GC_TIMEOUT = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // The minimum amount of time between successive GC requests for a process.
214 static final int GC_MIN_INTERVAL = 60*1000;
215
Dianne Hackborn287952c2010-09-22 22:34:31 -0700216 // The rate at which we check for apps using excessive power -- 15 mins.
217 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
218
219 // The minimum sample duration we will allow before deciding we have
220 // enough data on wake locks to start killing things.
221 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
222
223 // The minimum sample duration we will allow before deciding we have
224 // enough data on CPU usage to start killing things.
225 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 // How long we allow a receiver to run before giving up on it.
228 static final int BROADCAST_TIMEOUT = 10*1000;
229
230 // How long we wait for a service to finish executing.
231 static final int SERVICE_TIMEOUT = 20*1000;
232
233 // How long a service needs to be running until restarting its process
234 // is no longer considered to be a relaunch of the service.
235 static final int SERVICE_RESTART_DURATION = 5*1000;
236
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700237 // How long a service needs to be running until it will start back at
238 // SERVICE_RESTART_DURATION after being killed.
239 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
240
241 // Multiplying factor to increase restart duration time by, for each time
242 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
243 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
244
245 // The minimum amount of time between restarting services that we allow.
246 // That is, when multiple services are restarting, we won't allow each
247 // to restart less than this amount of time from the last one.
248 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 // Maximum amount of time for there to be no activity on a service before
251 // we consider it non-essential and allow its process to go on the
252 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700253 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254
255 // How long we wait until we timeout on key dispatching.
256 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
257
258 // The minimum time we allow between crashes, for us to consider this
259 // application to be bad and stop and its services and reject broadcasts.
260 static final int MIN_CRASH_INTERVAL = 60*1000;
261
262 // How long we wait until we timeout on key dispatching during instrumentation.
263 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
264
265 // OOM adjustments for processes in various states:
266
267 // This is a process without anything currently running in it. Definitely
268 // the first to go! Value set in system/rootdir/init.rc on startup.
269 // This value is initalized in the constructor, careful when refering to
270 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272
273 // This is a process only hosting activities that are not visible,
274 // so it can be killed without any disruption. Value set in
275 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800276 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 static int HIDDEN_APP_MIN_ADJ;
278
The Android Open Source Project4df24232009-03-05 14:34:35 -0800279 // This is a process holding the home application -- we want to try
280 // avoiding killing it, even if it would normally be in the background,
281 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800283
Christopher Tate6fa95972009-06-05 18:43:55 -0700284 // This is a process currently hosting a backup operation. Killing it
285 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 // This is a process holding a secondary server -- killing it will not
289 // have much of an impact as far as the user is concerned. Value set in
290 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800291 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700293 // This is a process with a heavy-weight application. It is in the
294 // background, but we want to try to avoid killing it. Value set in
295 // system/rootdir/init.rc on startup.
296 static final int HEAVY_WEIGHT_APP_ADJ;
297
298 // This is a process only hosting components that are perceptible to the
299 // user, and we really want to avoid killing them, but they are not
300 // immediately visible. An example is background music playback. Value set in
301 // system/rootdir/init.rc on startup.
302 static final int PERCEPTIBLE_APP_ADJ;
303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 // This is a process only hosting activities that are visible to the
305 // user, so we'd prefer they don't disappear. Value set in
306 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 // This is the process running the current foreground app. We'd really
310 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800311 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
313 // This is a process running a core server, such as telephony. Definitely
314 // don't want to kill it, but doing so is not completely fatal.
315 static final int CORE_SERVER_ADJ = -12;
316
317 // The system process runs at the default adjustment.
318 static final int SYSTEM_ADJ = -16;
319
320 // Memory pages are 4K.
321 static final int PAGE_SIZE = 4*1024;
322
323 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800324 static final int EMPTY_APP_MEM;
325 static final int HIDDEN_APP_MEM;
326 static final int HOME_APP_MEM;
327 static final int BACKUP_APP_MEM;
328 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700329 static final int HEAVY_WEIGHT_APP_MEM;
330 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800331 static final int VISIBLE_APP_MEM;
332 static final int FOREGROUND_APP_MEM;
333
334 // The minimum number of hidden apps we want to be able to keep around,
335 // without empty apps being able to push them out of memory.
336 static final int MIN_HIDDEN_APPS = 2;
337
Dianne Hackborn8633e682010-04-22 16:03:41 -0700338 // The maximum number of hidden processes we will keep around before
339 // killing them; this is just a control to not let us go too crazy with
340 // keeping around processes on devices with large amounts of RAM.
341 static final int MAX_HIDDEN_APPS = 15;
342
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800343 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700344 // been idle for less than 15 seconds.
345 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346
347 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700348 // been idle for less than 120 seconds.
349 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800350
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700351 static int getIntProp(String name, boolean allowZero) {
352 String str = SystemProperties.get(name);
353 if (str == null) {
354 throw new IllegalArgumentException("Property not defined: " + name);
355 }
356 int val = Integer.valueOf(str);
357 if (val == 0 && !allowZero) {
358 throw new IllegalArgumentException("Property must not be zero: " + name);
359 }
360 return val;
361 }
362
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800363 static {
364 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700365 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
366 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
367 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
368 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
369 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
370 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
371 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
372 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
373 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
374 // These days we use the last empty slot for hidden apps as well.
375 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
376 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
377 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
378 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
379 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
380 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
381 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
382 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
383 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
384 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386
Dan Egnor42471dd2010-01-07 17:25:22 -0800387 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388
389 static final String[] EMPTY_STRING_ARRAY = new String[0];
390
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700391 public ActivityStack mMainStack;
392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700394 * Description of a request to start a new activity, which has been held
395 * due to app switches being disabled.
396 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700397 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700398 ActivityRecord r;
399 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700400 Uri[] grantedUriPermissions;
401 int grantedMode;
402 boolean onlyIfNeeded;
403 }
404
405 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
406 = new ArrayList<PendingActivityLaunch>();
407
408 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 * List of all active broadcasts that are to be executed immediately
410 * (without waiting for another broadcast to finish). Currently this only
411 * contains broadcasts to registered receivers, to avoid spinning up
412 * a bunch of processes to execute IntentReceiver components.
413 */
414 final ArrayList<BroadcastRecord> mParallelBroadcasts
415 = new ArrayList<BroadcastRecord>();
416
417 /**
418 * List of all active broadcasts that are to be executed one at a time.
419 * The object at the top of the list is the currently activity broadcasts;
420 * those after it are waiting for the top to finish..
421 */
422 final ArrayList<BroadcastRecord> mOrderedBroadcasts
423 = new ArrayList<BroadcastRecord>();
424
425 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800426 * Historical data of past broadcasts, for debugging.
427 */
428 static final int MAX_BROADCAST_HISTORY = 100;
429 final BroadcastRecord[] mBroadcastHistory
430 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
431
432 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * Set when we current have a BROADCAST_INTENT_MSG in flight.
434 */
435 boolean mBroadcastsScheduled = false;
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * Activity we have told the window manager to have key focus.
439 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700440 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700441 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 * List of intents that were used to start the most recent tasks.
443 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700444 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445
446 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * All of the applications we currently have running organized by name.
448 * The keys are strings of the application package name (as
449 * returned by the package manager), and the keys are ApplicationRecord
450 * objects.
451 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700452 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453
454 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700455 * The currently running heavy-weight process, if any.
456 */
457 ProcessRecord mHeavyWeightProcess = null;
458
459 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 * The last time that various processes have crashed.
461 */
462 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
463
464 /**
465 * Set of applications that we consider to be bad, and will reject
466 * incoming broadcasts from (which the user has no control over).
467 * Processes are added to this set when they have crashed twice within
468 * a minimum amount of time; they are removed from it when they are
469 * later restarted (hopefully due to some user action). The value is the
470 * time it was added to the list.
471 */
472 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
473
474 /**
475 * All of the processes we currently have running organized by pid.
476 * The keys are the pid running the application.
477 *
478 * <p>NOTE: This object is protected by its own lock, NOT the global
479 * activity manager lock!
480 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700481 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482
483 /**
484 * All of the processes that have been forced to be foreground. The key
485 * is the pid of the caller who requested it (we hold a death
486 * link on it).
487 */
488 abstract class ForegroundToken implements IBinder.DeathRecipient {
489 int pid;
490 IBinder token;
491 }
492 final SparseArray<ForegroundToken> mForegroundProcesses
493 = new SparseArray<ForegroundToken>();
494
495 /**
496 * List of records for processes that someone had tried to start before the
497 * system was ready. We don't start them at that point, but ensure they
498 * are started by the time booting is complete.
499 */
500 final ArrayList<ProcessRecord> mProcessesOnHold
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * List of records for processes that we have started and are waiting
505 * for them to call back. This is really only needed when running in
506 * single processes mode, in which case we do not have a unique pid for
507 * each process.
508 */
509 final ArrayList<ProcessRecord> mStartingProcesses
510 = new ArrayList<ProcessRecord>();
511
512 /**
513 * List of persistent applications that are in the process
514 * of being started.
515 */
516 final ArrayList<ProcessRecord> mPersistentStartingProcesses
517 = new ArrayList<ProcessRecord>();
518
519 /**
520 * Processes that are being forcibly torn down.
521 */
522 final ArrayList<ProcessRecord> mRemovedProcesses
523 = new ArrayList<ProcessRecord>();
524
525 /**
526 * List of running applications, sorted by recent usage.
527 * The first entry in the list is the least recently used.
528 * It contains ApplicationRecord objects. This list does NOT include
529 * any persistent application records (since we never want to exit them).
530 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800531 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 = new ArrayList<ProcessRecord>();
533
534 /**
535 * List of processes that should gc as soon as things are idle.
536 */
537 final ArrayList<ProcessRecord> mProcessesToGc
538 = new ArrayList<ProcessRecord>();
539
540 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800541 * This is the process holding what we currently consider to be
542 * the "home" activity.
543 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700544 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800545
546 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 * Set of PendingResultRecord objects that are currently active.
548 */
549 final HashSet mPendingResultRecords = new HashSet();
550
551 /**
552 * Set of IntentSenderRecord objects that are currently active.
553 */
554 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
555 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
556
557 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800558 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700559 * already logged DropBox entries for. Guarded by itself. If
560 * something (rogue user app) forces this over
561 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
562 */
563 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
564 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
565
566 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700567 * Strict Mode background batched logging state.
568 *
569 * The string buffer is guarded by itself, and its lock is also
570 * used to determine if another batched write is already
571 * in-flight.
572 */
573 private final StringBuilder mStrictModeBuffer = new StringBuilder();
574
575 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700576 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
577 */
578 private boolean mPendingBroadcastTimeoutMessage;
579
580 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 * Intent broadcast that we have tried to start, but are
582 * waiting for its application's process to be created. We only
583 * need one (instead of a list) because we always process broadcasts
584 * one at a time, so no others can be started while waiting for this
585 * one.
586 */
587 BroadcastRecord mPendingBroadcast = null;
588
589 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700590 * The receiver index that is pending, to restart the broadcast if needed.
591 */
592 int mPendingBroadcastRecvIndex;
593
594 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 * Keeps track of all IIntentReceivers that have been registered for
596 * broadcasts. Hash keys are the receiver IBinder, hash value is
597 * a ReceiverList.
598 */
599 final HashMap mRegisteredReceivers = new HashMap();
600
601 /**
602 * Resolver for broadcast intents to registered receivers.
603 * Holds BroadcastFilter (subclass of IntentFilter).
604 */
605 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
606 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
607 @Override
608 protected boolean allowFilterResult(
609 BroadcastFilter filter, List<BroadcastFilter> dest) {
610 IBinder target = filter.receiverList.receiver.asBinder();
611 for (int i=dest.size()-1; i>=0; i--) {
612 if (dest.get(i).receiverList.receiver.asBinder() == target) {
613 return false;
614 }
615 }
616 return true;
617 }
618 };
619
620 /**
621 * State of all active sticky broadcasts. Keys are the action of the
622 * sticky Intent, values are an ArrayList of all broadcasted intents with
623 * that action (which should usually be one).
624 */
625 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
626 new HashMap<String, ArrayList<Intent>>();
627
628 /**
629 * All currently running services.
630 */
631 final HashMap<ComponentName, ServiceRecord> mServices =
632 new HashMap<ComponentName, ServiceRecord>();
633
634 /**
635 * All currently running services indexed by the Intent used to start them.
636 */
637 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
638 new HashMap<Intent.FilterComparison, ServiceRecord>();
639
640 /**
641 * All currently bound service connections. Keys are the IBinder of
642 * the client's IServiceConnection.
643 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700644 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
645 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646
647 /**
648 * List of services that we have been asked to start,
649 * but haven't yet been able to. It is used to hold start requests
650 * while waiting for their corresponding application thread to get
651 * going.
652 */
653 final ArrayList<ServiceRecord> mPendingServices
654 = new ArrayList<ServiceRecord>();
655
656 /**
657 * List of services that are scheduled to restart following a crash.
658 */
659 final ArrayList<ServiceRecord> mRestartingServices
660 = new ArrayList<ServiceRecord>();
661
662 /**
663 * List of services that are in the process of being stopped.
664 */
665 final ArrayList<ServiceRecord> mStoppingServices
666 = new ArrayList<ServiceRecord>();
667
668 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700669 * Backup/restore process management
670 */
671 String mBackupAppName = null;
672 BackupRecord mBackupTarget = null;
673
674 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 * List of PendingThumbnailsRecord objects of clients who are still
676 * waiting to receive all of the thumbnails for a task.
677 */
678 final ArrayList mPendingThumbnails = new ArrayList();
679
680 /**
681 * List of HistoryRecord objects that have been finished and must
682 * still report back to a pending thumbnail receiver.
683 */
684 final ArrayList mCancelledThumbnails = new ArrayList();
685
686 /**
687 * All of the currently running global content providers. Keys are a
688 * string containing the provider name and values are a
689 * ContentProviderRecord object containing the data about it. Note
690 * that a single provider may be published under multiple names, so
691 * there may be multiple entries here for a single one in mProvidersByClass.
692 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700693 final HashMap<String, ContentProviderRecord> mProvidersByName
694 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695
696 /**
697 * All of the currently running global content providers. Keys are a
698 * string containing the provider's implementation class and values are a
699 * ContentProviderRecord object containing the data about it.
700 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700701 final HashMap<String, ContentProviderRecord> mProvidersByClass
702 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703
704 /**
705 * List of content providers who have clients waiting for them. The
706 * application is currently being launched and the provider will be
707 * removed from this list once it is published.
708 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700709 final ArrayList<ContentProviderRecord> mLaunchingProviders
710 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711
712 /**
713 * Global set of specific Uri permissions that have been granted.
714 */
715 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
716 = new SparseArray<HashMap<Uri, UriPermission>>();
717
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800718 CoreSettingsObserver mCoreSettingsObserver;
719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 /**
721 * Thread-local storage used to carry caller permissions over through
722 * indirect content-provider access.
723 * @see #ActivityManagerService.openContentUri()
724 */
725 private class Identity {
726 public int pid;
727 public int uid;
728
729 Identity(int _pid, int _uid) {
730 pid = _pid;
731 uid = _uid;
732 }
733 }
734 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
735
736 /**
737 * All information we have collected about the runtime performance of
738 * any user id that can impact battery performance.
739 */
740 final BatteryStatsService mBatteryStatsService;
741
742 /**
743 * information about component usage
744 */
745 final UsageStatsService mUsageStatsService;
746
747 /**
748 * Current configuration information. HistoryRecord objects are given
749 * a reference to this object to indicate which configuration they are
750 * currently running in, so this object must be kept immutable.
751 */
752 Configuration mConfiguration = new Configuration();
753
754 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800755 * Current sequencing integer of the configuration, for skipping old
756 * configurations.
757 */
758 int mConfigurationSeq = 0;
759
760 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700761 * Hardware-reported OpenGLES version.
762 */
763 final int GL_ES_VERSION;
764
765 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 * List of initialization arguments to pass to all processes when binding applications to them.
767 * For example, references to the commonly used services.
768 */
769 HashMap<String, IBinder> mAppBindArgs;
770
771 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700772 * Temporary to avoid allocations. Protected by main lock.
773 */
774 final StringBuilder mStringBuilder = new StringBuilder(256);
775
776 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 * Used to control how we initialize the service.
778 */
779 boolean mStartRunning = false;
780 ComponentName mTopComponent;
781 String mTopAction;
782 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700783 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 boolean mSystemReady = false;
785 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700786 boolean mWaitingUpdate = false;
787 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700788 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700789 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 Context mContext;
792
793 int mFactoryTest;
794
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700795 boolean mCheckedForSetup;
796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700798 * The time at which we will allow normal application switches again,
799 * after a call to {@link #stopAppSwitches()}.
800 */
801 long mAppSwitchesAllowedTime;
802
803 /**
804 * This is set to true after the first switch after mAppSwitchesAllowedTime
805 * is set; any switches after that will clear the time.
806 */
807 boolean mDidAppSwitch;
808
809 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700810 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700811 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700812 long mLastPowerCheckRealtime;
813
814 /**
815 * Last time (in uptime) at which we checked for power usage.
816 */
817 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700818
819 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 * Set while we are wanting to sleep, to prevent any
821 * activities from being started/resumed.
822 */
823 boolean mSleeping = false;
824
825 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700826 * Set if we are shutting down the system, similar to sleeping.
827 */
828 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
830 /**
831 * Task identifier that activities are currently being started
832 * in. Incremented each time a new task is created.
833 * todo: Replace this with a TokenSpace class that generates non-repeating
834 * integers that won't wrap.
835 */
836 int mCurTask = 1;
837
838 /**
839 * Current sequence id for oom_adj computation traversal.
840 */
841 int mAdjSeq = 0;
842
843 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700844 * Current sequence id for process LRU updating.
845 */
846 int mLruSeq = 0;
847
848 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
850 * is set, indicating the user wants processes started in such a way
851 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
852 * running in each process (thus no pre-initialized process, etc).
853 */
854 boolean mSimpleProcessManagement = false;
855
856 /**
857 * System monitoring: number of processes that died since the last
858 * N procs were started.
859 */
860 int[] mProcDeaths = new int[20];
861
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700862 /**
863 * This is set if we had to do a delayed dexopt of an app before launching
864 * it, to increasing the ANR timeouts in that case.
865 */
866 boolean mDidDexOpt;
867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 String mDebugApp = null;
869 boolean mWaitForDebugger = false;
870 boolean mDebugTransient = false;
871 String mOrigDebugApp = null;
872 boolean mOrigWaitForDebugger = false;
873 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700874 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700876 final RemoteCallbackList<IActivityWatcher> mWatchers
877 = new RemoteCallbackList<IActivityWatcher>();
878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 /**
880 * Callback of last caller to {@link #requestPss}.
881 */
882 Runnable mRequestPssCallback;
883
884 /**
885 * Remaining processes for which we are waiting results from the last
886 * call to {@link #requestPss}.
887 */
888 final ArrayList<ProcessRecord> mRequestPssList
889 = new ArrayList<ProcessRecord>();
890
891 /**
892 * Runtime statistics collection thread. This object's lock is used to
893 * protect all related state.
894 */
895 final Thread mProcessStatsThread;
896
897 /**
898 * Used to collect process stats when showing not responding dialog.
899 * Protected by mProcessStatsThread.
900 */
901 final ProcessStats mProcessStats = new ProcessStats(
902 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700903 final AtomicLong mLastCpuTime = new AtomicLong(0);
904 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 long mLastWriteTime = 0;
907
908 /**
909 * Set to true after the system has finished booting.
910 */
911 boolean mBooted = false;
912
913 int mProcessLimit = 0;
914
915 WindowManagerService mWindowManager;
916
917 static ActivityManagerService mSelf;
918 static ActivityThread mSystemThread;
919
920 private final class AppDeathRecipient implements IBinder.DeathRecipient {
921 final ProcessRecord mApp;
922 final int mPid;
923 final IApplicationThread mAppThread;
924
925 AppDeathRecipient(ProcessRecord app, int pid,
926 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 TAG, "New death recipient " + this
929 + " for thread " + thread.asBinder());
930 mApp = app;
931 mPid = pid;
932 mAppThread = thread;
933 }
934
935 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800936 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 TAG, "Death received in " + this
938 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 synchronized(ActivityManagerService.this) {
940 appDiedLocked(mApp, mPid, mAppThread);
941 }
942 }
943 }
944
945 static final int SHOW_ERROR_MSG = 1;
946 static final int SHOW_NOT_RESPONDING_MSG = 2;
947 static final int SHOW_FACTORY_ERROR_MSG = 3;
948 static final int UPDATE_CONFIGURATION_MSG = 4;
949 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
950 static final int WAIT_FOR_DEBUGGER_MSG = 6;
951 static final int BROADCAST_INTENT_MSG = 7;
952 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 static final int SERVICE_TIMEOUT_MSG = 12;
954 static final int UPDATE_TIME_ZONE = 13;
955 static final int SHOW_UID_ERROR_MSG = 14;
956 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700958 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700959 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800960 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700961 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
962 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700963 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700964 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700965 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700966 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967
968 AlertDialog mUidAlert;
969
970 final Handler mHandler = new Handler() {
971 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800972 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 //}
974
975 public void handleMessage(Message msg) {
976 switch (msg.what) {
977 case SHOW_ERROR_MSG: {
978 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 synchronized (ActivityManagerService.this) {
980 ProcessRecord proc = (ProcessRecord)data.get("app");
981 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800982 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 return;
984 }
985 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700986 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800987 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 d.show();
989 proc.crashDialog = d;
990 } else {
991 // The device is asleep, so just pretend that the user
992 // saw a crash dialog and hit "force quit".
993 res.set(0);
994 }
995 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700996
997 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 } break;
999 case SHOW_NOT_RESPONDING_MSG: {
1000 synchronized (ActivityManagerService.this) {
1001 HashMap data = (HashMap) msg.obj;
1002 ProcessRecord proc = (ProcessRecord)data.get("app");
1003 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001004 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 return;
1006 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001007
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001008 Intent intent = new Intent("android.intent.action.ANR");
1009 if (!mProcessesReady) {
1010 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1011 }
1012 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001013 null, null, 0, null, null, null,
1014 false, false, MY_PID, Process.SYSTEM_UID);
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001017 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 d.show();
1019 proc.anrDialog = d;
1020 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001021
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001022 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001024 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1025 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1026 synchronized (ActivityManagerService.this) {
1027 ProcessRecord proc = (ProcessRecord) data.get("app");
1028 if (proc == null) {
1029 Slog.e(TAG, "App not found when showing strict mode dialog.");
1030 break;
1031 }
1032 if (proc.crashDialog != null) {
1033 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1034 return;
1035 }
1036 AppErrorResult res = (AppErrorResult) data.get("result");
1037 if (!mSleeping && !mShuttingDown) {
1038 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1039 d.show();
1040 proc.crashDialog = d;
1041 } else {
1042 // The device is asleep, so just pretend that the user
1043 // saw a crash dialog and hit "force quit".
1044 res.set(0);
1045 }
1046 }
1047 ensureBootCompleted();
1048 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 case SHOW_FACTORY_ERROR_MSG: {
1050 Dialog d = new FactoryErrorDialog(
1051 mContext, msg.getData().getCharSequence("msg"));
1052 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001053 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
1055 case UPDATE_CONFIGURATION_MSG: {
1056 final ContentResolver resolver = mContext.getContentResolver();
1057 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1058 } break;
1059 case GC_BACKGROUND_PROCESSES_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 performAppGcsIfAppropriateLocked();
1062 }
1063 } break;
1064 case WAIT_FOR_DEBUGGER_MSG: {
1065 synchronized (ActivityManagerService.this) {
1066 ProcessRecord app = (ProcessRecord)msg.obj;
1067 if (msg.arg1 != 0) {
1068 if (!app.waitedForDebugger) {
1069 Dialog d = new AppWaitingForDebuggerDialog(
1070 ActivityManagerService.this,
1071 mContext, app);
1072 app.waitDialog = d;
1073 app.waitedForDebugger = true;
1074 d.show();
1075 }
1076 } else {
1077 if (app.waitDialog != null) {
1078 app.waitDialog.dismiss();
1079 app.waitDialog = null;
1080 }
1081 }
1082 }
1083 } break;
1084 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001085 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 TAG, "Received BROADCAST_INTENT_MSG");
1087 processNextBroadcast(true);
1088 } break;
1089 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001090 synchronized (ActivityManagerService.this) {
1091 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001095 if (mDidDexOpt) {
1096 mDidDexOpt = false;
1097 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1098 nmsg.obj = msg.obj;
1099 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1100 return;
1101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 serviceTimeout((ProcessRecord)msg.obj);
1103 } break;
1104 case UPDATE_TIME_ZONE: {
1105 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001106 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1107 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 if (r.thread != null) {
1109 try {
1110 r.thread.updateTimeZone();
1111 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001112 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 }
1114 }
1115 }
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001118 case CLEAR_DNS_CACHE: {
1119 synchronized (ActivityManagerService.this) {
1120 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1121 ProcessRecord r = mLruProcesses.get(i);
1122 if (r.thread != null) {
1123 try {
1124 r.thread.clearDnsCache();
1125 } catch (RemoteException ex) {
1126 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1127 }
1128 }
1129 }
1130 }
1131 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001132 case UPDATE_HTTP_PROXY: {
1133 ProxyProperties proxy = (ProxyProperties)msg.obj;
1134 String host = "";
1135 String port = "";
1136 String exclList = "";
1137 if (proxy != null) {
1138 host = proxy.getHost();
1139 port = Integer.toString(proxy.getPort());
1140 exclList = proxy.getExclusionList();
1141 }
1142 synchronized (ActivityManagerService.this) {
1143 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1144 ProcessRecord r = mLruProcesses.get(i);
1145 if (r.thread != null) {
1146 try {
1147 r.thread.setHttpProxy(host, port, exclList);
1148 } catch (RemoteException ex) {
1149 Slog.w(TAG, "Failed to update http proxy for: " +
1150 r.info.processName);
1151 }
1152 }
1153 }
1154 }
1155 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 case SHOW_UID_ERROR_MSG: {
1157 // XXX This is a temporary dialog, no need to localize.
1158 AlertDialog d = new BaseErrorDialog(mContext);
1159 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1160 d.setCancelable(false);
1161 d.setTitle("System UIDs Inconsistent");
1162 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 +02001163 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1165 mUidAlert = d;
1166 d.show();
1167 } break;
1168 case IM_FEELING_LUCKY_MSG: {
1169 if (mUidAlert != null) {
1170 mUidAlert.dismiss();
1171 mUidAlert = null;
1172 }
1173 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001175 if (mDidDexOpt) {
1176 mDidDexOpt = false;
1177 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1178 nmsg.obj = msg.obj;
1179 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1180 return;
1181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 ProcessRecord app = (ProcessRecord)msg.obj;
1183 synchronized (ActivityManagerService.this) {
1184 processStartTimedOutLocked(app);
1185 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001186 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001187 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1188 synchronized (ActivityManagerService.this) {
1189 doPendingActivityLaunchesLocked(true);
1190 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001191 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001192 case KILL_APPLICATION_MSG: {
1193 synchronized (ActivityManagerService.this) {
1194 int uid = msg.arg1;
1195 boolean restart = (msg.arg2 == 1);
1196 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001197 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001198 }
1199 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001200 case FINALIZE_PENDING_INTENT_MSG: {
1201 ((PendingIntentRecord)msg.obj).completeFinalize();
1202 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001203 case POST_HEAVY_NOTIFICATION_MSG: {
1204 INotificationManager inm = NotificationManager.getService();
1205 if (inm == null) {
1206 return;
1207 }
1208
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001209 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001210 ProcessRecord process = root.app;
1211 if (process == null) {
1212 return;
1213 }
1214
1215 try {
1216 Context context = mContext.createPackageContext(process.info.packageName, 0);
1217 String text = mContext.getString(R.string.heavy_weight_notification,
1218 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1219 Notification notification = new Notification();
1220 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1221 notification.when = 0;
1222 notification.flags = Notification.FLAG_ONGOING_EVENT;
1223 notification.tickerText = text;
1224 notification.defaults = 0; // please be quiet
1225 notification.sound = null;
1226 notification.vibrate = null;
1227 notification.setLatestEventInfo(context, text,
1228 mContext.getText(R.string.heavy_weight_notification_detail),
1229 PendingIntent.getActivity(mContext, 0, root.intent,
1230 PendingIntent.FLAG_CANCEL_CURRENT));
1231
1232 try {
1233 int[] outId = new int[1];
1234 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1235 notification, outId);
1236 } catch (RuntimeException e) {
1237 Slog.w(ActivityManagerService.TAG,
1238 "Error showing notification for heavy-weight app", e);
1239 } catch (RemoteException e) {
1240 }
1241 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001242 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001243 }
1244 } break;
1245 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1246 INotificationManager inm = NotificationManager.getService();
1247 if (inm == null) {
1248 return;
1249 }
1250 try {
1251 inm.cancelNotification("android",
1252 R.string.heavy_weight_notification);
1253 } catch (RuntimeException e) {
1254 Slog.w(ActivityManagerService.TAG,
1255 "Error canceling notification for service", e);
1256 } catch (RemoteException e) {
1257 }
1258 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001259 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1260 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001261 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001262 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001263 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1264 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001265 }
1266 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 }
1268 }
1269 };
1270
1271 public static void setSystemProcess() {
1272 try {
1273 ActivityManagerService m = mSelf;
1274
1275 ServiceManager.addService("activity", m);
1276 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001277 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 if (MONITOR_CPU_USAGE) {
1279 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 ServiceManager.addService("permission", new PermissionController(m));
1282
1283 ApplicationInfo info =
1284 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001285 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001286 mSystemThread.installSystemApplicationInfo(info);
1287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 synchronized (mSelf) {
1289 ProcessRecord app = mSelf.newProcessRecordLocked(
1290 mSystemThread.getApplicationThread(), info,
1291 info.processName);
1292 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001293 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 app.maxAdj = SYSTEM_ADJ;
1295 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1296 synchronized (mSelf.mPidsSelfLocked) {
1297 mSelf.mPidsSelfLocked.put(app.pid, app);
1298 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001299 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001300 }
1301 } catch (PackageManager.NameNotFoundException e) {
1302 throw new RuntimeException(
1303 "Unable to find android system package", e);
1304 }
1305 }
1306
1307 public void setWindowManager(WindowManagerService wm) {
1308 mWindowManager = wm;
1309 }
1310
1311 public static final Context main(int factoryTest) {
1312 AThread thr = new AThread();
1313 thr.start();
1314
1315 synchronized (thr) {
1316 while (thr.mService == null) {
1317 try {
1318 thr.wait();
1319 } catch (InterruptedException e) {
1320 }
1321 }
1322 }
1323
1324 ActivityManagerService m = thr.mService;
1325 mSelf = m;
1326 ActivityThread at = ActivityThread.systemMain();
1327 mSystemThread = at;
1328 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001329 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 m.mContext = context;
1331 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001332 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333
1334 m.mBatteryStatsService.publish(context);
1335 m.mUsageStatsService.publish(context);
1336
1337 synchronized (thr) {
1338 thr.mReady = true;
1339 thr.notifyAll();
1340 }
1341
1342 m.startRunning(null, null, null, null);
1343
1344 return context;
1345 }
1346
1347 public static ActivityManagerService self() {
1348 return mSelf;
1349 }
1350
1351 static class AThread extends Thread {
1352 ActivityManagerService mService;
1353 boolean mReady = false;
1354
1355 public AThread() {
1356 super("ActivityManager");
1357 }
1358
1359 public void run() {
1360 Looper.prepare();
1361
1362 android.os.Process.setThreadPriority(
1363 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001364 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365
1366 ActivityManagerService m = new ActivityManagerService();
1367
1368 synchronized (this) {
1369 mService = m;
1370 notifyAll();
1371 }
1372
1373 synchronized (this) {
1374 while (!mReady) {
1375 try {
1376 wait();
1377 } catch (InterruptedException e) {
1378 }
1379 }
1380 }
1381
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001382 // For debug builds, log event loop stalls to dropbox for analysis.
1383 if (StrictMode.conditionallyEnableDebugLogging()) {
1384 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1385 }
1386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 Looper.loop();
1388 }
1389 }
1390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 static class MemBinder extends Binder {
1392 ActivityManagerService mActivityManagerService;
1393 MemBinder(ActivityManagerService activityManagerService) {
1394 mActivityManagerService = activityManagerService;
1395 }
1396
1397 @Override
1398 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001399 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 }
1401 }
1402
Chet Haase9c1e23b2011-03-24 10:51:31 -07001403 static class GraphicsBinder extends Binder {
1404 ActivityManagerService mActivityManagerService;
1405 GraphicsBinder(ActivityManagerService activityManagerService) {
1406 mActivityManagerService = activityManagerService;
1407 }
1408
1409 @Override
1410 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001411 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001412 }
1413 }
1414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 static class CpuBinder extends Binder {
1416 ActivityManagerService mActivityManagerService;
1417 CpuBinder(ActivityManagerService activityManagerService) {
1418 mActivityManagerService = activityManagerService;
1419 }
1420
1421 @Override
1422 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1423 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001424 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1425 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1426 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 }
1428 }
1429 }
1430
1431 private ActivityManagerService() {
1432 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1433 if (v != null && Integer.getInteger(v) != 0) {
1434 mSimpleProcessManagement = true;
1435 }
1436 v = System.getenv("ANDROID_DEBUG_APP");
1437 if (v != null) {
1438 mSimpleProcessManagement = true;
1439 }
1440
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 File dataDir = Environment.getDataDirectory();
1444 File systemDir = new File(dataDir, "system");
1445 systemDir.mkdirs();
1446 mBatteryStatsService = new BatteryStatsService(new File(
1447 systemDir, "batterystats.bin").toString());
1448 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001449 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001450 mOnBattery = DEBUG_POWER ? true
1451 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001452 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001454 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001455 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456
Jack Palevichb90d28c2009-07-22 15:35:24 -07001457 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1458 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1459
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001460 mConfiguration.setToDefaults();
1461 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 mProcessStats.init();
1463
1464 // Add ourself to the Watchdog monitors.
1465 Watchdog.getInstance().addMonitor(this);
1466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 mProcessStatsThread = new Thread("ProcessStats") {
1468 public void run() {
1469 while (true) {
1470 try {
1471 try {
1472 synchronized(this) {
1473 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001474 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 // + ", write delay=" + nextWriteDelay);
1478 if (nextWriteDelay < nextCpuDelay) {
1479 nextCpuDelay = nextWriteDelay;
1480 }
1481 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001482 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 this.wait(nextCpuDelay);
1484 }
1485 }
1486 } catch (InterruptedException e) {
1487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 updateCpuStatsNow();
1489 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 }
1492 }
1493 }
1494 };
1495 mProcessStatsThread.start();
1496 }
1497
1498 @Override
1499 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1500 throws RemoteException {
1501 try {
1502 return super.onTransact(code, data, reply, flags);
1503 } catch (RuntimeException e) {
1504 // The activity manager only throws security exceptions, so let's
1505 // log all others.
1506 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001507 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 }
1509 throw e;
1510 }
1511 }
1512
1513 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001514 final long now = SystemClock.uptimeMillis();
1515 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1516 return;
1517 }
1518 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1519 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 mProcessStatsThread.notify();
1521 }
1522 }
1523 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 void updateCpuStatsNow() {
1526 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001527 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 final long now = SystemClock.uptimeMillis();
1529 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001532 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1533 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 haveNewCpuStats = true;
1535 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001536 //Slog.i(TAG, mProcessStats.printCurrentState());
1537 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 // + mProcessStats.getTotalCpuPercent() + "%");
1539
Joe Onorato8a9b2202010-02-26 18:56:32 -08001540 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 if ("true".equals(SystemProperties.get("events.cpu"))) {
1542 int user = mProcessStats.getLastUserTime();
1543 int system = mProcessStats.getLastSystemTime();
1544 int iowait = mProcessStats.getLastIoWaitTime();
1545 int irq = mProcessStats.getLastIrqTime();
1546 int softIrq = mProcessStats.getLastSoftIrqTime();
1547 int idle = mProcessStats.getLastIdleTime();
1548
1549 int total = user + system + iowait + irq + softIrq + idle;
1550 if (total == 0) total = 1;
1551
Doug Zongker2bec3d42009-12-04 12:52:44 -08001552 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 ((user+system+iowait+irq+softIrq) * 100) / total,
1554 (user * 100) / total,
1555 (system * 100) / total,
1556 (iowait * 100) / total,
1557 (irq * 100) / total,
1558 (softIrq * 100) / total);
1559 }
1560 }
1561
Amith Yamasanie43530a2009-08-21 13:11:37 -07001562 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001563 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001564 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 synchronized(mPidsSelfLocked) {
1566 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001567 if (mOnBattery) {
1568 int perc = bstats.startAddingCpuLocked();
1569 int totalUTime = 0;
1570 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001571 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001573 ProcessStats.Stats st = mProcessStats.getStats(i);
1574 if (!st.working) {
1575 continue;
1576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001578 int otherUTime = (st.rel_utime*perc)/100;
1579 int otherSTime = (st.rel_stime*perc)/100;
1580 totalUTime += otherUTime;
1581 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 if (pr != null) {
1583 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001584 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1585 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001586 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001587 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001588 } else {
1589 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001590 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001591 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001592 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1593 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001594 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 }
1597 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 bstats.finishAddingCpuLocked(perc, totalUTime,
1599 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 }
1601 }
1602 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1605 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001606 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 }
1608 }
1609 }
1610 }
1611
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001612 @Override
1613 public void batteryNeedsCpuUpdate() {
1614 updateCpuStatsNow();
1615 }
1616
1617 @Override
1618 public void batteryPowerChanged(boolean onBattery) {
1619 // When plugging in, update the CPU stats first before changing
1620 // the plug state.
1621 updateCpuStatsNow();
1622 synchronized (this) {
1623 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001624 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001625 }
1626 }
1627 }
1628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 /**
1630 * Initialize the application bind args. These are passed to each
1631 * process when the bindApplication() IPC is sent to the process. They're
1632 * lazily setup to make sure the services are running when they're asked for.
1633 */
1634 private HashMap<String, IBinder> getCommonServicesLocked() {
1635 if (mAppBindArgs == null) {
1636 mAppBindArgs = new HashMap<String, IBinder>();
1637
1638 // Setup the application init args
1639 mAppBindArgs.put("package", ServiceManager.getService("package"));
1640 mAppBindArgs.put("window", ServiceManager.getService("window"));
1641 mAppBindArgs.put(Context.ALARM_SERVICE,
1642 ServiceManager.getService(Context.ALARM_SERVICE));
1643 }
1644 return mAppBindArgs;
1645 }
1646
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001647 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 if (mFocusedActivity != r) {
1649 mFocusedActivity = r;
1650 mWindowManager.setFocusedApp(r, true);
1651 }
1652 }
1653
Dianne Hackborn906497c2010-05-10 15:57:38 -07001654 private final void updateLruProcessInternalLocked(ProcessRecord app,
1655 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001657 int lrui = mLruProcesses.indexOf(app);
1658 if (lrui >= 0) mLruProcesses.remove(lrui);
1659
1660 int i = mLruProcesses.size()-1;
1661 int skipTop = 0;
1662
Dianne Hackborn906497c2010-05-10 15:57:38 -07001663 app.lruSeq = mLruSeq;
1664
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001665 // compute the new weight for this process.
1666 if (updateActivityTime) {
1667 app.lastActivityTime = SystemClock.uptimeMillis();
1668 }
1669 if (app.activities.size() > 0) {
1670 // If this process has activities, we more strongly want to keep
1671 // it around.
1672 app.lruWeight = app.lastActivityTime;
1673 } else if (app.pubProviders.size() > 0) {
1674 // If this process contains content providers, we want to keep
1675 // it a little more strongly.
1676 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1677 // Also don't let it kick out the first few "real" hidden processes.
1678 skipTop = MIN_HIDDEN_APPS;
1679 } else {
1680 // If this process doesn't have activities, we less strongly
1681 // want to keep it around, and generally want to avoid getting
1682 // in front of any very recently used activities.
1683 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1684 // Also don't let it kick out the first few "real" hidden processes.
1685 skipTop = MIN_HIDDEN_APPS;
1686 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001687
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001688 while (i >= 0) {
1689 ProcessRecord p = mLruProcesses.get(i);
1690 // If this app shouldn't be in front of the first N background
1691 // apps, then skip over that many that are currently hidden.
1692 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1693 skipTop--;
1694 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001695 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001696 mLruProcesses.add(i+1, app);
1697 break;
1698 }
1699 i--;
1700 }
1701 if (i < 0) {
1702 mLruProcesses.add(0, app);
1703 }
1704
Dianne Hackborn906497c2010-05-10 15:57:38 -07001705 // If the app is currently using a content provider or service,
1706 // bump those processes as well.
1707 if (app.connections.size() > 0) {
1708 for (ConnectionRecord cr : app.connections) {
1709 if (cr.binding != null && cr.binding.service != null
1710 && cr.binding.service.app != null
1711 && cr.binding.service.app.lruSeq != mLruSeq) {
1712 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1713 updateActivityTime, i+1);
1714 }
1715 }
1716 }
1717 if (app.conProviders.size() > 0) {
1718 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1719 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1720 updateLruProcessInternalLocked(cpr.app, oomAdj,
1721 updateActivityTime, i+1);
1722 }
1723 }
1724 }
1725
Joe Onorato8a9b2202010-02-26 18:56:32 -08001726 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 if (oomAdj) {
1728 updateOomAdjLocked();
1729 }
1730 }
1731
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001732 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001733 boolean oomAdj, boolean updateActivityTime) {
1734 mLruSeq++;
1735 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1736 }
1737
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001738 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 String processName, int uid) {
1740 if (uid == Process.SYSTEM_UID) {
1741 // The system gets to run in any process. If there are multiple
1742 // processes with the same uid, just pick the first (this
1743 // should never happen).
1744 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1745 processName);
1746 return procs != null ? procs.valueAt(0) : null;
1747 }
1748 ProcessRecord proc = mProcessNames.get(processName, uid);
1749 return proc;
1750 }
1751
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001752 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001753 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001754 try {
1755 if (pm.performDexOpt(packageName)) {
1756 mDidDexOpt = true;
1757 }
1758 } catch (RemoteException e) {
1759 }
1760 }
1761
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001762 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 int transit = mWindowManager.getPendingAppTransition();
1764 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1765 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1766 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1767 }
1768
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001769 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001771 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1773 // We don't have to do anything more if:
1774 // (1) There is an existing application record; and
1775 // (2) The caller doesn't think it is dead, OR there is no thread
1776 // object attached to it so we know it couldn't have crashed; and
1777 // (3) There is a pid assigned to it, so it is either starting or
1778 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001779 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 + " app=" + app + " knownToBeDead=" + knownToBeDead
1781 + " thread=" + (app != null ? app.thread : null)
1782 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001783 if (app != null && app.pid > 0) {
1784 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001785 // We already have the app running, or are waiting for it to
1786 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001787 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001788 return app;
1789 } else {
1790 // An application record is attached to a previous process,
1791 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001792 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001793 handleAppDiedLocked(app, true);
1794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 String hostingNameStr = hostingName != null
1798 ? hostingName.flattenToShortString() : null;
1799
1800 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1801 // If we are in the background, then check to see if this process
1802 // is bad. If so, we will just silently fail.
1803 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001804 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1805 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 return null;
1807 }
1808 } else {
1809 // When the user is explicitly starting a process, then clear its
1810 // crash count so that we won't make it bad until they see at
1811 // least one crash dialog again, and make the process good again
1812 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001813 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1814 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 mProcessCrashTimes.remove(info.processName, info.uid);
1816 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001817 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 info.processName);
1819 mBadProcesses.remove(info.processName, info.uid);
1820 if (app != null) {
1821 app.bad = false;
1822 }
1823 }
1824 }
1825
1826 if (app == null) {
1827 app = newProcessRecordLocked(null, info, processName);
1828 mProcessNames.put(processName, info.uid, app);
1829 } else {
1830 // If this is a new package in the process, add the package to the list
1831 app.addPackage(info.packageName);
1832 }
1833
1834 // If the system is not ready yet, then hold off on starting this
1835 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001836 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001837 && !isAllowedWhileBooting(info)
1838 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 if (!mProcessesOnHold.contains(app)) {
1840 mProcessesOnHold.add(app);
1841 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001842 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 return app;
1844 }
1845
1846 startProcessLocked(app, hostingType, hostingNameStr);
1847 return (app.pid != 0) ? app : null;
1848 }
1849
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001850 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1851 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1852 }
1853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 private final void startProcessLocked(ProcessRecord app,
1855 String hostingType, String hostingNameStr) {
1856 if (app.pid > 0 && app.pid != MY_PID) {
1857 synchronized (mPidsSelfLocked) {
1858 mPidsSelfLocked.remove(app.pid);
1859 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1860 }
1861 app.pid = 0;
1862 }
1863
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001864 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1865 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 mProcessesOnHold.remove(app);
1867
1868 updateCpuStats();
1869
1870 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1871 mProcDeaths[0] = 0;
1872
1873 try {
1874 int uid = app.info.uid;
1875 int[] gids = null;
1876 try {
1877 gids = mContext.getPackageManager().getPackageGids(
1878 app.info.packageName);
1879 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001880 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 }
1882 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1883 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1884 && mTopComponent != null
1885 && app.processName.equals(mTopComponent.getPackageName())) {
1886 uid = 0;
1887 }
1888 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1889 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1890 uid = 0;
1891 }
1892 }
1893 int debugFlags = 0;
1894 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1895 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1896 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001897 // Run the app in safe mode if its manifest requests so or the
1898 // system is booted in safe mode.
1899 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1900 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001901 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1904 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1905 }
1906 if ("1".equals(SystemProperties.get("debug.assert"))) {
1907 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1908 }
1909 int pid = Process.start("android.app.ActivityThread",
1910 mSimpleProcessManagement ? app.processName : null, uid, uid,
1911 gids, debugFlags, null);
1912 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1913 synchronized (bs) {
1914 if (bs.isOnBattery()) {
1915 app.batteryStats.incStartsLocked();
1916 }
1917 }
1918
Doug Zongker2bec3d42009-12-04 12:52:44 -08001919 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 app.processName, hostingType,
1921 hostingNameStr != null ? hostingNameStr : "");
1922
1923 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001924 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 }
1926
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001927 StringBuilder buf = mStringBuilder;
1928 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 buf.append("Start proc ");
1930 buf.append(app.processName);
1931 buf.append(" for ");
1932 buf.append(hostingType);
1933 if (hostingNameStr != null) {
1934 buf.append(" ");
1935 buf.append(hostingNameStr);
1936 }
1937 buf.append(": pid=");
1938 buf.append(pid);
1939 buf.append(" uid=");
1940 buf.append(uid);
1941 buf.append(" gids={");
1942 if (gids != null) {
1943 for (int gi=0; gi<gids.length; gi++) {
1944 if (gi != 0) buf.append(", ");
1945 buf.append(gids[gi]);
1946
1947 }
1948 }
1949 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001950 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 if (pid == 0 || pid == MY_PID) {
1952 // Processes are being emulated with threads.
1953 app.pid = MY_PID;
1954 app.removed = false;
1955 mStartingProcesses.add(app);
1956 } else if (pid > 0) {
1957 app.pid = pid;
1958 app.removed = false;
1959 synchronized (mPidsSelfLocked) {
1960 this.mPidsSelfLocked.put(pid, app);
1961 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1962 msg.obj = app;
1963 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1964 }
1965 } else {
1966 app.pid = 0;
1967 RuntimeException e = new RuntimeException(
1968 "Failure starting process " + app.processName
1969 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001970 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 }
1972 } catch (RuntimeException e) {
1973 // XXX do better error recovery.
1974 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001975 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 }
1977 }
1978
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001979 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 if (resumed) {
1981 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1982 } else {
1983 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1984 }
1985 }
1986
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001987 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001988 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1989 && mTopAction == null) {
1990 // We are running in factory test mode, but unable to find
1991 // the factory test app, so just sit around displaying the
1992 // error message and don't try to start anything.
1993 return false;
1994 }
1995 Intent intent = new Intent(
1996 mTopAction,
1997 mTopData != null ? Uri.parse(mTopData) : null);
1998 intent.setComponent(mTopComponent);
1999 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2000 intent.addCategory(Intent.CATEGORY_HOME);
2001 }
2002 ActivityInfo aInfo =
2003 intent.resolveActivityInfo(mContext.getPackageManager(),
2004 STOCK_PM_FLAGS);
2005 if (aInfo != null) {
2006 intent.setComponent(new ComponentName(
2007 aInfo.applicationInfo.packageName, aInfo.name));
2008 // Don't do this if the home app is currently being
2009 // instrumented.
2010 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2011 aInfo.applicationInfo.uid);
2012 if (app == null || app.instrumentationClass == null) {
2013 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002014 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002015 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002016 }
2017 }
2018
2019
2020 return true;
2021 }
2022
2023 /**
2024 * Starts the "new version setup screen" if appropriate.
2025 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002026 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002027 // Only do this once per boot.
2028 if (mCheckedForSetup) {
2029 return;
2030 }
2031
2032 // We will show this screen if the current one is a different
2033 // version than the last one shown, and we are not running in
2034 // low-level factory test mode.
2035 final ContentResolver resolver = mContext.getContentResolver();
2036 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2037 Settings.Secure.getInt(resolver,
2038 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2039 mCheckedForSetup = true;
2040
2041 // See if we should be showing the platform update setup UI.
2042 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2043 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2044 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2045
2046 // We don't allow third party apps to replace this.
2047 ResolveInfo ri = null;
2048 for (int i=0; ris != null && i<ris.size(); i++) {
2049 if ((ris.get(i).activityInfo.applicationInfo.flags
2050 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2051 ri = ris.get(i);
2052 break;
2053 }
2054 }
2055
2056 if (ri != null) {
2057 String vers = ri.activityInfo.metaData != null
2058 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2059 : null;
2060 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2061 vers = ri.activityInfo.applicationInfo.metaData.getString(
2062 Intent.METADATA_SETUP_VERSION);
2063 }
2064 String lastVers = Settings.Secure.getString(
2065 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2066 if (vers != null && !vers.equals(lastVers)) {
2067 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2068 intent.setComponent(new ComponentName(
2069 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002071 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002072 }
2073 }
2074 }
2075 }
2076
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002077 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002078 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002079
2080 final int identHash = System.identityHashCode(r);
2081 updateUsageStats(r, true);
2082
2083 int i = mWatchers.beginBroadcast();
2084 while (i > 0) {
2085 i--;
2086 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2087 if (w != null) {
2088 try {
2089 w.activityResuming(identHash);
2090 } catch (RemoteException e) {
2091 }
2092 }
2093 }
2094 mWatchers.finishBroadcast();
2095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002097 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002098 final int N = mPendingActivityLaunches.size();
2099 if (N <= 0) {
2100 return;
2101 }
2102 for (int i=0; i<N; i++) {
2103 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002104 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002105 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2106 doResume && i == (N-1));
2107 }
2108 mPendingActivityLaunches.clear();
2109 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002110
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002111 public final int startActivity(IApplicationThread caller,
2112 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2113 int grantedMode, IBinder resultTo,
2114 String resultWho, int requestCode, boolean onlyIfNeeded,
2115 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002116 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002117 grantedUriPermissions, grantedMode, resultTo, resultWho,
2118 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002119 }
2120
2121 public final WaitResult startActivityAndWait(IApplicationThread caller,
2122 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2123 int grantedMode, IBinder resultTo,
2124 String resultWho, int requestCode, boolean onlyIfNeeded,
2125 boolean debug) {
2126 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002127 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002128 grantedUriPermissions, grantedMode, resultTo, resultWho,
2129 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002130 return res;
2131 }
2132
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002133 public final int startActivityWithConfig(IApplicationThread caller,
2134 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2135 int grantedMode, IBinder resultTo,
2136 String resultWho, int requestCode, boolean onlyIfNeeded,
2137 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002138 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002139 grantedUriPermissions, grantedMode, resultTo, resultWho,
2140 requestCode, onlyIfNeeded, debug, null, config);
2141 }
2142
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002143 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002144 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002145 IBinder resultTo, String resultWho, int requestCode,
2146 int flagsMask, int flagsValues) {
2147 // Refuse possible leaked file descriptors
2148 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2149 throw new IllegalArgumentException("File descriptors passed in Intent");
2150 }
2151
2152 IIntentSender sender = intent.getTarget();
2153 if (!(sender instanceof PendingIntentRecord)) {
2154 throw new IllegalArgumentException("Bad PendingIntent object");
2155 }
2156
2157 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002158
2159 synchronized (this) {
2160 // If this is coming from the currently resumed activity, it is
2161 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002162 if (mMainStack.mResumedActivity != null
2163 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002164 Binder.getCallingUid()) {
2165 mAppSwitchesAllowedTime = 0;
2166 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002167 }
2168
2169 return pir.sendInner(0, fillInIntent, resolvedType,
2170 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2171 }
2172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 public boolean startNextMatchingActivity(IBinder callingActivity,
2174 Intent intent) {
2175 // Refuse possible leaked file descriptors
2176 if (intent != null && intent.hasFileDescriptors() == true) {
2177 throw new IllegalArgumentException("File descriptors passed in Intent");
2178 }
2179
2180 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002181 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 if (index < 0) {
2183 return false;
2184 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002185 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 if (r.app == null || r.app.thread == null) {
2187 // The caller is not running... d'oh!
2188 return false;
2189 }
2190 intent = new Intent(intent);
2191 // The caller is not allowed to change the data.
2192 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2193 // And we are resetting to find the next component...
2194 intent.setComponent(null);
2195
2196 ActivityInfo aInfo = null;
2197 try {
2198 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002199 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002201 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202
2203 // Look for the original activity in the list...
2204 final int N = resolves != null ? resolves.size() : 0;
2205 for (int i=0; i<N; i++) {
2206 ResolveInfo rInfo = resolves.get(i);
2207 if (rInfo.activityInfo.packageName.equals(r.packageName)
2208 && rInfo.activityInfo.name.equals(r.info.name)) {
2209 // We found the current one... the next matching is
2210 // after it.
2211 i++;
2212 if (i<N) {
2213 aInfo = resolves.get(i).activityInfo;
2214 }
2215 break;
2216 }
2217 }
2218 } catch (RemoteException e) {
2219 }
2220
2221 if (aInfo == null) {
2222 // Nobody who is next!
2223 return false;
2224 }
2225
2226 intent.setComponent(new ComponentName(
2227 aInfo.applicationInfo.packageName, aInfo.name));
2228 intent.setFlags(intent.getFlags()&~(
2229 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2230 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2231 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2232 Intent.FLAG_ACTIVITY_NEW_TASK));
2233
2234 // Okay now we need to start the new activity, replacing the
2235 // currently running activity. This is a little tricky because
2236 // we want to start the new one as if the current one is finished,
2237 // but not finish the current one first so that there is no flicker.
2238 // And thus...
2239 final boolean wasFinishing = r.finishing;
2240 r.finishing = true;
2241
2242 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002243 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 final String resultWho = r.resultWho;
2245 final int requestCode = r.requestCode;
2246 r.resultTo = null;
2247 if (resultTo != null) {
2248 resultTo.removeResultsLocked(r, resultWho, requestCode);
2249 }
2250
2251 final long origId = Binder.clearCallingIdentity();
2252 // XXX we are not dealing with propagating grantedUriPermissions...
2253 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002254 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002256 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 Binder.restoreCallingIdentity(origId);
2258
2259 r.finishing = wasFinishing;
2260 if (res != START_SUCCESS) {
2261 return false;
2262 }
2263 return true;
2264 }
2265 }
2266
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002267 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 Intent intent, String resolvedType, IBinder resultTo,
2269 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002270
2271 // This is so super not safe, that only the system (or okay root)
2272 // can do it.
2273 final int callingUid = Binder.getCallingUid();
2274 if (callingUid != 0 && callingUid != Process.myUid()) {
2275 throw new SecurityException(
2276 "startActivityInPackage only available to the system");
2277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002279 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2280 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2281 }
2282
2283 public final int startActivities(IApplicationThread caller,
2284 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2285 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2286 }
2287
2288 public final int startActivitiesInPackage(int uid,
2289 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2290
2291 // This is so super not safe, that only the system (or okay root)
2292 // can do it.
2293 final int callingUid = Binder.getCallingUid();
2294 if (callingUid != 0 && callingUid != Process.myUid()) {
2295 throw new SecurityException(
2296 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 }
2298
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002299 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 }
2301
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002302 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002304 // Quick case: check if the top-most recent task is the same.
2305 if (N > 0 && mRecentTasks.get(0) == task) {
2306 return;
2307 }
2308 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 for (int i=0; i<N; i++) {
2310 TaskRecord tr = mRecentTasks.get(i);
2311 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2312 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2313 mRecentTasks.remove(i);
2314 i--;
2315 N--;
2316 if (task.intent == null) {
2317 // If the new recent task we are adding is not fully
2318 // specified, then replace it with the existing recent task.
2319 task = tr;
2320 }
2321 }
2322 }
2323 if (N >= MAX_RECENT_TASKS) {
2324 mRecentTasks.remove(N-1);
2325 }
2326 mRecentTasks.add(0, task);
2327 }
2328
2329 public void setRequestedOrientation(IBinder token,
2330 int requestedOrientation) {
2331 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002332 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 if (index < 0) {
2334 return;
2335 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002336 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 final long origId = Binder.clearCallingIdentity();
2338 mWindowManager.setAppOrientation(r, requestedOrientation);
2339 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002340 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002341 r.mayFreezeScreenLocked(r.app) ? r : null);
2342 if (config != null) {
2343 r.frozenBeforeDestroy = true;
2344 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002345 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 }
2347 }
2348 Binder.restoreCallingIdentity(origId);
2349 }
2350 }
2351
2352 public int getRequestedOrientation(IBinder token) {
2353 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002354 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 if (index < 0) {
2356 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2357 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002358 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 return mWindowManager.getAppOrientation(r);
2360 }
2361 }
2362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 /**
2364 * This is the internal entry point for handling Activity.finish().
2365 *
2366 * @param token The Binder token referencing the Activity we want to finish.
2367 * @param resultCode Result code, if any, from this Activity.
2368 * @param resultData Result data (Intent), if any, from this Activity.
2369 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002370 * @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 -08002371 */
2372 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2373 // Refuse possible leaked file descriptors
2374 if (resultData != null && resultData.hasFileDescriptors() == true) {
2375 throw new IllegalArgumentException("File descriptors passed in Intent");
2376 }
2377
2378 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002379 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002381 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382 if (next != null) {
2383 // ask watcher if this is allowed
2384 boolean resumeOK = true;
2385 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002386 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002388 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 }
2390
2391 if (!resumeOK) {
2392 return false;
2393 }
2394 }
2395 }
2396 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002397 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 resultData, "app-request");
2399 Binder.restoreCallingIdentity(origId);
2400 return res;
2401 }
2402 }
2403
Dianne Hackborn860755f2010-06-03 18:47:52 -07002404 public final void finishHeavyWeightApp() {
2405 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2406 != PackageManager.PERMISSION_GRANTED) {
2407 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2408 + Binder.getCallingPid()
2409 + ", uid=" + Binder.getCallingUid()
2410 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2411 Slog.w(TAG, msg);
2412 throw new SecurityException(msg);
2413 }
2414
2415 synchronized(this) {
2416 if (mHeavyWeightProcess == null) {
2417 return;
2418 }
2419
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002420 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002421 mHeavyWeightProcess.activities);
2422 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002423 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002424 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002425 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002426 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002427 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002428 null, "finish-heavy");
2429 }
2430 }
2431 }
2432
2433 mHeavyWeightProcess = null;
2434 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2435 }
2436 }
2437
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002438 public void crashApplication(int uid, int initialPid, String packageName,
2439 String message) {
2440 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2441 != PackageManager.PERMISSION_GRANTED) {
2442 String msg = "Permission Denial: crashApplication() from pid="
2443 + Binder.getCallingPid()
2444 + ", uid=" + Binder.getCallingUid()
2445 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2446 Slog.w(TAG, msg);
2447 throw new SecurityException(msg);
2448 }
2449
2450 synchronized(this) {
2451 ProcessRecord proc = null;
2452
2453 // Figure out which process to kill. We don't trust that initialPid
2454 // still has any relation to current pids, so must scan through the
2455 // list.
2456 synchronized (mPidsSelfLocked) {
2457 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2458 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2459 if (p.info.uid != uid) {
2460 continue;
2461 }
2462 if (p.pid == initialPid) {
2463 proc = p;
2464 break;
2465 }
2466 for (String str : p.pkgList) {
2467 if (str.equals(packageName)) {
2468 proc = p;
2469 }
2470 }
2471 }
2472 }
2473
2474 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002475 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002476 + " initialPid=" + initialPid
2477 + " packageName=" + packageName);
2478 return;
2479 }
2480
2481 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002482 if (proc.pid == Process.myPid()) {
2483 Log.w(TAG, "crashApplication: trying to crash self!");
2484 return;
2485 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002486 long ident = Binder.clearCallingIdentity();
2487 try {
2488 proc.thread.scheduleCrash(message);
2489 } catch (RemoteException e) {
2490 }
2491 Binder.restoreCallingIdentity(ident);
2492 }
2493 }
2494 }
2495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 public final void finishSubActivity(IBinder token, String resultWho,
2497 int requestCode) {
2498 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002499 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 if (index < 0) {
2501 return;
2502 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002503 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504
2505 final long origId = Binder.clearCallingIdentity();
2506
2507 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002508 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2509 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 if (r.resultTo == self && r.requestCode == requestCode) {
2511 if ((r.resultWho == null && resultWho == null) ||
2512 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 Activity.RESULT_CANCELED, null, "request-sub");
2515 }
2516 }
2517 }
2518
2519 Binder.restoreCallingIdentity(origId);
2520 }
2521 }
2522
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002523 public boolean willActivityBeVisible(IBinder token) {
2524 synchronized(this) {
2525 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002526 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2527 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002528 if (r == token) {
2529 return true;
2530 }
2531 if (r.fullscreen && !r.finishing) {
2532 return false;
2533 }
2534 }
2535 return true;
2536 }
2537 }
2538
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002539 public void overridePendingTransition(IBinder token, String packageName,
2540 int enterAnim, int exitAnim) {
2541 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002542 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002543 if (index < 0) {
2544 return;
2545 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002546 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002547
2548 final long origId = Binder.clearCallingIdentity();
2549
2550 if (self.state == ActivityState.RESUMED
2551 || self.state == ActivityState.PAUSING) {
2552 mWindowManager.overridePendingAppTransition(packageName,
2553 enterAnim, exitAnim);
2554 }
2555
2556 Binder.restoreCallingIdentity(origId);
2557 }
2558 }
2559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 * Main function for removing an existing process from the activity manager
2562 * as a result of that process going away. Clears out all connections
2563 * to the process.
2564 */
2565 private final void handleAppDiedLocked(ProcessRecord app,
2566 boolean restarting) {
2567 cleanUpApplicationRecordLocked(app, restarting, -1);
2568 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002569 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 }
2571
2572 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002573 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2574 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2575 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002577 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2578 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 }
2580
2581 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002582 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583
2584 boolean atTop = true;
2585 boolean hasVisibleActivities = false;
2586
2587 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002588 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002589 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 TAG, "Removing app " + app + " from history with " + i + " entries");
2591 while (i > 0) {
2592 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002594 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2596 if (r.app == app) {
2597 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002598 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 TAG, "Removing this entry! frozen=" + r.haveState
2600 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002601 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002602 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002603 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 mWindowManager.removeAppToken(r);
2605 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002606 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002608 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609
2610 } else {
2611 // We have the current state for this activity, so
2612 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002613 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 TAG, "Keeping entry, setting app to null");
2615 if (r.visible) {
2616 hasVisibleActivities = true;
2617 }
2618 r.app = null;
2619 r.nowVisible = false;
2620 if (!r.haveState) {
2621 r.icicle = null;
2622 }
2623 }
2624
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002625 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 r.state = ActivityState.STOPPED;
2627 }
2628 atTop = false;
2629 }
2630
2631 app.activities.clear();
2632
2633 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002634 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 + " running instrumentation " + app.instrumentationClass);
2636 Bundle info = new Bundle();
2637 info.putString("shortMsg", "Process crashed.");
2638 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2639 }
2640
2641 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002642 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 // If there was nothing to resume, and we are not already
2644 // restarting this process, but there is a visible activity that
2645 // is hosted by the process... then make sure all visible
2646 // activities are running, taking care of restarting this
2647 // process.
2648 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002649 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 }
2651 }
2652 }
2653 }
2654
2655 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2656 IBinder threadBinder = thread.asBinder();
2657
2658 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002659 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2660 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2662 return i;
2663 }
2664 }
2665 return -1;
2666 }
2667
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002668 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 IApplicationThread thread) {
2670 if (thread == null) {
2671 return null;
2672 }
2673
2674 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002675 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 }
2677
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002678 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 IApplicationThread thread) {
2680
2681 mProcDeaths[0]++;
2682
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002683 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2684 synchronized (stats) {
2685 stats.noteProcessDiedLocked(app.info.uid, pid);
2686 }
2687
Magnus Edlund7bb25812010-02-24 15:45:06 +01002688 // Clean up already done if the process has been re-started.
2689 if (app.pid == pid && app.thread != null &&
2690 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002691 if (!app.killedBackground) {
2692 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2693 + ") has died.");
2694 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002695 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002696 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 TAG, "Dying app: " + app + ", pid: " + pid
2698 + ", thread: " + thread.asBinder());
2699 boolean doLowMem = app.instrumentationClass == null;
2700 handleAppDiedLocked(app, false);
2701
2702 if (doLowMem) {
2703 // If there are no longer any background processes running,
2704 // and the app that died was not running instrumentation,
2705 // then tell everyone we are now low on memory.
2706 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002707 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2708 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2710 haveBg = true;
2711 break;
2712 }
2713 }
2714
2715 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002716 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002717 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002718 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002719 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2720 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002721 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002722 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2723 // The low memory report is overriding any current
2724 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002725 // heavy/important/visible/foreground processes first.
2726 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002727 rec.lastRequestedGc = 0;
2728 } else {
2729 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002731 rec.reportLowMemory = true;
2732 rec.lastLowMemory = now;
2733 mProcessesToGc.remove(rec);
2734 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735 }
2736 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002737 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 }
2739 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002740 } else if (app.pid != pid) {
2741 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002742 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002743 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002744 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002745 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002746 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 + thread.asBinder());
2748 }
2749 }
2750
Dan Egnor42471dd2010-01-07 17:25:22 -08002751 /**
2752 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002753 * @param clearTraces causes the dump file to be erased prior to the new
2754 * traces being written, if true; when false, the new traces will be
2755 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002756 * @param firstPids of dalvik VM processes to dump stack traces for first
2757 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002758 * @return file containing stack traces, or null if no dump file is configured
2759 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002760 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2761 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002762 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2763 if (tracesPath == null || tracesPath.length() == 0) {
2764 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002766
2767 File tracesFile = new File(tracesPath);
2768 try {
2769 File tracesDir = tracesFile.getParentFile();
2770 if (!tracesDir.exists()) tracesFile.mkdirs();
2771 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2772
Christopher Tate6ee412d2010-05-28 12:01:56 -07002773 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002774 tracesFile.createNewFile();
2775 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2776 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002777 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002778 return null;
2779 }
2780
2781 // Use a FileObserver to detect when traces finish writing.
2782 // The order of traces is considered important to maintain for legibility.
2783 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2784 public synchronized void onEvent(int event, String path) { notify(); }
2785 };
2786
2787 try {
2788 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002789
2790 // First collect all of the stacks of the most important pids.
2791 try {
2792 int num = firstPids.size();
2793 for (int i = 0; i < num; i++) {
2794 synchronized (observer) {
2795 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2796 observer.wait(200); // Wait for write-close, give up after 200msec
2797 }
2798 }
2799 } catch (InterruptedException e) {
2800 Log.wtf(TAG, e);
2801 }
2802
2803 // Next measure CPU usage.
2804 if (processStats != null) {
2805 processStats.init();
2806 System.gc();
2807 processStats.update();
2808 try {
2809 synchronized (processStats) {
2810 processStats.wait(500); // measure over 1/2 second.
2811 }
2812 } catch (InterruptedException e) {
2813 }
2814 processStats.update();
2815
2816 // We'll take the stack crawls of just the top apps using CPU.
2817 final int N = processStats.countWorkingStats();
2818 int numProcs = 0;
2819 for (int i=0; i<N && numProcs<5; i++) {
2820 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2821 if (lastPids.indexOfKey(stats.pid) >= 0) {
2822 numProcs++;
2823 try {
2824 synchronized (observer) {
2825 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2826 observer.wait(200); // Wait for write-close, give up after 200msec
2827 }
2828 } catch (InterruptedException e) {
2829 Log.wtf(TAG, e);
2830 }
2831
2832 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002833 }
2834 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002835
2836 return tracesFile;
2837
Dan Egnor42471dd2010-01-07 17:25:22 -08002838 } finally {
2839 observer.stopWatching();
2840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 }
2842
Jeff Brown4d94a762010-09-23 11:33:28 -07002843 private final class AppNotResponding implements Runnable {
2844 private final ProcessRecord mApp;
2845 private final String mAnnotation;
2846
2847 public AppNotResponding(ProcessRecord app, String annotation) {
2848 mApp = app;
2849 mAnnotation = annotation;
2850 }
2851
2852 @Override
2853 public void run() {
2854 appNotResponding(mApp, null, null, mAnnotation);
2855 }
2856 }
2857
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002858 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2859 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002860 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2861 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2862
Dianne Hackborn287952c2010-09-22 22:34:31 -07002863 if (mController != null) {
2864 try {
2865 // 0 == continue, -1 = kill process immediately
2866 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2867 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2868 } catch (RemoteException e) {
2869 mController = null;
2870 }
2871 }
2872
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002873 long anrTime = SystemClock.uptimeMillis();
2874 if (MONITOR_CPU_USAGE) {
2875 updateCpuStatsNow();
2876 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002877
2878 synchronized (this) {
2879 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2880 if (mShuttingDown) {
2881 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2882 return;
2883 } else if (app.notResponding) {
2884 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2885 return;
2886 } else if (app.crashing) {
2887 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2888 return;
2889 }
2890
2891 // In case we come through here for the same app before completing
2892 // this one, mark as anring now so we will bail out.
2893 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002894
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002895 // Log the ANR to the event log.
2896 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2897 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002898
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002899 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002900 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002901
2902 int parentPid = app.pid;
2903 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002904 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002905
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002906 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002907
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002908 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2909 ProcessRecord r = mLruProcesses.get(i);
2910 if (r != null && r.thread != null) {
2911 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002912 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2913 if (r.persistent) {
2914 firstPids.add(pid);
2915 } else {
2916 lastPids.put(pid, Boolean.TRUE);
2917 }
2918 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 }
2921 }
2922
Dan Egnor42471dd2010-01-07 17:25:22 -08002923 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002924 StringBuilder info = mStringBuilder;
2925 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002926 info.append("ANR in ").append(app.processName);
2927 if (activity != null && activity.shortComponentName != null) {
2928 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002929 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002930 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002932 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002934 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002935 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937
Dianne Hackborn287952c2010-09-22 22:34:31 -07002938 final ProcessStats processStats = new ProcessStats(true);
2939
2940 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2941
Dan Egnor42471dd2010-01-07 17:25:22 -08002942 String cpuInfo = null;
2943 if (MONITOR_CPU_USAGE) {
2944 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002945 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002946 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002947 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002948 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002949 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 }
2951
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002952 info.append(processStats.printCurrentState(anrTime));
2953
Joe Onorato8a9b2202010-02-26 18:56:32 -08002954 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002955 if (tracesFile == null) {
2956 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2957 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2958 }
2959
2960 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2961
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002962 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002964 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2965 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002967 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2968 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 }
2970 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002971 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 }
2973 }
2974
Dan Egnor42471dd2010-01-07 17:25:22 -08002975 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2976 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2977 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002978
2979 synchronized (this) {
2980 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002981 Slog.w(TAG, "Killing " + app + ": background ANR");
2982 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
2983 app.processName, app.setAdj, "background ANR");
2984 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002985 return;
2986 }
2987
2988 // Set the app's notResponding state, and look up the errorReportReceiver
2989 makeAppNotRespondingLocked(app,
2990 activity != null ? activity.shortComponentName : null,
2991 annotation != null ? "ANR " + annotation : "ANR",
2992 info.toString());
2993
2994 // Bring up the infamous App Not Responding dialog
2995 Message msg = Message.obtain();
2996 HashMap map = new HashMap();
2997 msg.what = SHOW_NOT_RESPONDING_MSG;
2998 msg.obj = map;
2999 map.put("app", app);
3000 if (activity != null) {
3001 map.put("activity", activity);
3002 }
3003
3004 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 }
3007
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003008 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3009 if (!mLaunchWarningShown) {
3010 mLaunchWarningShown = true;
3011 mHandler.post(new Runnable() {
3012 @Override
3013 public void run() {
3014 synchronized (ActivityManagerService.this) {
3015 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3016 d.show();
3017 mHandler.postDelayed(new Runnable() {
3018 @Override
3019 public void run() {
3020 synchronized (ActivityManagerService.this) {
3021 d.dismiss();
3022 mLaunchWarningShown = false;
3023 }
3024 }
3025 }, 4000);
3026 }
3027 }
3028 });
3029 }
3030 }
3031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 public boolean clearApplicationUserData(final String packageName,
3033 final IPackageDataObserver observer) {
3034 int uid = Binder.getCallingUid();
3035 int pid = Binder.getCallingPid();
3036 long callingId = Binder.clearCallingIdentity();
3037 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003038 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 int pkgUid = -1;
3040 synchronized(this) {
3041 try {
3042 pkgUid = pm.getPackageUid(packageName);
3043 } catch (RemoteException e) {
3044 }
3045 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003046 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 return false;
3048 }
3049 if (uid == pkgUid || checkComponentPermission(
3050 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003051 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003053 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 } else {
3055 throw new SecurityException(pid+" does not have permission:"+
3056 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3057 "for process:"+packageName);
3058 }
3059 }
3060
3061 try {
3062 //clear application user data
3063 pm.clearApplicationUserData(packageName, observer);
3064 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3065 Uri.fromParts("package", packageName, null));
3066 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003067 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3068 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 } catch (RemoteException e) {
3070 }
3071 } finally {
3072 Binder.restoreCallingIdentity(callingId);
3073 }
3074 return true;
3075 }
3076
Dianne Hackborn03abb812010-01-04 18:43:19 -08003077 public void killBackgroundProcesses(final String packageName) {
3078 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3079 != PackageManager.PERMISSION_GRANTED &&
3080 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3081 != PackageManager.PERMISSION_GRANTED) {
3082 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 + Binder.getCallingPid()
3084 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003085 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003086 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 throw new SecurityException(msg);
3088 }
3089
3090 long callingId = Binder.clearCallingIdentity();
3091 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003092 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 int pkgUid = -1;
3094 synchronized(this) {
3095 try {
3096 pkgUid = pm.getPackageUid(packageName);
3097 } catch (RemoteException e) {
3098 }
3099 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003100 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 return;
3102 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003103 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003104 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003105 }
3106 } finally {
3107 Binder.restoreCallingIdentity(callingId);
3108 }
3109 }
3110
3111 public void forceStopPackage(final String packageName) {
3112 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3113 != PackageManager.PERMISSION_GRANTED) {
3114 String msg = "Permission Denial: forceStopPackage() from pid="
3115 + Binder.getCallingPid()
3116 + ", uid=" + Binder.getCallingUid()
3117 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003118 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003119 throw new SecurityException(msg);
3120 }
3121
3122 long callingId = Binder.clearCallingIdentity();
3123 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003124 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003125 int pkgUid = -1;
3126 synchronized(this) {
3127 try {
3128 pkgUid = pm.getPackageUid(packageName);
3129 } catch (RemoteException e) {
3130 }
3131 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003132 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003133 return;
3134 }
3135 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003136 try {
3137 pm.setPackageStoppedState(packageName, true);
3138 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003139 } catch (IllegalArgumentException e) {
3140 Slog.w(TAG, "Failed trying to unstop package "
3141 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003142 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 }
3144 } finally {
3145 Binder.restoreCallingIdentity(callingId);
3146 }
3147 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003148
3149 /*
3150 * The pkg name and uid have to be specified.
3151 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3152 */
3153 public void killApplicationWithUid(String pkg, int uid) {
3154 if (pkg == null) {
3155 return;
3156 }
3157 // Make sure the uid is valid.
3158 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003159 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003160 return;
3161 }
3162 int callerUid = Binder.getCallingUid();
3163 // Only the system server can kill an application
3164 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003165 // Post an aysnc message to kill the application
3166 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3167 msg.arg1 = uid;
3168 msg.arg2 = 0;
3169 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003170 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003171 } else {
3172 throw new SecurityException(callerUid + " cannot kill pkg: " +
3173 pkg);
3174 }
3175 }
3176
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003177 public void closeSystemDialogs(String reason) {
3178 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003179 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003180 if (reason != null) {
3181 intent.putExtra("reason", reason);
3182 }
3183
3184 final int uid = Binder.getCallingUid();
3185 final long origId = Binder.clearCallingIdentity();
3186 synchronized (this) {
3187 int i = mWatchers.beginBroadcast();
3188 while (i > 0) {
3189 i--;
3190 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3191 if (w != null) {
3192 try {
3193 w.closingSystemDialogs(reason);
3194 } catch (RemoteException e) {
3195 }
3196 }
3197 }
3198 mWatchers.finishBroadcast();
3199
Dianne Hackbornffa42482009-09-23 22:20:11 -07003200 mWindowManager.closeSystemDialogs(reason);
3201
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003202 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3203 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003204 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003205 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003206 Activity.RESULT_CANCELED, null, "close-sys");
3207 }
3208 }
3209
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003210 broadcastIntentLocked(null, null, intent, null,
3211 null, 0, null, null, null, false, false, -1, uid);
3212 }
3213 Binder.restoreCallingIdentity(origId);
3214 }
3215
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003216 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003217 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003218 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3219 for (int i=pids.length-1; i>=0; i--) {
3220 infos[i] = new Debug.MemoryInfo();
3221 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003222 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003223 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003224 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003225
3226 public void killApplicationProcess(String processName, int uid) {
3227 if (processName == null) {
3228 return;
3229 }
3230
3231 int callerUid = Binder.getCallingUid();
3232 // Only the system server can kill an application
3233 if (callerUid == Process.SYSTEM_UID) {
3234 synchronized (this) {
3235 ProcessRecord app = getProcessRecordLocked(processName, uid);
3236 if (app != null) {
3237 try {
3238 app.thread.scheduleSuicide();
3239 } catch (RemoteException e) {
3240 // If the other end already died, then our work here is done.
3241 }
3242 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003243 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003244 + processName + " / " + uid);
3245 }
3246 }
3247 } else {
3248 throw new SecurityException(callerUid + " cannot kill app process: " +
3249 processName);
3250 }
3251 }
3252
Dianne Hackborn03abb812010-01-04 18:43:19 -08003253 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003254 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3256 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003257 if (!mProcessesReady) {
3258 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 intent.putExtra(Intent.EXTRA_UID, uid);
3261 broadcastIntentLocked(null, null, intent,
3262 null, null, 0, null, null, null,
3263 false, false, MY_PID, Process.SYSTEM_UID);
3264 }
3265
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003266 private final boolean killPackageProcessesLocked(String packageName, int uid,
3267 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003268 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269
Dianne Hackborn03abb812010-01-04 18:43:19 -08003270 // Remove all processes this package may have touched: all with the
3271 // same UID (except for the system or root user), and all whose name
3272 // matches the package name.
3273 final String procNamePrefix = packageName + ":";
3274 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3275 final int NA = apps.size();
3276 for (int ia=0; ia<NA; ia++) {
3277 ProcessRecord app = apps.valueAt(ia);
3278 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003279 if (doit) {
3280 procs.add(app);
3281 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003282 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3283 || app.processName.equals(packageName)
3284 || app.processName.startsWith(procNamePrefix)) {
3285 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003286 if (!doit) {
3287 return true;
3288 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003289 app.removed = true;
3290 procs.add(app);
3291 }
3292 }
3293 }
3294 }
3295
3296 int N = procs.size();
3297 for (int i=0; i<N; i++) {
3298 removeProcessLocked(procs.get(i), callerWillRestart);
3299 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003300 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003301 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003302
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003303 private final boolean forceStopPackageLocked(String name, int uid,
3304 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 int i, N;
3306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 if (uid < 0) {
3308 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003309 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 } catch (RemoteException e) {
3311 }
3312 }
3313
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003314 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003315 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003316
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003317 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3318 while (badApps.hasNext()) {
3319 SparseArray<Long> ba = badApps.next();
3320 if (ba.get(uid) != null) {
3321 badApps.remove();
3322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 }
3324 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003325
3326 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3327 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003329 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3330 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332 if (!doit) {
3333 return true;
3334 }
3335 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003336 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 if (r.app != null) {
3338 r.app.removed = true;
3339 }
3340 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003341 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 }
3343 }
3344
3345 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3346 for (ServiceRecord service : mServices.values()) {
3347 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003348 if (!doit) {
3349 return true;
3350 }
3351 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003352 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 if (service.app != null) {
3354 service.app.removed = true;
3355 }
3356 service.app = null;
3357 services.add(service);
3358 }
3359 }
3360
3361 N = services.size();
3362 for (i=0; i<N; i++) {
3363 bringDownServiceLocked(services.get(i), true);
3364 }
3365
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003366 if (doit) {
3367 if (purgeCache) {
3368 AttributeCache ac = AttributeCache.instance();
3369 if (ac != null) {
3370 ac.removePackage(name);
3371 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003372 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003373 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003374 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003375
3376 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 }
3378
3379 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3380 final String name = app.processName;
3381 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003382 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 TAG, "Force removing process " + app + " (" + name
3384 + "/" + uid + ")");
3385
3386 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003387 if (mHeavyWeightProcess == app) {
3388 mHeavyWeightProcess = null;
3389 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 boolean needRestart = false;
3392 if (app.pid > 0 && app.pid != MY_PID) {
3393 int pid = app.pid;
3394 synchronized (mPidsSelfLocked) {
3395 mPidsSelfLocked.remove(pid);
3396 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3397 }
3398 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003399 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 Process.killProcess(pid);
3401
3402 if (app.persistent) {
3403 if (!callerWillRestart) {
3404 addAppLocked(app.info);
3405 } else {
3406 needRestart = true;
3407 }
3408 }
3409 } else {
3410 mRemovedProcesses.add(app);
3411 }
3412
3413 return needRestart;
3414 }
3415
3416 private final void processStartTimedOutLocked(ProcessRecord app) {
3417 final int pid = app.pid;
3418 boolean gone = false;
3419 synchronized (mPidsSelfLocked) {
3420 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3421 if (knownApp != null && knownApp.thread == null) {
3422 mPidsSelfLocked.remove(pid);
3423 gone = true;
3424 }
3425 }
3426
3427 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003428 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003429 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003430 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003432 if (mHeavyWeightProcess == app) {
3433 mHeavyWeightProcess = null;
3434 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3435 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003436 // Take care of any launching providers waiting for this process.
3437 checkAppInLaunchingProvidersLocked(app, true);
3438 // Take care of any services that are waiting for the process.
3439 for (int i=0; i<mPendingServices.size(); i++) {
3440 ServiceRecord sr = mPendingServices.get(i);
3441 if (app.info.uid == sr.appInfo.uid
3442 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003444 mPendingServices.remove(i);
3445 i--;
3446 bringDownServiceLocked(sr, true);
3447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003449 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3450 app.processName, app.setAdj, "start timeout");
3451 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003452 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003454 try {
3455 IBackupManager bm = IBackupManager.Stub.asInterface(
3456 ServiceManager.getService(Context.BACKUP_SERVICE));
3457 bm.agentDisconnected(app.info.packageName);
3458 } catch (RemoteException e) {
3459 // Can't happen; the backup manager is local
3460 }
3461 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003462 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003464 mPendingBroadcast.state = BroadcastRecord.IDLE;
3465 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003466 mPendingBroadcast = null;
3467 scheduleBroadcastsLocked();
3468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003470 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 }
3472 }
3473
3474 private final boolean attachApplicationLocked(IApplicationThread thread,
3475 int pid) {
3476
3477 // Find the application record that is being attached... either via
3478 // the pid if we are running in multiple processes, or just pull the
3479 // next app record if we are emulating process with anonymous threads.
3480 ProcessRecord app;
3481 if (pid != MY_PID && pid >= 0) {
3482 synchronized (mPidsSelfLocked) {
3483 app = mPidsSelfLocked.get(pid);
3484 }
3485 } else if (mStartingProcesses.size() > 0) {
3486 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003487 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 } else {
3489 app = null;
3490 }
3491
3492 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003493 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003495 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003497 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 } else {
3499 try {
3500 thread.scheduleExit();
3501 } catch (Exception e) {
3502 // Ignore exceptions.
3503 }
3504 }
3505 return false;
3506 }
3507
3508 // If this application record is still attached to a previous
3509 // process, clean it up now.
3510 if (app.thread != null) {
3511 handleAppDiedLocked(app, true);
3512 }
3513
3514 // Tell the process all about itself.
3515
Joe Onorato8a9b2202010-02-26 18:56:32 -08003516 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003517 TAG, "Binding process pid " + pid + " to record " + app);
3518
3519 String processName = app.processName;
3520 try {
3521 thread.asBinder().linkToDeath(new AppDeathRecipient(
3522 app, pid, thread), 0);
3523 } catch (RemoteException e) {
3524 app.resetPackageList();
3525 startProcessLocked(app, "link fail", processName);
3526 return false;
3527 }
3528
Doug Zongker2bec3d42009-12-04 12:52:44 -08003529 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530
3531 app.thread = thread;
3532 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003533 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3534 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 app.forcingToForeground = null;
3536 app.foregroundServices = false;
3537 app.debugging = false;
3538
3539 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3540
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003541 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003542 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003544 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003545 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003546 }
3547
Joe Onorato8a9b2202010-02-26 18:56:32 -08003548 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 TAG, "New app record " + app
3550 + " thread=" + thread.asBinder() + " pid=" + pid);
3551 try {
3552 int testMode = IApplicationThread.DEBUG_OFF;
3553 if (mDebugApp != null && mDebugApp.equals(processName)) {
3554 testMode = mWaitForDebugger
3555 ? IApplicationThread.DEBUG_WAIT
3556 : IApplicationThread.DEBUG_ON;
3557 app.debugging = true;
3558 if (mDebugTransient) {
3559 mDebugApp = mOrigDebugApp;
3560 mWaitForDebugger = mOrigWaitForDebugger;
3561 }
3562 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003563
Christopher Tate181fafa2009-05-14 11:12:14 -07003564 // If the app is being launched for restore or full backup, set it up specially
3565 boolean isRestrictedBackupMode = false;
3566 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3567 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3568 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3569 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003570
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003571 ensurePackageDexOpt(app.instrumentationInfo != null
3572 ? app.instrumentationInfo.packageName
3573 : app.info.packageName);
3574 if (app.instrumentationClass != null) {
3575 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003576 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003577 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003578 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003579 thread.bindApplication(processName, app.instrumentationInfo != null
3580 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 app.instrumentationClass, app.instrumentationProfileFile,
3582 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003583 isRestrictedBackupMode || !normalMode,
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003584 mConfiguration, getCommonServicesLocked(),
3585 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003586 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003587 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 } catch (Exception e) {
3589 // todo: Yikes! What should we do? For now we will try to
3590 // start another process, but that could easily get us in
3591 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003592 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593
3594 app.resetPackageList();
3595 startProcessLocked(app, "bind fail", processName);
3596 return false;
3597 }
3598
3599 // Remove this record from the list of starting applications.
3600 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003601 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3602 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 mProcessesOnHold.remove(app);
3604
3605 boolean badApp = false;
3606 boolean didSomething = false;
3607
3608 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003609 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003610 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3612 && processName.equals(hr.processName)) {
3613 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003614 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 didSomething = true;
3616 }
3617 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003618 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 + hr.intent.getComponent().flattenToShortString(), e);
3620 badApp = true;
3621 }
3622 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003623 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 }
3625 }
3626
3627 // Find any services that should be running in this process...
3628 if (!badApp && mPendingServices.size() > 0) {
3629 ServiceRecord sr = null;
3630 try {
3631 for (int i=0; i<mPendingServices.size(); i++) {
3632 sr = mPendingServices.get(i);
3633 if (app.info.uid != sr.appInfo.uid
3634 || !processName.equals(sr.processName)) {
3635 continue;
3636 }
3637
3638 mPendingServices.remove(i);
3639 i--;
3640 realStartServiceLocked(sr, app);
3641 didSomething = true;
3642 }
3643 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003644 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003645 + sr.shortName, e);
3646 badApp = true;
3647 }
3648 }
3649
3650 // Check if the next broadcast receiver is in this process...
3651 BroadcastRecord br = mPendingBroadcast;
3652 if (!badApp && br != null && br.curApp == app) {
3653 try {
3654 mPendingBroadcast = null;
3655 processCurBroadcastLocked(br, app);
3656 didSomething = true;
3657 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003658 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 + br.curComponent.flattenToShortString(), e);
3660 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003661 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3663 br.resultExtras, br.resultAbort, true);
3664 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003665 // We need to reset the state if we fails to start the receiver.
3666 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 }
3668 }
3669
Christopher Tate181fafa2009-05-14 11:12:14 -07003670 // Check whether the next backup agent is in this process...
3671 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003672 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003673 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003674 try {
3675 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3676 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003677 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003678 e.printStackTrace();
3679 }
3680 }
3681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 if (badApp) {
3683 // todo: Also need to kill application to deal with all
3684 // kinds of exceptions.
3685 handleAppDiedLocked(app, false);
3686 return false;
3687 }
3688
3689 if (!didSomething) {
3690 updateOomAdjLocked();
3691 }
3692
3693 return true;
3694 }
3695
3696 public final void attachApplication(IApplicationThread thread) {
3697 synchronized (this) {
3698 int callingPid = Binder.getCallingPid();
3699 final long origId = Binder.clearCallingIdentity();
3700 attachApplicationLocked(thread, callingPid);
3701 Binder.restoreCallingIdentity(origId);
3702 }
3703 }
3704
Dianne Hackborne88846e2009-09-30 21:34:25 -07003705 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 Binder.restoreCallingIdentity(origId);
3709 }
3710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003712 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003713 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 mWindowManager.enableScreenAfterBoot();
3715 }
3716
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003717 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003718 IntentFilter pkgFilter = new IntentFilter();
3719 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3720 pkgFilter.addDataScheme("package");
3721 mContext.registerReceiver(new BroadcastReceiver() {
3722 @Override
3723 public void onReceive(Context context, Intent intent) {
3724 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3725 if (pkgs != null) {
3726 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003727 synchronized (ActivityManagerService.this) {
3728 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3729 setResultCode(Activity.RESULT_OK);
3730 return;
3731 }
3732 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003733 }
3734 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003735 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003736 }, pkgFilter);
3737
3738 synchronized (this) {
3739 // Ensure that any processes we had put on hold are now started
3740 // up.
3741 final int NP = mProcessesOnHold.size();
3742 if (NP > 0) {
3743 ArrayList<ProcessRecord> procs =
3744 new ArrayList<ProcessRecord>(mProcessesOnHold);
3745 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003746 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3747 + procs.get(ip));
3748 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003749 }
3750 }
3751
3752 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003753 // Start looking for apps that are abusing wake locks.
3754 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003755 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003756 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003757 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003758 broadcastIntentLocked(null, null,
3759 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3760 null, null, 0, null, null,
3761 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3762 false, false, MY_PID, Process.SYSTEM_UID);
3763 }
3764 }
3765 }
3766
3767 final void ensureBootCompleted() {
3768 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003769 boolean enableScreen;
3770 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003771 booting = mBooting;
3772 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003773 enableScreen = !mBooted;
3774 mBooted = true;
3775 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003776
3777 if (booting) {
3778 finishBooting();
3779 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003780
3781 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003782 enableScreenAfterBoot();
3783 }
3784 }
3785
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003786 public final void activityPaused(IBinder token) {
3787 final long origId = Binder.clearCallingIdentity();
3788 mMainStack.activityPaused(token, false);
3789 Binder.restoreCallingIdentity(origId);
3790 }
3791
3792 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3793 CharSequence description) {
3794 if (localLOGV) Slog.v(
3795 TAG, "Activity stopped: token=" + token);
3796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 // Refuse possible leaked file descriptors
3798 if (icicle != null && icicle.hasFileDescriptors()) {
3799 throw new IllegalArgumentException("File descriptors passed in Bundle");
3800 }
3801
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003802 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803
3804 final long origId = Binder.clearCallingIdentity();
3805
3806 synchronized (this) {
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 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003810 r.icicle = icicle;
3811 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003812 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 r.stopped = true;
3814 r.state = ActivityState.STOPPED;
3815 if (!r.finishing) {
3816 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003817 r.stack.destroyActivityLocked(r, true);
3818 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 }
3820 }
3821 }
3822 }
3823
3824 if (r != null) {
3825 sendPendingThumbnail(r, null, null, null, false);
3826 }
3827
3828 trimApplications();
3829
3830 Binder.restoreCallingIdentity(origId);
3831 }
3832
3833 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003834 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003835 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 }
3837
3838 public String getCallingPackage(IBinder token) {
3839 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003840 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003841 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 }
3843 }
3844
3845 public ComponentName getCallingActivity(IBinder token) {
3846 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003847 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 return r != null ? r.intent.getComponent() : null;
3849 }
3850 }
3851
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003852 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003853 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003855 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 if (r != null) {
3857 return r.resultTo;
3858 }
3859 }
3860 return null;
3861 }
3862
3863 public ComponentName getActivityClassForToken(IBinder token) {
3864 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003865 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003867 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 return r.intent.getComponent();
3869 }
3870 return null;
3871 }
3872 }
3873
3874 public String getPackageForToken(IBinder token) {
3875 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003876 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003878 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 return r.packageName;
3880 }
3881 return null;
3882 }
3883 }
3884
3885 public IIntentSender getIntentSender(int type,
3886 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003887 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003889 if (intents != null) {
3890 if (intents.length < 1) {
3891 throw new IllegalArgumentException("Intents array length must be >= 1");
3892 }
3893 for (int i=0; i<intents.length; i++) {
3894 Intent intent = intents[i];
3895 if (intent == null) {
3896 throw new IllegalArgumentException("Null intent at index " + i);
3897 }
3898 if (intent.hasFileDescriptors()) {
3899 throw new IllegalArgumentException("File descriptors passed in Intent");
3900 }
3901 if (type == INTENT_SENDER_BROADCAST &&
3902 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3903 throw new IllegalArgumentException(
3904 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3905 }
3906 intents[i] = new Intent(intent);
3907 }
3908 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003909 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003910 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003911 }
3912 }
3913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 synchronized(this) {
3915 int callingUid = Binder.getCallingUid();
3916 try {
3917 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3918 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003919 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 .getPackageUid(packageName);
3921 if (uid != Binder.getCallingUid()) {
3922 String msg = "Permission Denial: getIntentSender() from pid="
3923 + Binder.getCallingPid()
3924 + ", uid=" + Binder.getCallingUid()
3925 + ", (need uid=" + uid + ")"
3926 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003927 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 throw new SecurityException(msg);
3929 }
3930 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003931
3932 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003933 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 } catch (RemoteException e) {
3936 throw new SecurityException(e);
3937 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003938 }
3939 }
3940
3941 IIntentSender getIntentSenderLocked(int type,
3942 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003943 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003944 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003946 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003947 if (index < 0) {
3948 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003950 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003951 if (activity.finishing) {
3952 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003954 }
3955
3956 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3957 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3958 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3959 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3960 |PendingIntent.FLAG_UPDATE_CURRENT);
3961
3962 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3963 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003964 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003965 WeakReference<PendingIntentRecord> ref;
3966 ref = mIntentSenderRecords.get(key);
3967 PendingIntentRecord rec = ref != null ? ref.get() : null;
3968 if (rec != null) {
3969 if (!cancelCurrent) {
3970 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003971 if (rec.key.requestIntent != null) {
3972 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3973 }
3974 if (intents != null) {
3975 intents[intents.length-1] = rec.key.requestIntent;
3976 rec.key.allIntents = intents;
3977 rec.key.allResolvedTypes = resolvedTypes;
3978 } else {
3979 rec.key.allIntents = null;
3980 rec.key.allResolvedTypes = null;
3981 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 return rec;
3984 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003985 rec.canceled = true;
3986 mIntentSenderRecords.remove(key);
3987 }
3988 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 return rec;
3990 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003991 rec = new PendingIntentRecord(this, key, callingUid);
3992 mIntentSenderRecords.put(key, rec.ref);
3993 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3994 if (activity.pendingResults == null) {
3995 activity.pendingResults
3996 = new HashSet<WeakReference<PendingIntentRecord>>();
3997 }
3998 activity.pendingResults.add(rec.ref);
3999 }
4000 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 }
4002
4003 public void cancelIntentSender(IIntentSender sender) {
4004 if (!(sender instanceof PendingIntentRecord)) {
4005 return;
4006 }
4007 synchronized(this) {
4008 PendingIntentRecord rec = (PendingIntentRecord)sender;
4009 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004010 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 .getPackageUid(rec.key.packageName);
4012 if (uid != Binder.getCallingUid()) {
4013 String msg = "Permission Denial: cancelIntentSender() from pid="
4014 + Binder.getCallingPid()
4015 + ", uid=" + Binder.getCallingUid()
4016 + " is not allowed to cancel packges "
4017 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004018 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 throw new SecurityException(msg);
4020 }
4021 } catch (RemoteException e) {
4022 throw new SecurityException(e);
4023 }
4024 cancelIntentSenderLocked(rec, true);
4025 }
4026 }
4027
4028 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4029 rec.canceled = true;
4030 mIntentSenderRecords.remove(rec.key);
4031 if (cleanActivity && rec.key.activity != null) {
4032 rec.key.activity.pendingResults.remove(rec.ref);
4033 }
4034 }
4035
4036 public String getPackageForIntentSender(IIntentSender pendingResult) {
4037 if (!(pendingResult instanceof PendingIntentRecord)) {
4038 return null;
4039 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004040 try {
4041 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4042 return res.key.packageName;
4043 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 }
4045 return null;
4046 }
4047
4048 public void setProcessLimit(int max) {
4049 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4050 "setProcessLimit()");
4051 mProcessLimit = max;
4052 }
4053
4054 public int getProcessLimit() {
4055 return mProcessLimit;
4056 }
4057
4058 void foregroundTokenDied(ForegroundToken token) {
4059 synchronized (ActivityManagerService.this) {
4060 synchronized (mPidsSelfLocked) {
4061 ForegroundToken cur
4062 = mForegroundProcesses.get(token.pid);
4063 if (cur != token) {
4064 return;
4065 }
4066 mForegroundProcesses.remove(token.pid);
4067 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4068 if (pr == null) {
4069 return;
4070 }
4071 pr.forcingToForeground = null;
4072 pr.foregroundServices = false;
4073 }
4074 updateOomAdjLocked();
4075 }
4076 }
4077
4078 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4079 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4080 "setProcessForeground()");
4081 synchronized(this) {
4082 boolean changed = false;
4083
4084 synchronized (mPidsSelfLocked) {
4085 ProcessRecord pr = mPidsSelfLocked.get(pid);
4086 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004087 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 return;
4089 }
4090 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4091 if (oldToken != null) {
4092 oldToken.token.unlinkToDeath(oldToken, 0);
4093 mForegroundProcesses.remove(pid);
4094 pr.forcingToForeground = null;
4095 changed = true;
4096 }
4097 if (isForeground && token != null) {
4098 ForegroundToken newToken = new ForegroundToken() {
4099 public void binderDied() {
4100 foregroundTokenDied(this);
4101 }
4102 };
4103 newToken.pid = pid;
4104 newToken.token = token;
4105 try {
4106 token.linkToDeath(newToken, 0);
4107 mForegroundProcesses.put(pid, newToken);
4108 pr.forcingToForeground = token;
4109 changed = true;
4110 } catch (RemoteException e) {
4111 // If the process died while doing this, we will later
4112 // do the cleanup with the process death link.
4113 }
4114 }
4115 }
4116
4117 if (changed) {
4118 updateOomAdjLocked();
4119 }
4120 }
4121 }
4122
4123 // =========================================================
4124 // PERMISSIONS
4125 // =========================================================
4126
4127 static class PermissionController extends IPermissionController.Stub {
4128 ActivityManagerService mActivityManagerService;
4129 PermissionController(ActivityManagerService activityManagerService) {
4130 mActivityManagerService = activityManagerService;
4131 }
4132
4133 public boolean checkPermission(String permission, int pid, int uid) {
4134 return mActivityManagerService.checkPermission(permission, pid,
4135 uid) == PackageManager.PERMISSION_GRANTED;
4136 }
4137 }
4138
4139 /**
4140 * This can be called with or without the global lock held.
4141 */
4142 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004143 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 // We might be performing an operation on behalf of an indirect binder
4145 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4146 // client identity accordingly before proceeding.
4147 Identity tlsIdentity = sCallerIdentity.get();
4148 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004149 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4151 uid = tlsIdentity.uid;
4152 pid = tlsIdentity.pid;
4153 }
4154
4155 // Root, system server and our own process get to do everything.
4156 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4157 !Process.supportsProcesses()) {
4158 return PackageManager.PERMISSION_GRANTED;
4159 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004160 // If there is a uid that owns whatever is being accessed, it has
4161 // blanket access to it regardless of the permissions it requires.
4162 if (owningUid >= 0 && uid == owningUid) {
4163 return PackageManager.PERMISSION_GRANTED;
4164 }
4165 // If the target is not exported, then nobody else can get to it.
4166 if (!exported) {
4167 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 return PackageManager.PERMISSION_DENIED;
4169 }
4170 if (permission == null) {
4171 return PackageManager.PERMISSION_GRANTED;
4172 }
4173 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004174 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 .checkUidPermission(permission, uid);
4176 } catch (RemoteException e) {
4177 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004178 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 }
4180 return PackageManager.PERMISSION_DENIED;
4181 }
4182
4183 /**
4184 * As the only public entry point for permissions checking, this method
4185 * can enforce the semantic that requesting a check on a null global
4186 * permission is automatically denied. (Internally a null permission
4187 * string is used when calling {@link #checkComponentPermission} in cases
4188 * when only uid-based security is needed.)
4189 *
4190 * This can be called with or without the global lock held.
4191 */
4192 public int checkPermission(String permission, int pid, int uid) {
4193 if (permission == null) {
4194 return PackageManager.PERMISSION_DENIED;
4195 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004196 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 }
4198
4199 /**
4200 * Binder IPC calls go through the public entry point.
4201 * This can be called with or without the global lock held.
4202 */
4203 int checkCallingPermission(String permission) {
4204 return checkPermission(permission,
4205 Binder.getCallingPid(),
4206 Binder.getCallingUid());
4207 }
4208
4209 /**
4210 * This can be called with or without the global lock held.
4211 */
4212 void enforceCallingPermission(String permission, String func) {
4213 if (checkCallingPermission(permission)
4214 == PackageManager.PERMISSION_GRANTED) {
4215 return;
4216 }
4217
4218 String msg = "Permission Denial: " + func + " from pid="
4219 + Binder.getCallingPid()
4220 + ", uid=" + Binder.getCallingUid()
4221 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004222 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 throw new SecurityException(msg);
4224 }
4225
4226 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004227 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4228 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4229 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4230 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4231 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004233 // Is the component private from the target uid?
4234 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4235
4236 // Acceptable if the there is no read permission needed from the
4237 // target or the target is holding the read permission.
4238 if (!readPerm) {
4239 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004241 == PackageManager.PERMISSION_GRANTED)) {
4242 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 }
4244 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004245
4246 // Acceptable if the there is no write permission needed from the
4247 // target or the target is holding the read permission.
4248 if (!writePerm) {
4249 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004251 == PackageManager.PERMISSION_GRANTED)) {
4252 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 }
4254 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004255
4256 // Acceptable if there is a path permission matching the URI that
4257 // the target holds the permission on.
4258 PathPermission[] pps = pi.pathPermissions;
4259 if (pps != null && (!readPerm || !writePerm)) {
4260 final String path = uri.getPath();
4261 int i = pps.length;
4262 while (i > 0 && (!readPerm || !writePerm)) {
4263 i--;
4264 PathPermission pp = pps[i];
4265 if (!readPerm) {
4266 final String pprperm = pp.getReadPermission();
4267 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4268 + pprperm + " for " + pp.getPath()
4269 + ": match=" + pp.match(path)
4270 + " check=" + pm.checkUidPermission(pprperm, uid));
4271 if (pprperm != null && pp.match(path) &&
4272 (pm.checkUidPermission(pprperm, uid)
4273 == PackageManager.PERMISSION_GRANTED)) {
4274 readPerm = true;
4275 }
4276 }
4277 if (!writePerm) {
4278 final String ppwperm = pp.getWritePermission();
4279 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4280 + ppwperm + " for " + pp.getPath()
4281 + ": match=" + pp.match(path)
4282 + " check=" + pm.checkUidPermission(ppwperm, uid));
4283 if (ppwperm != null && pp.match(path) &&
4284 (pm.checkUidPermission(ppwperm, uid)
4285 == PackageManager.PERMISSION_GRANTED)) {
4286 writePerm = true;
4287 }
4288 }
4289 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 } catch (RemoteException e) {
4292 return false;
4293 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004294
4295 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 }
4297
4298 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4299 int modeFlags) {
4300 // Root gets to do everything.
4301 if (uid == 0 || !Process.supportsProcesses()) {
4302 return true;
4303 }
4304 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4305 if (perms == null) return false;
4306 UriPermission perm = perms.get(uri);
4307 if (perm == null) return false;
4308 return (modeFlags&perm.modeFlags) == modeFlags;
4309 }
4310
4311 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4312 // Another redirected-binder-call permissions check as in
4313 // {@link checkComponentPermission}.
4314 Identity tlsIdentity = sCallerIdentity.get();
4315 if (tlsIdentity != null) {
4316 uid = tlsIdentity.uid;
4317 pid = tlsIdentity.pid;
4318 }
4319
4320 // Our own process gets to do everything.
4321 if (pid == MY_PID) {
4322 return PackageManager.PERMISSION_GRANTED;
4323 }
4324 synchronized(this) {
4325 return checkUriPermissionLocked(uri, uid, modeFlags)
4326 ? PackageManager.PERMISSION_GRANTED
4327 : PackageManager.PERMISSION_DENIED;
4328 }
4329 }
4330
Dianne Hackborn39792d22010-08-19 18:01:52 -07004331 /**
4332 * Check if the targetPkg can be granted permission to access uri by
4333 * the callingUid using the given modeFlags. Throws a security exception
4334 * if callingUid is not allowed to do this. Returns the uid of the target
4335 * if the URI permission grant should be performed; returns -1 if it is not
4336 * needed (for example targetPkg already has permission to access the URI).
4337 */
4338 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4339 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4341 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4342 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004343 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
4345
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004346 if (targetPkg != null) {
4347 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4348 "Checking grant " + targetPkg + " permission to " + uri);
4349 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004350
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004351 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352
4353 // If this is not a content: uri, we can't do anything with it.
4354 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004355 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004356 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004357 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 }
4359
4360 String name = uri.getAuthority();
4361 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004362 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 if (cpr != null) {
4364 pi = cpr.info;
4365 } else {
4366 try {
4367 pi = pm.resolveContentProvider(name,
4368 PackageManager.GET_URI_PERMISSION_PATTERNS);
4369 } catch (RemoteException ex) {
4370 }
4371 }
4372 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004373 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004374 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 }
4376
4377 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004378 if (targetPkg != null) {
4379 try {
4380 targetUid = pm.getPackageUid(targetPkg);
4381 if (targetUid < 0) {
4382 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4383 "Can't grant URI permission no uid for: " + targetPkg);
4384 return -1;
4385 }
4386 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004387 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004389 } else {
4390 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 }
4392
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004393 if (targetUid >= 0) {
4394 // First... does the target actually need this permission?
4395 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4396 // No need to grant the target this permission.
4397 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4398 "Target " + targetPkg + " already has full permission to " + uri);
4399 return -1;
4400 }
4401 } else {
4402 // First... there is no target package, so can anyone access it?
4403 boolean allowed = pi.exported;
4404 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4405 if (pi.readPermission != null) {
4406 allowed = false;
4407 }
4408 }
4409 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4410 if (pi.writePermission != null) {
4411 allowed = false;
4412 }
4413 }
4414 if (allowed) {
4415 return -1;
4416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 }
4418
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004419 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 if (!pi.grantUriPermissions) {
4421 throw new SecurityException("Provider " + pi.packageName
4422 + "/" + pi.name
4423 + " does not allow granting of Uri permissions (uri "
4424 + uri + ")");
4425 }
4426 if (pi.uriPermissionPatterns != null) {
4427 final int N = pi.uriPermissionPatterns.length;
4428 boolean allowed = false;
4429 for (int i=0; i<N; i++) {
4430 if (pi.uriPermissionPatterns[i] != null
4431 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4432 allowed = true;
4433 break;
4434 }
4435 }
4436 if (!allowed) {
4437 throw new SecurityException("Provider " + pi.packageName
4438 + "/" + pi.name
4439 + " does not allow granting of permission to path of Uri "
4440 + uri);
4441 }
4442 }
4443
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004444 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004446 if (callingUid != Process.myUid()) {
4447 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4448 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4449 throw new SecurityException("Uid " + callingUid
4450 + " does not have permission to uri " + uri);
4451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 }
4453 }
4454
Dianne Hackborn39792d22010-08-19 18:01:52 -07004455 return targetUid;
4456 }
4457
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004458 public int checkGrantUriPermission(int callingUid, String targetPkg,
4459 Uri uri, int modeFlags) {
4460 synchronized(this) {
4461 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4462 }
4463 }
4464
Dianne Hackborn39792d22010-08-19 18:01:52 -07004465 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4466 Uri uri, int modeFlags, UriPermissionOwner owner) {
4467 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4468 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4469 if (modeFlags == 0) {
4470 return;
4471 }
4472
4473 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 // to the uri, and the target doesn't. Let's now give this to
4475 // the target.
4476
Joe Onorato8a9b2202010-02-26 18:56:32 -08004477 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004478 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 HashMap<Uri, UriPermission> targetUris
4481 = mGrantedUriPermissions.get(targetUid);
4482 if (targetUris == null) {
4483 targetUris = new HashMap<Uri, UriPermission>();
4484 mGrantedUriPermissions.put(targetUid, targetUris);
4485 }
4486
4487 UriPermission perm = targetUris.get(uri);
4488 if (perm == null) {
4489 perm = new UriPermission(targetUid, uri);
4490 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004494 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004496 } else {
4497 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4498 perm.readOwners.add(owner);
4499 owner.addReadPermission(perm);
4500 }
4501 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4502 perm.writeOwners.add(owner);
4503 owner.addWritePermission(perm);
4504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506 }
4507
Dianne Hackborn39792d22010-08-19 18:01:52 -07004508 void grantUriPermissionLocked(int callingUid,
4509 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004510 if (targetPkg == null) {
4511 throw new NullPointerException("targetPkg");
4512 }
4513
Dianne Hackborn39792d22010-08-19 18:01:52 -07004514 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4515 if (targetUid < 0) {
4516 return;
4517 }
4518
4519 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4520 }
4521
4522 /**
4523 * Like checkGrantUriPermissionLocked, but takes an Intent.
4524 */
4525 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4526 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004527 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004528 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004529 + " from " + intent + "; flags=0x"
4530 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4531
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004532 if (targetPkg == null) {
4533 throw new NullPointerException("targetPkg");
4534 }
4535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004537 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 }
4539 Uri data = intent.getData();
4540 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004541 return -1;
4542 }
4543 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4544 intent.getFlags());
4545 }
4546
4547 /**
4548 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4549 */
4550 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4551 String targetPkg, Intent intent, UriPermissionOwner owner) {
4552 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4553 intent.getFlags(), owner);
4554 }
4555
4556 void grantUriPermissionFromIntentLocked(int callingUid,
4557 String targetPkg, Intent intent, UriPermissionOwner owner) {
4558 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4559 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 return;
4561 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004562
4563 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004564 }
4565
4566 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4567 Uri uri, int modeFlags) {
4568 synchronized(this) {
4569 final ProcessRecord r = getRecordForAppLocked(caller);
4570 if (r == null) {
4571 throw new SecurityException("Unable to find app for caller "
4572 + caller
4573 + " when granting permission to uri " + uri);
4574 }
4575 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004576 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 }
4578 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004579 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 }
4581
4582 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4583 null);
4584 }
4585 }
4586
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004587 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4589 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4590 HashMap<Uri, UriPermission> perms
4591 = mGrantedUriPermissions.get(perm.uid);
4592 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004593 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004594 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 perms.remove(perm.uri);
4596 if (perms.size() == 0) {
4597 mGrantedUriPermissions.remove(perm.uid);
4598 }
4599 }
4600 }
4601 }
4602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4604 int modeFlags) {
4605 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4606 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4607 if (modeFlags == 0) {
4608 return;
4609 }
4610
Joe Onorato8a9b2202010-02-26 18:56:32 -08004611 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004612 "Revoking all granted permissions to " + uri);
4613
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004614 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615
4616 final String authority = uri.getAuthority();
4617 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004618 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 if (cpr != null) {
4620 pi = cpr.info;
4621 } else {
4622 try {
4623 pi = pm.resolveContentProvider(authority,
4624 PackageManager.GET_URI_PERMISSION_PATTERNS);
4625 } catch (RemoteException ex) {
4626 }
4627 }
4628 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004629 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 return;
4631 }
4632
4633 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004634 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 // Right now, if you are not the original owner of the permission,
4636 // you are not allowed to revoke it.
4637 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4638 throw new SecurityException("Uid " + callingUid
4639 + " does not have permission to uri " + uri);
4640 //}
4641 }
4642
4643 // Go through all of the permissions and remove any that match.
4644 final List<String> SEGMENTS = uri.getPathSegments();
4645 if (SEGMENTS != null) {
4646 final int NS = SEGMENTS.size();
4647 int N = mGrantedUriPermissions.size();
4648 for (int i=0; i<N; i++) {
4649 HashMap<Uri, UriPermission> perms
4650 = mGrantedUriPermissions.valueAt(i);
4651 Iterator<UriPermission> it = perms.values().iterator();
4652 toploop:
4653 while (it.hasNext()) {
4654 UriPermission perm = it.next();
4655 Uri targetUri = perm.uri;
4656 if (!authority.equals(targetUri.getAuthority())) {
4657 continue;
4658 }
4659 List<String> targetSegments = targetUri.getPathSegments();
4660 if (targetSegments == null) {
4661 continue;
4662 }
4663 if (targetSegments.size() < NS) {
4664 continue;
4665 }
4666 for (int j=0; j<NS; j++) {
4667 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4668 continue toploop;
4669 }
4670 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004671 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004672 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 perm.clearModes(modeFlags);
4674 if (perm.modeFlags == 0) {
4675 it.remove();
4676 }
4677 }
4678 if (perms.size() == 0) {
4679 mGrantedUriPermissions.remove(
4680 mGrantedUriPermissions.keyAt(i));
4681 N--;
4682 i--;
4683 }
4684 }
4685 }
4686 }
4687
4688 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4689 int modeFlags) {
4690 synchronized(this) {
4691 final ProcessRecord r = getRecordForAppLocked(caller);
4692 if (r == null) {
4693 throw new SecurityException("Unable to find app for caller "
4694 + caller
4695 + " when revoking permission to uri " + uri);
4696 }
4697 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004698 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699 return;
4700 }
4701
4702 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4703 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4704 if (modeFlags == 0) {
4705 return;
4706 }
4707
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004708 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709
4710 final String authority = uri.getAuthority();
4711 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004712 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 if (cpr != null) {
4714 pi = cpr.info;
4715 } else {
4716 try {
4717 pi = pm.resolveContentProvider(authority,
4718 PackageManager.GET_URI_PERMISSION_PATTERNS);
4719 } catch (RemoteException ex) {
4720 }
4721 }
4722 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004723 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 return;
4725 }
4726
4727 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4728 }
4729 }
4730
Dianne Hackborn7e269642010-08-25 19:50:20 -07004731 @Override
4732 public IBinder newUriPermissionOwner(String name) {
4733 synchronized(this) {
4734 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4735 return owner.getExternalTokenLocked();
4736 }
4737 }
4738
4739 @Override
4740 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4741 Uri uri, int modeFlags) {
4742 synchronized(this) {
4743 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4744 if (owner == null) {
4745 throw new IllegalArgumentException("Unknown owner: " + token);
4746 }
4747 if (fromUid != Binder.getCallingUid()) {
4748 if (Binder.getCallingUid() != Process.myUid()) {
4749 // Only system code can grant URI permissions on behalf
4750 // of other users.
4751 throw new SecurityException("nice try");
4752 }
4753 }
4754 if (targetPkg == null) {
4755 throw new IllegalArgumentException("null target");
4756 }
4757 if (uri == null) {
4758 throw new IllegalArgumentException("null uri");
4759 }
4760
4761 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4762 }
4763 }
4764
4765 @Override
4766 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4767 synchronized(this) {
4768 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4769 if (owner == null) {
4770 throw new IllegalArgumentException("Unknown owner: " + token);
4771 }
4772
4773 if (uri == null) {
4774 owner.removeUriPermissionsLocked(mode);
4775 } else {
4776 owner.removeUriPermissionLocked(uri, mode);
4777 }
4778 }
4779 }
4780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004781 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4782 synchronized (this) {
4783 ProcessRecord app =
4784 who != null ? getRecordForAppLocked(who) : null;
4785 if (app == null) return;
4786
4787 Message msg = Message.obtain();
4788 msg.what = WAIT_FOR_DEBUGGER_MSG;
4789 msg.obj = app;
4790 msg.arg1 = waiting ? 1 : 0;
4791 mHandler.sendMessage(msg);
4792 }
4793 }
4794
4795 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4796 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004797 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004799 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 }
4801
4802 // =========================================================
4803 // TASK MANAGEMENT
4804 // =========================================================
4805
4806 public List getTasks(int maxNum, int flags,
4807 IThumbnailReceiver receiver) {
4808 ArrayList list = new ArrayList();
4809
4810 PendingThumbnailsRecord pending = null;
4811 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004812 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813
4814 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4817 + ", receiver=" + receiver);
4818
4819 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4820 != PackageManager.PERMISSION_GRANTED) {
4821 if (receiver != null) {
4822 // If the caller wants to wait for pending thumbnails,
4823 // it ain't gonna get them.
4824 try {
4825 receiver.finished();
4826 } catch (RemoteException ex) {
4827 }
4828 }
4829 String msg = "Permission Denial: getTasks() from pid="
4830 + Binder.getCallingPid()
4831 + ", uid=" + Binder.getCallingUid()
4832 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004833 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004834 throw new SecurityException(msg);
4835 }
4836
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004837 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004838 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004839 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004840 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 TaskRecord curTask = null;
4842 int numActivities = 0;
4843 int numRunning = 0;
4844 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004845 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004846 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004847 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004848
4849 // Initialize state for next task if needed.
4850 if (top == null ||
4851 (top.state == ActivityState.INITIALIZING
4852 && top.task == r.task)) {
4853 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 curTask = r.task;
4855 numActivities = numRunning = 0;
4856 }
4857
4858 // Add 'r' into the current task.
4859 numActivities++;
4860 if (r.app != null && r.app.thread != null) {
4861 numRunning++;
4862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863
Joe Onorato8a9b2202010-02-26 18:56:32 -08004864 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 TAG, r.intent.getComponent().flattenToShortString()
4866 + ": task=" + r.task);
4867
4868 // If the next one is a different task, generate a new
4869 // TaskInfo entry for what we have.
4870 if (next == null || next.task != curTask) {
4871 ActivityManager.RunningTaskInfo ci
4872 = new ActivityManager.RunningTaskInfo();
4873 ci.id = curTask.taskId;
4874 ci.baseActivity = r.intent.getComponent();
4875 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004876 if (top.thumbHolder != null) {
4877 ci.description = top.thumbHolder.lastDescription;
4878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 ci.numActivities = numActivities;
4880 ci.numRunning = numRunning;
4881 //System.out.println(
4882 // "#" + maxNum + ": " + " descr=" + ci.description);
4883 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004884 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 TAG, "State=" + top.state + "Idle=" + top.idle
4886 + " app=" + top.app
4887 + " thr=" + (top.app != null ? top.app.thread : null));
4888 if (top.state == ActivityState.RESUMED
4889 || top.state == ActivityState.PAUSING) {
4890 if (top.idle && top.app != null
4891 && top.app.thread != null) {
4892 topRecord = top;
4893 topThumbnail = top.app.thread;
4894 } else {
4895 top.thumbnailNeeded = true;
4896 }
4897 }
4898 if (pending == null) {
4899 pending = new PendingThumbnailsRecord(receiver);
4900 }
4901 pending.pendingRecords.add(top);
4902 }
4903 list.add(ci);
4904 maxNum--;
4905 top = null;
4906 }
4907 }
4908
4909 if (pending != null) {
4910 mPendingThumbnails.add(pending);
4911 }
4912 }
4913
Joe Onorato8a9b2202010-02-26 18:56:32 -08004914 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915
4916 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004917 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 try {
4919 topThumbnail.requestThumbnail(topRecord);
4920 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004921 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 sendPendingThumbnail(null, topRecord, null, null, true);
4923 }
4924 }
4925
4926 if (pending == null && receiver != null) {
4927 // In this case all thumbnails were available and the client
4928 // is being asked to be told when the remaining ones come in...
4929 // which is unusually, since the top-most currently running
4930 // activity should never have a canned thumbnail! Oh well.
4931 try {
4932 receiver.finished();
4933 } catch (RemoteException ex) {
4934 }
4935 }
4936
4937 return list;
4938 }
4939
4940 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4941 int flags) {
4942 synchronized (this) {
4943 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4944 "getRecentTasks()");
4945
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004946 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 final int N = mRecentTasks.size();
4949 ArrayList<ActivityManager.RecentTaskInfo> res
4950 = new ArrayList<ActivityManager.RecentTaskInfo>(
4951 maxNum < N ? maxNum : N);
4952 for (int i=0; i<N && maxNum > 0; i++) {
4953 TaskRecord tr = mRecentTasks.get(i);
4954 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4955 || (tr.intent == null)
4956 || ((tr.intent.getFlags()
4957 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4958 ActivityManager.RecentTaskInfo rti
4959 = new ActivityManager.RecentTaskInfo();
4960 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004961 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 rti.baseIntent = new Intent(
4963 tr.intent != null ? tr.intent : tr.affinityIntent);
4964 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08004965 rti.description = tr.lastDescription;
4966
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004967 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4968 // Check whether this activity is currently available.
4969 try {
4970 if (rti.origActivity != null) {
4971 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4972 continue;
4973 }
4974 } else if (rti.baseIntent != null) {
4975 if (pm.queryIntentActivities(rti.baseIntent,
4976 null, 0) == null) {
4977 continue;
4978 }
4979 }
4980 } catch (RemoteException e) {
4981 // Will never happen.
4982 }
4983 }
4984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 res.add(rti);
4986 maxNum--;
4987 }
4988 }
4989 return res;
4990 }
4991 }
4992
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004993 private TaskRecord taskForIdLocked(int id) {
4994 final int N = mRecentTasks.size();
4995 for (int i=0; i<N; i++) {
4996 TaskRecord tr = mRecentTasks.get(i);
4997 if (tr.taskId == id) {
4998 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004999 }
5000 }
5001 return null;
5002 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005003
5004 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5005 synchronized (this) {
5006 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5007 "getTaskThumbnails()");
5008 TaskRecord tr = taskForIdLocked(id);
5009 if (tr != null) {
5010 return mMainStack.getTaskThumbnailsLocked(tr);
5011 }
5012 }
5013 return null;
5014 }
5015
5016 public boolean removeSubTask(int taskId, int subTaskIndex) {
5017 synchronized (this) {
5018 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5019 "removeSubTask()");
5020 long ident = Binder.clearCallingIdentity();
5021 try {
5022 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5023 } finally {
5024 Binder.restoreCallingIdentity(ident);
5025 }
5026 }
5027 }
5028
5029 private void removeTaskProcessesLocked(ActivityRecord root) {
5030 TaskRecord tr = root.task;
5031 Intent baseIntent = new Intent(
5032 tr.intent != null ? tr.intent : tr.affinityIntent);
5033 ComponentName component = baseIntent.getComponent();
5034 if (component == null) {
5035 Slog.w(TAG, "Now component for base intent of task: " + tr);
5036 return;
5037 }
5038
5039 // Find any running services associated with this app.
5040 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5041 for (ServiceRecord sr : mServices.values()) {
5042 if (sr.packageName.equals(component.getPackageName())) {
5043 services.add(sr);
5044 }
5045 }
5046
5047 // Take care of any running services associated with the app.
5048 for (int i=0; i<services.size(); i++) {
5049 ServiceRecord sr = services.get(i);
5050 if (sr.startRequested) {
5051 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
5052 stopServiceLocked(sr);
5053 } else {
5054 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5055 sr.makeNextStartId(), baseIntent, -1));
5056 if (sr.app != null && sr.app.thread != null) {
5057 sendServiceArgsLocked(sr, false);
5058 }
5059 }
5060 }
5061 }
5062
5063 // Find any running processes associated with this app.
5064 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5065 SparseArray<ProcessRecord> appProcs
5066 = mProcessNames.getMap().get(component.getPackageName());
5067 if (appProcs != null) {
5068 for (int i=0; i<appProcs.size(); i++) {
5069 procs.add(appProcs.valueAt(i));
5070 }
5071 }
5072
5073 // Kill the running processes.
5074 for (int i=0; i<procs.size(); i++) {
5075 ProcessRecord pr = procs.get(i);
5076 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5077 Slog.i(TAG, "Killing " + pr + ": remove task");
5078 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5079 pr.processName, pr.setAdj, "remove task");
5080 Process.killProcessQuiet(pr.pid);
5081 } else {
5082 pr.waitingToKill = "remove task";
5083 }
5084 }
5085 }
5086
5087 public boolean removeTask(int taskId, int flags) {
5088 synchronized (this) {
5089 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5090 "removeTask()");
5091 long ident = Binder.clearCallingIdentity();
5092 try {
5093 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5094 if (r != null) {
5095 mRecentTasks.remove(r.task);
5096
5097 if ((flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0) {
5098 removeTaskProcessesLocked(r);
5099 }
5100
5101 return true;
5102 }
5103 } finally {
5104 Binder.restoreCallingIdentity(ident);
5105 }
5106 }
5107 return false;
5108 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5111 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005112 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 TaskRecord jt = startTask;
5114
5115 // First look backwards
5116 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005117 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 if (r.task != jt) {
5119 jt = r.task;
5120 if (affinity.equals(jt.affinity)) {
5121 return j;
5122 }
5123 }
5124 }
5125
5126 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005127 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 jt = startTask;
5129 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005130 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 if (r.task != jt) {
5132 if (affinity.equals(jt.affinity)) {
5133 return j;
5134 }
5135 jt = r.task;
5136 }
5137 }
5138
5139 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005140 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141 return N-1;
5142 }
5143
5144 return -1;
5145 }
5146
5147 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005148 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005150 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5152 "moveTaskToFront()");
5153
5154 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005155 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5156 Binder.getCallingUid(), "Task to front")) {
5157 return;
5158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 final long origId = Binder.clearCallingIdentity();
5160 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005161 TaskRecord tr = taskForIdLocked(task);
5162 if (tr != null) {
5163 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5164 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005166 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5167 // Caller wants the home activity moved with it. To accomplish this,
5168 // we'll just move the home task to the top first.
5169 mMainStack.moveHomeToFrontLocked();
5170 }
5171 mMainStack.moveTaskToFrontLocked(tr, null);
5172 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005174 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5175 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005177 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5178 mMainStack.mUserLeaving = true;
5179 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005180 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5181 // Caller wants the home activity moved with it. To accomplish this,
5182 // we'll just move the home task to the top first.
5183 mMainStack.moveHomeToFrontLocked();
5184 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005185 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 return;
5187 }
5188 }
5189 } finally {
5190 Binder.restoreCallingIdentity(origId);
5191 }
5192 }
5193 }
5194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 public void moveTaskToBack(int task) {
5196 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5197 "moveTaskToBack()");
5198
5199 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005200 if (mMainStack.mResumedActivity != null
5201 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005202 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5203 Binder.getCallingUid(), "Task to back")) {
5204 return;
5205 }
5206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005207 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005208 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 Binder.restoreCallingIdentity(origId);
5210 }
5211 }
5212
5213 /**
5214 * Moves an activity, and all of the other activities within the same task, to the bottom
5215 * of the history stack. The activity's order within the task is unchanged.
5216 *
5217 * @param token A reference to the activity we wish to move
5218 * @param nonRoot If false then this only works if the activity is the root
5219 * of a task; if true it will work for any activity in a task.
5220 * @return Returns true if the move completed, false if not.
5221 */
5222 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5223 synchronized(this) {
5224 final long origId = Binder.clearCallingIdentity();
5225 int taskId = getTaskForActivityLocked(token, !nonRoot);
5226 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005227 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 }
5229 Binder.restoreCallingIdentity(origId);
5230 }
5231 return false;
5232 }
5233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 public void moveTaskBackwards(int task) {
5235 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5236 "moveTaskBackwards()");
5237
5238 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005239 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5240 Binder.getCallingUid(), "Task backwards")) {
5241 return;
5242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 final long origId = Binder.clearCallingIdentity();
5244 moveTaskBackwardsLocked(task);
5245 Binder.restoreCallingIdentity(origId);
5246 }
5247 }
5248
5249 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005250 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 }
5252
5253 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5254 synchronized(this) {
5255 return getTaskForActivityLocked(token, onlyRoot);
5256 }
5257 }
5258
5259 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005260 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 TaskRecord lastTask = null;
5262 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005263 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 if (r == token) {
5265 if (!onlyRoot || lastTask != r.task) {
5266 return r.task.taskId;
5267 }
5268 return -1;
5269 }
5270 lastTask = r.task;
5271 }
5272
5273 return -1;
5274 }
5275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 public void finishOtherInstances(IBinder token, ComponentName className) {
5277 synchronized(this) {
5278 final long origId = Binder.clearCallingIdentity();
5279
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005280 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 TaskRecord lastTask = null;
5282 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005283 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 if (r.realActivity.equals(className)
5285 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005286 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 null, "others")) {
5288 i--;
5289 N--;
5290 }
5291 }
5292 lastTask = r.task;
5293 }
5294
5295 Binder.restoreCallingIdentity(origId);
5296 }
5297 }
5298
5299 // =========================================================
5300 // THUMBNAILS
5301 // =========================================================
5302
5303 public void reportThumbnail(IBinder token,
5304 Bitmap thumbnail, CharSequence description) {
5305 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5306 final long origId = Binder.clearCallingIdentity();
5307 sendPendingThumbnail(null, token, thumbnail, description, true);
5308 Binder.restoreCallingIdentity(origId);
5309 }
5310
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005311 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 Bitmap thumbnail, CharSequence description, boolean always) {
5313 TaskRecord task = null;
5314 ArrayList receivers = null;
5315
5316 //System.out.println("Send pending thumbnail: " + r);
5317
5318 synchronized(this) {
5319 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005320 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 if (index < 0) {
5322 return;
5323 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005324 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005326 if (thumbnail == null && r.thumbHolder != null) {
5327 thumbnail = r.thumbHolder.lastThumbnail;
5328 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 }
5330 if (thumbnail == null && !always) {
5331 // If there is no thumbnail, and this entry is not actually
5332 // going away, then abort for now and pick up the next
5333 // thumbnail we get.
5334 return;
5335 }
5336 task = r.task;
5337
5338 int N = mPendingThumbnails.size();
5339 int i=0;
5340 while (i<N) {
5341 PendingThumbnailsRecord pr =
5342 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5343 //System.out.println("Looking in " + pr.pendingRecords);
5344 if (pr.pendingRecords.remove(r)) {
5345 if (receivers == null) {
5346 receivers = new ArrayList();
5347 }
5348 receivers.add(pr);
5349 if (pr.pendingRecords.size() == 0) {
5350 pr.finished = true;
5351 mPendingThumbnails.remove(i);
5352 N--;
5353 continue;
5354 }
5355 }
5356 i++;
5357 }
5358 }
5359
5360 if (receivers != null) {
5361 final int N = receivers.size();
5362 for (int i=0; i<N; i++) {
5363 try {
5364 PendingThumbnailsRecord pr =
5365 (PendingThumbnailsRecord)receivers.get(i);
5366 pr.receiver.newThumbnail(
5367 task != null ? task.taskId : -1, thumbnail, description);
5368 if (pr.finished) {
5369 pr.receiver.finished();
5370 }
5371 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005372 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 }
5374 }
5375 }
5376 }
5377
5378 // =========================================================
5379 // CONTENT PROVIDERS
5380 // =========================================================
5381
5382 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5383 List providers = null;
5384 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005385 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005387 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 } catch (RemoteException ex) {
5389 }
5390 if (providers != null) {
5391 final int N = providers.size();
5392 for (int i=0; i<N; i++) {
5393 ProviderInfo cpi =
5394 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005395 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 if (cpr == null) {
5397 cpr = new ContentProviderRecord(cpi, app.info);
5398 mProvidersByClass.put(cpi.name, cpr);
5399 }
5400 app.pubProviders.put(cpi.name, cpr);
5401 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005402 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 }
5404 }
5405 return providers;
5406 }
5407
5408 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005409 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5411 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5412 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005413 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005414 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005415 return null;
5416 }
5417 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005418 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 == PackageManager.PERMISSION_GRANTED) {
5420 return null;
5421 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005422
5423 PathPermission[] pps = cpi.pathPermissions;
5424 if (pps != null) {
5425 int i = pps.length;
5426 while (i > 0) {
5427 i--;
5428 PathPermission pp = pps[i];
5429 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005430 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005431 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005432 return null;
5433 }
5434 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005435 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005436 == PackageManager.PERMISSION_GRANTED) {
5437 return null;
5438 }
5439 }
5440 }
5441
Dianne Hackbornb424b632010-08-18 15:59:05 -07005442 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5443 if (perms != null) {
5444 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5445 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5446 return null;
5447 }
5448 }
5449 }
5450
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005451 String msg;
5452 if (!cpi.exported) {
5453 msg = "Permission Denial: opening provider " + cpi.name
5454 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5455 + ", uid=" + callingUid + ") that is not exported from uid "
5456 + cpi.applicationInfo.uid;
5457 } else {
5458 msg = "Permission Denial: opening provider " + cpi.name
5459 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5460 + ", uid=" + callingUid + ") requires "
5461 + cpi.readPermission + " or " + cpi.writePermission;
5462 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005463 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 return msg;
5465 }
5466
5467 private final ContentProviderHolder getContentProviderImpl(
5468 IApplicationThread caller, String name) {
5469 ContentProviderRecord cpr;
5470 ProviderInfo cpi = null;
5471
5472 synchronized(this) {
5473 ProcessRecord r = null;
5474 if (caller != null) {
5475 r = getRecordForAppLocked(caller);
5476 if (r == null) {
5477 throw new SecurityException(
5478 "Unable to find app for caller " + caller
5479 + " (pid=" + Binder.getCallingPid()
5480 + ") when getting content provider " + name);
5481 }
5482 }
5483
5484 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005485 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 if (cpr != null) {
5487 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005488 String msg;
5489 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5490 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 }
5492
5493 if (r != null && cpr.canRunHere(r)) {
5494 // This provider has been published or is in the process
5495 // of being published... but it is also allowed to run
5496 // in the caller's process, so don't make a connection
5497 // and just let the caller instantiate its own instance.
5498 if (cpr.provider != null) {
5499 // don't give caller the provider object, it needs
5500 // to make its own.
5501 cpr = new ContentProviderRecord(cpr);
5502 }
5503 return cpr;
5504 }
5505
5506 final long origId = Binder.clearCallingIdentity();
5507
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005508 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 // return it right away.
5510 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005511 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005512 "Adding provider requested by "
5513 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005514 + cpr.info.processName);
5515 Integer cnt = r.conProviders.get(cpr);
5516 if (cnt == null) {
5517 r.conProviders.put(cpr, new Integer(1));
5518 } else {
5519 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005522 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5523 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005524 // make sure to count it as being accessed and thus
5525 // back up on the LRU list. This is good because
5526 // content providers are often expensive to start.
5527 updateLruProcessLocked(cpr.app, false, true);
5528 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005529 } else {
5530 cpr.externals++;
5531 }
5532
5533 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 updateOomAdjLocked(cpr.app);
5535 }
5536
5537 Binder.restoreCallingIdentity(origId);
5538
5539 } else {
5540 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005541 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005542 resolveContentProvider(name,
5543 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 } catch (RemoteException ex) {
5545 }
5546 if (cpi == null) {
5547 return null;
5548 }
5549
Dianne Hackbornb424b632010-08-18 15:59:05 -07005550 String msg;
5551 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5552 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 }
5554
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005555 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005556 && !cpi.processName.equals("system")) {
5557 // If this content provider does not run in the system
5558 // process, and the system is not yet ready to run other
5559 // processes, then fail fast instead of hanging.
5560 throw new IllegalArgumentException(
5561 "Attempt to launch content provider before system ready");
5562 }
5563
Dianne Hackborn860755f2010-06-03 18:47:52 -07005564 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 final boolean firstClass = cpr == null;
5566 if (firstClass) {
5567 try {
5568 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005569 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 getApplicationInfo(
5571 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005572 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005574 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 + cpi.name);
5576 return null;
5577 }
5578 cpr = new ContentProviderRecord(cpi, ai);
5579 } catch (RemoteException ex) {
5580 // pm is in same process, this will never happen.
5581 }
5582 }
5583
5584 if (r != null && cpr.canRunHere(r)) {
5585 // If this is a multiprocess provider, then just return its
5586 // info and allow the caller to instantiate it. Only do
5587 // this if the provider is the same user as the caller's
5588 // process, or can run as root (so can be in any process).
5589 return cpr;
5590 }
5591
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005592 if (DEBUG_PROVIDER) {
5593 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005594 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005595 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 }
5597
5598 // This is single process, and our app is now connecting to it.
5599 // See if we are already in the process of launching this
5600 // provider.
5601 final int N = mLaunchingProviders.size();
5602 int i;
5603 for (i=0; i<N; i++) {
5604 if (mLaunchingProviders.get(i) == cpr) {
5605 break;
5606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 }
5608
5609 // If the provider is not already being launched, then get it
5610 // started.
5611 if (i >= N) {
5612 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005613
5614 try {
5615 // Content provider is now in use, its package can't be stopped.
5616 try {
5617 AppGlobals.getPackageManager().setPackageStoppedState(
5618 cpr.appInfo.packageName, false);
5619 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005620 } catch (IllegalArgumentException e) {
5621 Slog.w(TAG, "Failed trying to unstop package "
5622 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005623 }
5624
5625 ProcessRecord proc = startProcessLocked(cpi.processName,
5626 cpr.appInfo, false, 0, "content provider",
5627 new ComponentName(cpi.applicationInfo.packageName,
5628 cpi.name), false);
5629 if (proc == null) {
5630 Slog.w(TAG, "Unable to launch app "
5631 + cpi.applicationInfo.packageName + "/"
5632 + cpi.applicationInfo.uid + " for provider "
5633 + name + ": process is bad");
5634 return null;
5635 }
5636 cpr.launchingApp = proc;
5637 mLaunchingProviders.add(cpr);
5638 } finally {
5639 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 }
5642
5643 // Make sure the provider is published (the same provider class
5644 // may be published under multiple names).
5645 if (firstClass) {
5646 mProvidersByClass.put(cpi.name, cpr);
5647 }
5648 mProvidersByName.put(name, cpr);
5649
5650 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005651 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005652 "Adding provider requested by "
5653 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005654 + cpr.info.processName);
5655 Integer cnt = r.conProviders.get(cpr);
5656 if (cnt == null) {
5657 r.conProviders.put(cpr, new Integer(1));
5658 } else {
5659 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 cpr.clients.add(r);
5662 } else {
5663 cpr.externals++;
5664 }
5665 }
5666 }
5667
5668 // Wait for the provider to be published...
5669 synchronized (cpr) {
5670 while (cpr.provider == null) {
5671 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005672 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 + cpi.applicationInfo.packageName + "/"
5674 + cpi.applicationInfo.uid + " for provider "
5675 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005676 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005677 cpi.applicationInfo.packageName,
5678 cpi.applicationInfo.uid, name);
5679 return null;
5680 }
5681 try {
5682 cpr.wait();
5683 } catch (InterruptedException ex) {
5684 }
5685 }
5686 }
5687 return cpr;
5688 }
5689
5690 public final ContentProviderHolder getContentProvider(
5691 IApplicationThread caller, String name) {
5692 if (caller == null) {
5693 String msg = "null IApplicationThread when getting content provider "
5694 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005695 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 throw new SecurityException(msg);
5697 }
5698
5699 return getContentProviderImpl(caller, name);
5700 }
5701
5702 private ContentProviderHolder getContentProviderExternal(String name) {
5703 return getContentProviderImpl(null, name);
5704 }
5705
5706 /**
5707 * Drop a content provider from a ProcessRecord's bookkeeping
5708 * @param cpr
5709 */
5710 public void removeContentProvider(IApplicationThread caller, String name) {
5711 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005712 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005714 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005715 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005716 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 return;
5718 }
5719 final ProcessRecord r = getRecordForAppLocked(caller);
5720 if (r == null) {
5721 throw new SecurityException(
5722 "Unable to find app for caller " + caller +
5723 " when removing content provider " + name);
5724 }
5725 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005726 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005727 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005728 + r.info.processName + " from process "
5729 + localCpr.appInfo.processName);
5730 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005732 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005733 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 return;
5735 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005736 Integer cnt = r.conProviders.get(localCpr);
5737 if (cnt == null || cnt.intValue() <= 1) {
5738 localCpr.clients.remove(r);
5739 r.conProviders.remove(localCpr);
5740 } else {
5741 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 }
5744 updateOomAdjLocked();
5745 }
5746 }
5747
5748 private void removeContentProviderExternal(String name) {
5749 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005750 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 if(cpr == null) {
5752 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005753 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 return;
5755 }
5756
5757 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005758 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005759 localCpr.externals--;
5760 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005761 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 }
5763 updateOomAdjLocked();
5764 }
5765 }
5766
5767 public final void publishContentProviders(IApplicationThread caller,
5768 List<ContentProviderHolder> providers) {
5769 if (providers == null) {
5770 return;
5771 }
5772
5773 synchronized(this) {
5774 final ProcessRecord r = getRecordForAppLocked(caller);
5775 if (r == null) {
5776 throw new SecurityException(
5777 "Unable to find app for caller " + caller
5778 + " (pid=" + Binder.getCallingPid()
5779 + ") when publishing content providers");
5780 }
5781
5782 final long origId = Binder.clearCallingIdentity();
5783
5784 final int N = providers.size();
5785 for (int i=0; i<N; i++) {
5786 ContentProviderHolder src = providers.get(i);
5787 if (src == null || src.info == null || src.provider == null) {
5788 continue;
5789 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005790 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 if (dst != null) {
5792 mProvidersByClass.put(dst.info.name, dst);
5793 String names[] = dst.info.authority.split(";");
5794 for (int j = 0; j < names.length; j++) {
5795 mProvidersByName.put(names[j], dst);
5796 }
5797
5798 int NL = mLaunchingProviders.size();
5799 int j;
5800 for (j=0; j<NL; j++) {
5801 if (mLaunchingProviders.get(j) == dst) {
5802 mLaunchingProviders.remove(j);
5803 j--;
5804 NL--;
5805 }
5806 }
5807 synchronized (dst) {
5808 dst.provider = src.provider;
5809 dst.app = r;
5810 dst.notifyAll();
5811 }
5812 updateOomAdjLocked(r);
5813 }
5814 }
5815
5816 Binder.restoreCallingIdentity(origId);
5817 }
5818 }
5819
5820 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005821 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005822 synchronized (mSelf) {
5823 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5824 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005825 if (providers != null) {
5826 for (int i=providers.size()-1; i>=0; i--) {
5827 ProviderInfo pi = (ProviderInfo)providers.get(i);
5828 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5829 Slog.w(TAG, "Not installing system proc provider " + pi.name
5830 + ": not system .apk");
5831 providers.remove(i);
5832 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005833 }
5834 }
5835 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005836 if (providers != null) {
5837 mSystemThread.installSystemProviders(providers);
5838 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005839
5840 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 }
5842
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005843 /**
5844 * Allows app to retrieve the MIME type of a URI without having permission
5845 * to access its content provider.
5846 *
5847 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5848 *
5849 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5850 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5851 */
5852 public String getProviderMimeType(Uri uri) {
5853 final String name = uri.getAuthority();
5854 final long ident = Binder.clearCallingIdentity();
5855 ContentProviderHolder holder = null;
5856
5857 try {
5858 holder = getContentProviderExternal(name);
5859 if (holder != null) {
5860 return holder.provider.getType(uri);
5861 }
5862 } catch (RemoteException e) {
5863 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5864 return null;
5865 } finally {
5866 if (holder != null) {
5867 removeContentProviderExternal(name);
5868 }
5869 Binder.restoreCallingIdentity(ident);
5870 }
5871
5872 return null;
5873 }
5874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 // =========================================================
5876 // GLOBAL MANAGEMENT
5877 // =========================================================
5878
5879 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5880 ApplicationInfo info, String customProcess) {
5881 String proc = customProcess != null ? customProcess : info.processName;
5882 BatteryStatsImpl.Uid.Proc ps = null;
5883 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5884 synchronized (stats) {
5885 ps = stats.getProcessStatsLocked(info.uid, proc);
5886 }
5887 return new ProcessRecord(ps, thread, info, proc);
5888 }
5889
5890 final ProcessRecord addAppLocked(ApplicationInfo info) {
5891 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5892
5893 if (app == null) {
5894 app = newProcessRecordLocked(null, info, null);
5895 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005896 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 }
5898
Dianne Hackborne7f97212011-02-24 14:40:20 -08005899 // This package really, really can not be stopped.
5900 try {
5901 AppGlobals.getPackageManager().setPackageStoppedState(
5902 info.packageName, false);
5903 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005904 } catch (IllegalArgumentException e) {
5905 Slog.w(TAG, "Failed trying to unstop package "
5906 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005907 }
5908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5910 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5911 app.persistent = true;
5912 app.maxAdj = CORE_SERVER_ADJ;
5913 }
5914 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5915 mPersistentStartingProcesses.add(app);
5916 startProcessLocked(app, "added application", app.processName);
5917 }
5918
5919 return app;
5920 }
5921
5922 public void unhandledBack() {
5923 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5924 "unhandledBack()");
5925
5926 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005927 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005928 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 TAG, "Performing unhandledBack(): stack size = " + count);
5930 if (count > 1) {
5931 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005932 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5934 Binder.restoreCallingIdentity(origId);
5935 }
5936 }
5937 }
5938
5939 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5940 String name = uri.getAuthority();
5941 ContentProviderHolder cph = getContentProviderExternal(name);
5942 ParcelFileDescriptor pfd = null;
5943 if (cph != null) {
5944 // We record the binder invoker's uid in thread-local storage before
5945 // going to the content provider to open the file. Later, in the code
5946 // that handles all permissions checks, we look for this uid and use
5947 // that rather than the Activity Manager's own uid. The effect is that
5948 // we do the check against the caller's permissions even though it looks
5949 // to the content provider like the Activity Manager itself is making
5950 // the request.
5951 sCallerIdentity.set(new Identity(
5952 Binder.getCallingPid(), Binder.getCallingUid()));
5953 try {
5954 pfd = cph.provider.openFile(uri, "r");
5955 } catch (FileNotFoundException e) {
5956 // do nothing; pfd will be returned null
5957 } finally {
5958 // Ensure that whatever happens, we clean up the identity state
5959 sCallerIdentity.remove();
5960 }
5961
5962 // We've got the fd now, so we're done with the provider.
5963 removeContentProviderExternal(name);
5964 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005965 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 }
5967 return pfd;
5968 }
5969
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005970 // Actually is sleeping or shutting down or whatever else in the future
5971 // is an inactive state.
5972 public boolean isSleeping() {
5973 return mSleeping || mShuttingDown;
5974 }
5975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 public void goingToSleep() {
5977 synchronized(this) {
5978 mSleeping = true;
5979 mWindowManager.setEventDispatching(false);
5980
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005981 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005982
5983 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005984 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005985 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5986 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005987 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 }
5989 }
5990
Dianne Hackborn55280a92009-05-07 15:53:46 -07005991 public boolean shutdown(int timeout) {
5992 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5993 != PackageManager.PERMISSION_GRANTED) {
5994 throw new SecurityException("Requires permission "
5995 + android.Manifest.permission.SHUTDOWN);
5996 }
5997
5998 boolean timedout = false;
5999
6000 synchronized(this) {
6001 mShuttingDown = true;
6002 mWindowManager.setEventDispatching(false);
6003
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006004 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006005 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006006 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006007 while (mMainStack.mResumedActivity != null
6008 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006009 long delay = endTime - System.currentTimeMillis();
6010 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006011 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006012 timedout = true;
6013 break;
6014 }
6015 try {
6016 this.wait();
6017 } catch (InterruptedException e) {
6018 }
6019 }
6020 }
6021 }
6022
6023 mUsageStatsService.shutdown();
6024 mBatteryStatsService.shutdown();
6025
6026 return timedout;
6027 }
6028
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006029 public final void activitySlept(IBinder token) {
6030 if (localLOGV) Slog.v(
6031 TAG, "Activity slept: token=" + token);
6032
6033 ActivityRecord r = null;
6034
6035 final long origId = Binder.clearCallingIdentity();
6036
6037 synchronized (this) {
6038 int index = mMainStack.indexOfTokenLocked(token);
6039 if (index >= 0) {
6040 r = (ActivityRecord)mMainStack.mHistory.get(index);
6041 mMainStack.activitySleptLocked(r);
6042 }
6043 }
6044
6045 Binder.restoreCallingIdentity(origId);
6046 }
6047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 public void wakingUp() {
6049 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006050 mWindowManager.setEventDispatching(true);
6051 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006052 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006053 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 }
6055 }
6056
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006057 public void stopAppSwitches() {
6058 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6059 != PackageManager.PERMISSION_GRANTED) {
6060 throw new SecurityException("Requires permission "
6061 + android.Manifest.permission.STOP_APP_SWITCHES);
6062 }
6063
6064 synchronized(this) {
6065 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6066 + APP_SWITCH_DELAY_TIME;
6067 mDidAppSwitch = false;
6068 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6069 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6070 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6071 }
6072 }
6073
6074 public void resumeAppSwitches() {
6075 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6076 != PackageManager.PERMISSION_GRANTED) {
6077 throw new SecurityException("Requires permission "
6078 + android.Manifest.permission.STOP_APP_SWITCHES);
6079 }
6080
6081 synchronized(this) {
6082 // Note that we don't execute any pending app switches... we will
6083 // let those wait until either the timeout, or the next start
6084 // activity request.
6085 mAppSwitchesAllowedTime = 0;
6086 }
6087 }
6088
6089 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6090 String name) {
6091 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6092 return true;
6093 }
6094
6095 final int perm = checkComponentPermission(
6096 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006097 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006098 if (perm == PackageManager.PERMISSION_GRANTED) {
6099 return true;
6100 }
6101
Joe Onorato8a9b2202010-02-26 18:56:32 -08006102 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006103 return false;
6104 }
6105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 public void setDebugApp(String packageName, boolean waitForDebugger,
6107 boolean persistent) {
6108 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6109 "setDebugApp()");
6110
6111 // Note that this is not really thread safe if there are multiple
6112 // callers into it at the same time, but that's not a situation we
6113 // care about.
6114 if (persistent) {
6115 final ContentResolver resolver = mContext.getContentResolver();
6116 Settings.System.putString(
6117 resolver, Settings.System.DEBUG_APP,
6118 packageName);
6119 Settings.System.putInt(
6120 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6121 waitForDebugger ? 1 : 0);
6122 }
6123
6124 synchronized (this) {
6125 if (!persistent) {
6126 mOrigDebugApp = mDebugApp;
6127 mOrigWaitForDebugger = mWaitForDebugger;
6128 }
6129 mDebugApp = packageName;
6130 mWaitForDebugger = waitForDebugger;
6131 mDebugTransient = !persistent;
6132 if (packageName != null) {
6133 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006134 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 Binder.restoreCallingIdentity(origId);
6136 }
6137 }
6138 }
6139
6140 public void setAlwaysFinish(boolean enabled) {
6141 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6142 "setAlwaysFinish()");
6143
6144 Settings.System.putInt(
6145 mContext.getContentResolver(),
6146 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6147
6148 synchronized (this) {
6149 mAlwaysFinishActivities = enabled;
6150 }
6151 }
6152
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006153 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006154 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006155 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006157 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006158 }
6159 }
6160
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006161 public boolean isUserAMonkey() {
6162 // For now the fact that there is a controller implies
6163 // we have a monkey.
6164 synchronized (this) {
6165 return mController != null;
6166 }
6167 }
6168
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006169 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006170 synchronized (this) {
6171 mWatchers.register(watcher);
6172 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006173 }
6174
6175 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006176 synchronized (this) {
6177 mWatchers.unregister(watcher);
6178 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006179 }
6180
Daniel Sandler69a48172010-06-23 16:29:36 -04006181 public void setImmersive(IBinder token, boolean immersive) {
6182 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006183 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006184 if (index < 0) {
6185 throw new IllegalArgumentException();
6186 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006187 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006188 r.immersive = immersive;
6189 }
6190 }
6191
6192 public boolean isImmersive(IBinder token) {
6193 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006194 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006195 if (index < 0) {
6196 throw new IllegalArgumentException();
6197 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006198 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006199 return r.immersive;
6200 }
6201 }
6202
6203 public boolean isTopActivityImmersive() {
6204 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006205 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006206 return (r != null) ? r.immersive : false;
6207 }
6208 }
6209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 public final void enterSafeMode() {
6211 synchronized(this) {
6212 // It only makes sense to do this before the system is ready
6213 // and started launching other packages.
6214 if (!mSystemReady) {
6215 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006216 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006217 } catch (RemoteException e) {
6218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 }
6220 }
6221 }
6222
Jeff Brownb09abc12011-01-13 21:08:27 -08006223 public final void showSafeModeOverlay() {
6224 View v = LayoutInflater.from(mContext).inflate(
6225 com.android.internal.R.layout.safe_mode, null);
6226 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6227 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6228 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6229 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6230 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6231 lp.format = v.getBackground().getOpacity();
6232 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6233 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6234 ((WindowManager)mContext.getSystemService(
6235 Context.WINDOW_SERVICE)).addView(v, lp);
6236 }
6237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006238 public void noteWakeupAlarm(IIntentSender sender) {
6239 if (!(sender instanceof PendingIntentRecord)) {
6240 return;
6241 }
6242 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6243 synchronized (stats) {
6244 if (mBatteryStatsService.isOnBattery()) {
6245 mBatteryStatsService.enforceCallingPermission();
6246 PendingIntentRecord rec = (PendingIntentRecord)sender;
6247 int MY_UID = Binder.getCallingUid();
6248 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6249 BatteryStatsImpl.Uid.Pkg pkg =
6250 stats.getPackageStatsLocked(uid, rec.key.packageName);
6251 pkg.incWakeupsLocked();
6252 }
6253 }
6254 }
6255
Dianne Hackborn64825172011-03-02 21:32:58 -08006256 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006258 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006260 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 // XXX Note: don't acquire main activity lock here, because the window
6262 // manager calls in with its locks held.
6263
6264 boolean killed = false;
6265 synchronized (mPidsSelfLocked) {
6266 int[] types = new int[pids.length];
6267 int worstType = 0;
6268 for (int i=0; i<pids.length; i++) {
6269 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6270 if (proc != null) {
6271 int type = proc.setAdj;
6272 types[i] = type;
6273 if (type > worstType) {
6274 worstType = type;
6275 }
6276 }
6277 }
6278
Dianne Hackborn64825172011-03-02 21:32:58 -08006279 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 // then constrain it so we will kill all hidden procs.
6281 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6282 worstType = HIDDEN_APP_MIN_ADJ;
6283 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006284
6285 // If this is not a secure call, don't let it kill processes that
6286 // are important.
6287 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6288 worstType = SECONDARY_SERVER_ADJ;
6289 }
6290
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006291 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 for (int i=0; i<pids.length; i++) {
6293 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6294 if (proc == null) {
6295 continue;
6296 }
6297 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006298 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006299 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006300 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6301 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006303 proc.killedBackground = true;
6304 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006305 }
6306 }
6307 }
6308 return killed;
6309 }
6310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006311 public final void startRunning(String pkg, String cls, String action,
6312 String data) {
6313 synchronized(this) {
6314 if (mStartRunning) {
6315 return;
6316 }
6317 mStartRunning = true;
6318 mTopComponent = pkg != null && cls != null
6319 ? new ComponentName(pkg, cls) : null;
6320 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6321 mTopData = data;
6322 if (!mSystemReady) {
6323 return;
6324 }
6325 }
6326
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006327 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 }
6329
6330 private void retrieveSettings() {
6331 final ContentResolver resolver = mContext.getContentResolver();
6332 String debugApp = Settings.System.getString(
6333 resolver, Settings.System.DEBUG_APP);
6334 boolean waitForDebugger = Settings.System.getInt(
6335 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6336 boolean alwaysFinishActivities = Settings.System.getInt(
6337 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6338
6339 Configuration configuration = new Configuration();
6340 Settings.System.getConfiguration(resolver, configuration);
6341
6342 synchronized (this) {
6343 mDebugApp = mOrigDebugApp = debugApp;
6344 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6345 mAlwaysFinishActivities = alwaysFinishActivities;
6346 // This happens before any activities are started, so we can
6347 // change mConfiguration in-place.
6348 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006349 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006350 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 }
6352 }
6353
6354 public boolean testIsSystemReady() {
6355 // no need to synchronize(this) just to read & return the value
6356 return mSystemReady;
6357 }
6358
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006359 private static File getCalledPreBootReceiversFile() {
6360 File dataDir = Environment.getDataDirectory();
6361 File systemDir = new File(dataDir, "system");
6362 File fname = new File(systemDir, "called_pre_boots.dat");
6363 return fname;
6364 }
6365
6366 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6367 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6368 File file = getCalledPreBootReceiversFile();
6369 FileInputStream fis = null;
6370 try {
6371 fis = new FileInputStream(file);
6372 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6373 int vers = dis.readInt();
6374 String codename = dis.readUTF();
6375 if (vers == android.os.Build.VERSION.SDK_INT
6376 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6377 int num = dis.readInt();
6378 while (num > 0) {
6379 num--;
6380 String pkg = dis.readUTF();
6381 String cls = dis.readUTF();
6382 lastDoneReceivers.add(new ComponentName(pkg, cls));
6383 }
6384 }
6385 } catch (FileNotFoundException e) {
6386 } catch (IOException e) {
6387 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6388 } finally {
6389 if (fis != null) {
6390 try {
6391 fis.close();
6392 } catch (IOException e) {
6393 }
6394 }
6395 }
6396 return lastDoneReceivers;
6397 }
6398
6399 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6400 File file = getCalledPreBootReceiversFile();
6401 FileOutputStream fos = null;
6402 DataOutputStream dos = null;
6403 try {
6404 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6405 fos = new FileOutputStream(file);
6406 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6407 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6408 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6409 dos.writeInt(list.size());
6410 for (int i=0; i<list.size(); i++) {
6411 dos.writeUTF(list.get(i).getPackageName());
6412 dos.writeUTF(list.get(i).getClassName());
6413 }
6414 } catch (IOException e) {
6415 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6416 file.delete();
6417 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006418 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006419 if (dos != null) {
6420 try {
6421 dos.close();
6422 } catch (IOException e) {
6423 // TODO Auto-generated catch block
6424 e.printStackTrace();
6425 }
6426 }
6427 }
6428 }
6429
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006430 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 // In the simulator, startRunning will never have been called, which
6432 // normally sets a few crucial variables. Do it here instead.
6433 if (!Process.supportsProcesses()) {
6434 mStartRunning = true;
6435 mTopAction = Intent.ACTION_MAIN;
6436 }
6437
6438 synchronized(this) {
6439 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006440 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 return;
6442 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006443
6444 // Check to see if there are any update receivers to run.
6445 if (!mDidUpdate) {
6446 if (mWaitingUpdate) {
6447 return;
6448 }
6449 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6450 List<ResolveInfo> ris = null;
6451 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006452 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006453 intent, null, 0);
6454 } catch (RemoteException e) {
6455 }
6456 if (ris != null) {
6457 for (int i=ris.size()-1; i>=0; i--) {
6458 if ((ris.get(i).activityInfo.applicationInfo.flags
6459 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6460 ris.remove(i);
6461 }
6462 }
6463 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006464
6465 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6466
6467 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006468 for (int i=0; i<ris.size(); i++) {
6469 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006470 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6471 if (lastDoneReceivers.contains(comp)) {
6472 ris.remove(i);
6473 i--;
6474 }
6475 }
6476
6477 for (int i=0; i<ris.size(); i++) {
6478 ActivityInfo ai = ris.get(i).activityInfo;
6479 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6480 doneReceivers.add(comp);
6481 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006482 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006483 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006484 finisher = new IIntentReceiver.Stub() {
6485 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006486 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006487 boolean sticky) {
6488 // The raw IIntentReceiver interface is called
6489 // with the AM lock held, so redispatch to
6490 // execute our code without the lock.
6491 mHandler.post(new Runnable() {
6492 public void run() {
6493 synchronized (ActivityManagerService.this) {
6494 mDidUpdate = true;
6495 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006496 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006497 systemReady(goingCallback);
6498 }
6499 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006500 }
6501 };
6502 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006503 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006504 broadcastIntentLocked(null, null, intent, null, finisher,
6505 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006506 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006507 mWaitingUpdate = true;
6508 }
6509 }
6510 }
6511 if (mWaitingUpdate) {
6512 return;
6513 }
6514 mDidUpdate = true;
6515 }
6516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517 mSystemReady = true;
6518 if (!mStartRunning) {
6519 return;
6520 }
6521 }
6522
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006523 ArrayList<ProcessRecord> procsToKill = null;
6524 synchronized(mPidsSelfLocked) {
6525 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6526 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6527 if (!isAllowedWhileBooting(proc.info)){
6528 if (procsToKill == null) {
6529 procsToKill = new ArrayList<ProcessRecord>();
6530 }
6531 procsToKill.add(proc);
6532 }
6533 }
6534 }
6535
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006536 synchronized(this) {
6537 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006538 for (int i=procsToKill.size()-1; i>=0; i--) {
6539 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006540 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006541 removeProcessLocked(proc, true);
6542 }
6543 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006544
6545 // Now that we have cleaned up any update processes, we
6546 // are ready to start launching real processes and know that
6547 // we won't trample on them any more.
6548 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006549 }
6550
Joe Onorato8a9b2202010-02-26 18:56:32 -08006551 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006552 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 SystemClock.uptimeMillis());
6554
6555 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006556 // Make sure we have no pre-ready processes sitting around.
6557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6559 ResolveInfo ri = mContext.getPackageManager()
6560 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006561 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 CharSequence errorMsg = null;
6563 if (ri != null) {
6564 ActivityInfo ai = ri.activityInfo;
6565 ApplicationInfo app = ai.applicationInfo;
6566 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6567 mTopAction = Intent.ACTION_FACTORY_TEST;
6568 mTopData = null;
6569 mTopComponent = new ComponentName(app.packageName,
6570 ai.name);
6571 } else {
6572 errorMsg = mContext.getResources().getText(
6573 com.android.internal.R.string.factorytest_not_system);
6574 }
6575 } else {
6576 errorMsg = mContext.getResources().getText(
6577 com.android.internal.R.string.factorytest_no_action);
6578 }
6579 if (errorMsg != null) {
6580 mTopAction = null;
6581 mTopData = null;
6582 mTopComponent = null;
6583 Message msg = Message.obtain();
6584 msg.what = SHOW_FACTORY_ERROR_MSG;
6585 msg.getData().putCharSequence("msg", errorMsg);
6586 mHandler.sendMessage(msg);
6587 }
6588 }
6589 }
6590
6591 retrieveSettings();
6592
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006593 if (goingCallback != null) goingCallback.run();
6594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006595 synchronized (this) {
6596 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6597 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006598 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006599 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006600 if (apps != null) {
6601 int N = apps.size();
6602 int i;
6603 for (i=0; i<N; i++) {
6604 ApplicationInfo info
6605 = (ApplicationInfo)apps.get(i);
6606 if (info != null &&
6607 !info.packageName.equals("android")) {
6608 addAppLocked(info);
6609 }
6610 }
6611 }
6612 } catch (RemoteException ex) {
6613 // pm is in same process, this will never happen.
6614 }
6615 }
6616
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006617 // Start up initial activity.
6618 mBooting = true;
6619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006620 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006621 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006622 Message msg = Message.obtain();
6623 msg.what = SHOW_UID_ERROR_MSG;
6624 mHandler.sendMessage(msg);
6625 }
6626 } catch (RemoteException e) {
6627 }
6628
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006629 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 }
6631 }
6632
Dan Egnorb7f03672009-12-09 16:22:32 -08006633 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006634 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006636 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006637 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 startAppProblemLocked(app);
6639 app.stopFreezingAllLocked();
6640 return handleAppCrashLocked(app);
6641 }
6642
Dan Egnorb7f03672009-12-09 16:22:32 -08006643 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006644 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006646 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006647 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6648 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 startAppProblemLocked(app);
6650 app.stopFreezingAllLocked();
6651 }
6652
6653 /**
6654 * Generate a process error record, suitable for attachment to a ProcessRecord.
6655 *
6656 * @param app The ProcessRecord in which the error occurred.
6657 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6658 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006659 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 * @param shortMsg Short message describing the crash.
6661 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006662 * @param stackTrace Full crash stack trace, may be null.
6663 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 * @return Returns a fully-formed AppErrorStateInfo record.
6665 */
6666 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006667 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 report.condition = condition;
6671 report.processName = app.processName;
6672 report.pid = app.pid;
6673 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006674 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 report.shortMsg = shortMsg;
6676 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006677 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006678
6679 return report;
6680 }
6681
Dan Egnor42471dd2010-01-07 17:25:22 -08006682 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683 synchronized (this) {
6684 app.crashing = false;
6685 app.crashingReport = null;
6686 app.notResponding = false;
6687 app.notRespondingReport = null;
6688 if (app.anrDialog == fromDialog) {
6689 app.anrDialog = null;
6690 }
6691 if (app.waitDialog == fromDialog) {
6692 app.waitDialog = null;
6693 }
6694 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006695 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006696 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006697 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6698 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006699 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 }
6702 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006703
Dan Egnorb7f03672009-12-09 16:22:32 -08006704 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 long now = SystemClock.uptimeMillis();
6706
6707 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6708 app.info.uid);
6709 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6710 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006711 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006713 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006715 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6716 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006717 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006718 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006719 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006720 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 }
6722 }
6723 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006724 // Don't let services in this process be restarted and potentially
6725 // annoy the user repeatedly. Unless it is persistent, since those
6726 // processes run critical code.
6727 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006728 // We don't want to start this process again until the user
6729 // explicitly does so... but for persistent process, we really
6730 // need to keep it running. If a persistent process is actually
6731 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006732 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 app.info.processName);
6734 mBadProcesses.put(app.info.processName, app.info.uid, now);
6735 app.bad = true;
6736 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6737 app.removed = true;
6738 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006739 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006740 return false;
6741 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006742 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006743 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006744 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006745 if (r.app == app) {
6746 // If the top running activity is from this crashing
6747 // process, then terminate it to avoid getting in a loop.
6748 Slog.w(TAG, " Force finishing activity "
6749 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006750 int index = mMainStack.indexOfTokenLocked(r);
6751 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006752 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006753 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006754 // stopped, to avoid a situation where one will get
6755 // re-start our crashing activity once it gets resumed again.
6756 index--;
6757 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006758 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006759 if (r.state == ActivityState.RESUMED
6760 || r.state == ActivityState.PAUSING
6761 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006762 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006763 Slog.w(TAG, " Force finishing activity "
6764 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006765 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006766 Activity.RESULT_CANCELED, null, "crashed");
6767 }
6768 }
6769 }
6770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 }
6772
6773 // Bump up the crash count of any services currently running in the proc.
6774 if (app.services.size() != 0) {
6775 // Any services running in the application need to be placed
6776 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006777 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006778 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006779 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780 sr.crashCount++;
6781 }
6782 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006783
6784 // If the crashing process is what we consider to be the "home process" and it has been
6785 // replaced by a third-party app, clear the package preferred activities from packages
6786 // with a home activity running in the process to prevent a repeatedly crashing app
6787 // from blocking the user to manually clear the list.
6788 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6789 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6790 Iterator it = mHomeProcess.activities.iterator();
6791 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006792 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006793 if (r.isHomeActivity) {
6794 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6795 try {
6796 ActivityThread.getPackageManager()
6797 .clearPackagePreferredActivities(r.packageName);
6798 } catch (RemoteException c) {
6799 // pm is in same process, this will never happen.
6800 }
6801 }
6802 }
6803 }
6804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6806 return true;
6807 }
6808
6809 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006810 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6811 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 skipCurrentReceiverLocked(app);
6813 }
6814
6815 void skipCurrentReceiverLocked(ProcessRecord app) {
6816 boolean reschedule = false;
6817 BroadcastRecord r = app.curReceiver;
6818 if (r != null) {
6819 // The current broadcast is waiting for this app's receiver
6820 // to be finished. Looks like that's not going to happen, so
6821 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006822 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6824 r.resultExtras, r.resultAbort, true);
6825 reschedule = true;
6826 }
6827 r = mPendingBroadcast;
6828 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006829 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006830 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006831 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6833 r.resultExtras, r.resultAbort, true);
6834 reschedule = true;
6835 }
6836 if (reschedule) {
6837 scheduleBroadcastsLocked();
6838 }
6839 }
6840
Dan Egnor60d87622009-12-16 16:32:58 -08006841 /**
6842 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6843 * The application process will exit immediately after this call returns.
6844 * @param app object of the crashing app, null for the system server
6845 * @param crashInfo describing the exception
6846 */
6847 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006848 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006849
6850 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6851 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006852 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006853 crashInfo.exceptionClassName,
6854 crashInfo.exceptionMessage,
6855 crashInfo.throwFileName,
6856 crashInfo.throwLineNumber);
6857
Dan Egnor42471dd2010-01-07 17:25:22 -08006858 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006859
6860 crashApplication(r, crashInfo);
6861 }
6862
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006863 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006864 IBinder app,
6865 int violationMask,
6866 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006867 ProcessRecord r = findAppProcess(app, "StrictMode");
6868 if (r == null) {
6869 return;
6870 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006871
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006872 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006873 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006874 boolean logIt = true;
6875 synchronized (mAlreadyLoggedViolatedStacks) {
6876 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6877 logIt = false;
6878 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006879 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006880 // the relative pain numbers, without logging all
6881 // the stack traces repeatedly. We'd want to do
6882 // likewise in the client code, which also does
6883 // dup suppression, before the Binder call.
6884 } else {
6885 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6886 mAlreadyLoggedViolatedStacks.clear();
6887 }
6888 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6889 }
6890 }
6891 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006892 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006893 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006894 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006895
6896 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6897 AppErrorResult result = new AppErrorResult();
6898 synchronized (this) {
6899 final long origId = Binder.clearCallingIdentity();
6900
6901 Message msg = Message.obtain();
6902 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6903 HashMap<String, Object> data = new HashMap<String, Object>();
6904 data.put("result", result);
6905 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006906 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006907 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006908 msg.obj = data;
6909 mHandler.sendMessage(msg);
6910
6911 Binder.restoreCallingIdentity(origId);
6912 }
6913 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006914 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006915 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006916 }
6917
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006918 // Depending on the policy in effect, there could be a bunch of
6919 // these in quick succession so we try to batch these together to
6920 // minimize disk writes, number of dropbox entries, and maximize
6921 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006922 private void logStrictModeViolationToDropBox(
6923 ProcessRecord process,
6924 StrictMode.ViolationInfo info) {
6925 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006926 return;
6927 }
6928 final boolean isSystemApp = process == null ||
6929 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6930 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6931 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6932 final DropBoxManager dbox = (DropBoxManager)
6933 mContext.getSystemService(Context.DROPBOX_SERVICE);
6934
6935 // Exit early if the dropbox isn't configured to accept this report type.
6936 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6937
6938 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006939 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006940 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6941 synchronized (sb) {
6942 bufferWasEmpty = sb.length() == 0;
6943 appendDropBoxProcessHeaders(process, sb);
6944 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6945 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006946 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6947 if (info.violationNumThisLoop != 0) {
6948 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6949 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006950 if (info.numAnimationsRunning != 0) {
6951 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6952 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006953 if (info.broadcastIntentAction != null) {
6954 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6955 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006956 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006957 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006958 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006959 if (info.numInstances != -1) {
6960 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6961 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006962 if (info.tags != null) {
6963 for (String tag : info.tags) {
6964 sb.append("Span-Tag: ").append(tag).append("\n");
6965 }
6966 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006967 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006968 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6969 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006970 }
6971 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006972
6973 // Only buffer up to ~64k. Various logging bits truncate
6974 // things at 128k.
6975 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006976 }
6977
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006978 // Flush immediately if the buffer's grown too large, or this
6979 // is a non-system app. Non-system apps are isolated with a
6980 // different tag & policy and not batched.
6981 //
6982 // Batching is useful during internal testing with
6983 // StrictMode settings turned up high. Without batching,
6984 // thousands of separate files could be created on boot.
6985 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006986 new Thread("Error dump: " + dropboxTag) {
6987 @Override
6988 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006989 String report;
6990 synchronized (sb) {
6991 report = sb.toString();
6992 sb.delete(0, sb.length());
6993 sb.trimToSize();
6994 }
6995 if (report.length() != 0) {
6996 dbox.addText(dropboxTag, report);
6997 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006998 }
6999 }.start();
7000 return;
7001 }
7002
7003 // System app batching:
7004 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007005 // An existing dropbox-writing thread is outstanding, so
7006 // we don't need to start it up. The existing thread will
7007 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007008 return;
7009 }
7010
7011 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7012 // (After this point, we shouldn't access AMS internal data structures.)
7013 new Thread("Error dump: " + dropboxTag) {
7014 @Override
7015 public void run() {
7016 // 5 second sleep to let stacks arrive and be batched together
7017 try {
7018 Thread.sleep(5000); // 5 seconds
7019 } catch (InterruptedException e) {}
7020
7021 String errorReport;
7022 synchronized (mStrictModeBuffer) {
7023 errorReport = mStrictModeBuffer.toString();
7024 if (errorReport.length() == 0) {
7025 return;
7026 }
7027 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7028 mStrictModeBuffer.trimToSize();
7029 }
7030 dbox.addText(dropboxTag, errorReport);
7031 }
7032 }.start();
7033 }
7034
Dan Egnor60d87622009-12-16 16:32:58 -08007035 /**
7036 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7037 * @param app object of the crashing app, null for the system server
7038 * @param tag reported by the caller
7039 * @param crashInfo describing the context of the error
7040 * @return true if the process should exit immediately (WTF is fatal)
7041 */
7042 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007043 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007044 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007045
7046 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7047 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007048 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007049 tag, crashInfo.exceptionMessage);
7050
Dan Egnor42471dd2010-01-07 17:25:22 -08007051 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007052
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007053 if (r != null && r.pid != Process.myPid() &&
7054 Settings.Secure.getInt(mContext.getContentResolver(),
7055 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007056 crashApplication(r, crashInfo);
7057 return true;
7058 } else {
7059 return false;
7060 }
7061 }
7062
7063 /**
7064 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7065 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7066 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007067 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007068 if (app == null) {
7069 return null;
7070 }
7071
7072 synchronized (this) {
7073 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7074 final int NA = apps.size();
7075 for (int ia=0; ia<NA; ia++) {
7076 ProcessRecord p = apps.valueAt(ia);
7077 if (p.thread != null && p.thread.asBinder() == app) {
7078 return p;
7079 }
7080 }
7081 }
7082
Dianne Hackborncb44d962011-03-10 17:02:27 -08007083 Slog.w(TAG, "Can't find mystery application for " + reason
7084 + " from pid=" + Binder.getCallingPid()
7085 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007086 return null;
7087 }
7088 }
7089
7090 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007091 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7092 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007093 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007094 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7095 // Note: ProcessRecord 'process' is guarded by the service
7096 // instance. (notably process.pkgList, which could otherwise change
7097 // concurrently during execution of this method)
7098 synchronized (this) {
7099 if (process == null || process.pid == MY_PID) {
7100 sb.append("Process: system_server\n");
7101 } else {
7102 sb.append("Process: ").append(process.processName).append("\n");
7103 }
7104 if (process == null) {
7105 return;
7106 }
Dan Egnora455d192010-03-12 08:52:28 -08007107 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007108 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007109 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7110 for (String pkg : process.pkgList) {
7111 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007112 try {
Dan Egnora455d192010-03-12 08:52:28 -08007113 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7114 if (pi != null) {
7115 sb.append(" v").append(pi.versionCode);
7116 if (pi.versionName != null) {
7117 sb.append(" (").append(pi.versionName).append(")");
7118 }
7119 }
7120 } catch (RemoteException e) {
7121 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007122 }
Dan Egnora455d192010-03-12 08:52:28 -08007123 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007124 }
Dan Egnora455d192010-03-12 08:52:28 -08007125 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007126 }
7127
7128 private static String processClass(ProcessRecord process) {
7129 if (process == null || process.pid == MY_PID) {
7130 return "system_server";
7131 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7132 return "system_app";
7133 } else {
7134 return "data_app";
7135 }
7136 }
7137
7138 /**
7139 * Write a description of an error (crash, WTF, ANR) to the drop box.
7140 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7141 * @param process which caused the error, null means the system server
7142 * @param activity which triggered the error, null if unknown
7143 * @param parent activity related to the error, null if unknown
7144 * @param subject line related to the error, null if absent
7145 * @param report in long form describing the error, null if absent
7146 * @param logFile to include in the report, null if none
7147 * @param crashInfo giving an application stack trace, null if absent
7148 */
7149 public void addErrorToDropBox(String eventType,
7150 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7151 final String report, final File logFile,
7152 final ApplicationErrorReport.CrashInfo crashInfo) {
7153 // NOTE -- this must never acquire the ActivityManagerService lock,
7154 // otherwise the watchdog may be prevented from resetting the system.
7155
7156 final String dropboxTag = processClass(process) + "_" + eventType;
7157 final DropBoxManager dbox = (DropBoxManager)
7158 mContext.getSystemService(Context.DROPBOX_SERVICE);
7159
7160 // Exit early if the dropbox isn't configured to accept this report type.
7161 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7162
7163 final StringBuilder sb = new StringBuilder(1024);
7164 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007165 if (activity != null) {
7166 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7167 }
7168 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7169 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7170 }
7171 if (parent != null && parent != activity) {
7172 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7173 }
7174 if (subject != null) {
7175 sb.append("Subject: ").append(subject).append("\n");
7176 }
7177 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007178 if (Debug.isDebuggerConnected()) {
7179 sb.append("Debugger: Connected\n");
7180 }
Dan Egnora455d192010-03-12 08:52:28 -08007181 sb.append("\n");
7182
7183 // Do the rest in a worker thread to avoid blocking the caller on I/O
7184 // (After this point, we shouldn't access AMS internal data structures.)
7185 Thread worker = new Thread("Error dump: " + dropboxTag) {
7186 @Override
7187 public void run() {
7188 if (report != null) {
7189 sb.append(report);
7190 }
7191 if (logFile != null) {
7192 try {
7193 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7194 } catch (IOException e) {
7195 Slog.e(TAG, "Error reading " + logFile, e);
7196 }
7197 }
7198 if (crashInfo != null && crashInfo.stackTrace != null) {
7199 sb.append(crashInfo.stackTrace);
7200 }
7201
7202 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7203 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7204 if (lines > 0) {
7205 sb.append("\n");
7206
7207 // Merge several logcat streams, and take the last N lines
7208 InputStreamReader input = null;
7209 try {
7210 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7211 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7212 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7213
7214 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7215 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7216 input = new InputStreamReader(logcat.getInputStream());
7217
7218 int num;
7219 char[] buf = new char[8192];
7220 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7221 } catch (IOException e) {
7222 Slog.e(TAG, "Error running logcat", e);
7223 } finally {
7224 if (input != null) try { input.close(); } catch (IOException e) {}
7225 }
7226 }
7227
7228 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007229 }
Dan Egnora455d192010-03-12 08:52:28 -08007230 };
7231
7232 if (process == null || process.pid == MY_PID) {
7233 worker.run(); // We may be about to die -- need to run this synchronously
7234 } else {
7235 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007236 }
7237 }
7238
7239 /**
7240 * Bring up the "unexpected error" dialog box for a crashing app.
7241 * Deal with edge cases (intercepts from instrumented applications,
7242 * ActivityController, error intent receivers, that sort of thing).
7243 * @param r the application crashing
7244 * @param crashInfo describing the failure
7245 */
7246 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007247 long timeMillis = System.currentTimeMillis();
7248 String shortMsg = crashInfo.exceptionClassName;
7249 String longMsg = crashInfo.exceptionMessage;
7250 String stackTrace = crashInfo.stackTrace;
7251 if (shortMsg != null && longMsg != null) {
7252 longMsg = shortMsg + ": " + longMsg;
7253 } else if (shortMsg != null) {
7254 longMsg = shortMsg;
7255 }
7256
Dan Egnor60d87622009-12-16 16:32:58 -08007257 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007259 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007260 try {
7261 String name = r != null ? r.processName : null;
7262 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007263 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007264 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007265 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 + " at watcher's request");
7267 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007268 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269 }
7270 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007271 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 }
7273 }
7274
7275 final long origId = Binder.clearCallingIdentity();
7276
7277 // If this process is running instrumentation, finish it.
7278 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007279 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007281 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7282 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 Bundle info = new Bundle();
7284 info.putString("shortMsg", shortMsg);
7285 info.putString("longMsg", longMsg);
7286 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7287 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007288 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 }
7290
Dan Egnor60d87622009-12-16 16:32:58 -08007291 // If we can't identify the process or it's already exceeded its crash quota,
7292 // quit right away without showing a crash dialog.
7293 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007295 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 }
7297
7298 Message msg = Message.obtain();
7299 msg.what = SHOW_ERROR_MSG;
7300 HashMap data = new HashMap();
7301 data.put("result", result);
7302 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 msg.obj = data;
7304 mHandler.sendMessage(msg);
7305
7306 Binder.restoreCallingIdentity(origId);
7307 }
7308
7309 int res = result.get();
7310
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007311 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 synchronized (this) {
7313 if (r != null) {
7314 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7315 SystemClock.uptimeMillis());
7316 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007317 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007318 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007319 }
7320 }
7321
7322 if (appErrorIntent != null) {
7323 try {
7324 mContext.startActivity(appErrorIntent);
7325 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007326 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007330
7331 Intent createAppErrorIntentLocked(ProcessRecord r,
7332 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7333 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007334 if (report == null) {
7335 return null;
7336 }
7337 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7338 result.setComponent(r.errorReportReceiver);
7339 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7340 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7341 return result;
7342 }
7343
Dan Egnorb7f03672009-12-09 16:22:32 -08007344 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7345 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007346 if (r.errorReportReceiver == null) {
7347 return null;
7348 }
7349
7350 if (!r.crashing && !r.notResponding) {
7351 return null;
7352 }
7353
Dan Egnorb7f03672009-12-09 16:22:32 -08007354 ApplicationErrorReport report = new ApplicationErrorReport();
7355 report.packageName = r.info.packageName;
7356 report.installerPackageName = r.errorReportReceiver.getPackageName();
7357 report.processName = r.processName;
7358 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007359 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007360
Dan Egnorb7f03672009-12-09 16:22:32 -08007361 if (r.crashing) {
7362 report.type = ApplicationErrorReport.TYPE_CRASH;
7363 report.crashInfo = crashInfo;
7364 } else if (r.notResponding) {
7365 report.type = ApplicationErrorReport.TYPE_ANR;
7366 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007367
Dan Egnorb7f03672009-12-09 16:22:32 -08007368 report.anrInfo.activity = r.notRespondingReport.tag;
7369 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7370 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007371 }
7372
Dan Egnorb7f03672009-12-09 16:22:32 -08007373 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007374 }
7375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7377 // assume our apps are happy - lazy create the list
7378 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7379
7380 synchronized (this) {
7381
7382 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007383 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7384 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007385 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7386 // This one's in trouble, so we'll generate a report for it
7387 // crashes are higher priority (in case there's a crash *and* an anr)
7388 ActivityManager.ProcessErrorStateInfo report = null;
7389 if (app.crashing) {
7390 report = app.crashingReport;
7391 } else if (app.notResponding) {
7392 report = app.notRespondingReport;
7393 }
7394
7395 if (report != null) {
7396 if (errList == null) {
7397 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7398 }
7399 errList.add(report);
7400 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007401 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 " crashing = " + app.crashing +
7403 " notResponding = " + app.notResponding);
7404 }
7405 }
7406 }
7407 }
7408
7409 return errList;
7410 }
7411
7412 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7413 // Lazy instantiation of list
7414 List<ActivityManager.RunningAppProcessInfo> runList = null;
7415 synchronized (this) {
7416 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007417 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7418 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7420 // Generate process state info for running application
7421 ActivityManager.RunningAppProcessInfo currApp =
7422 new ActivityManager.RunningAppProcessInfo(app.processName,
7423 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007424 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007425 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007426 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007427 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007428 if (app.persistent) {
7429 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007432 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7434 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7435 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007436 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7437 } else if (adj >= HOME_APP_ADJ) {
7438 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7439 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 } else if (adj >= SECONDARY_SERVER_ADJ) {
7441 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007442 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007443 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007444 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7445 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 } else if (adj >= VISIBLE_APP_ADJ) {
7447 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7448 } else {
7449 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7450 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007451 currApp.importanceReasonCode = app.adjTypeCode;
7452 if (app.adjSource instanceof ProcessRecord) {
7453 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007454 } else if (app.adjSource instanceof ActivityRecord) {
7455 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007456 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7457 }
7458 if (app.adjTarget instanceof ComponentName) {
7459 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7460 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007461 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 // + " lru=" + currApp.lru);
7463 if (runList == null) {
7464 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7465 }
7466 runList.add(currApp);
7467 }
7468 }
7469 }
7470 return runList;
7471 }
7472
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007473 public List<ApplicationInfo> getRunningExternalApplications() {
7474 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7475 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7476 if (runningApps != null && runningApps.size() > 0) {
7477 Set<String> extList = new HashSet<String>();
7478 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7479 if (app.pkgList != null) {
7480 for (String pkg : app.pkgList) {
7481 extList.add(pkg);
7482 }
7483 }
7484 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007485 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007486 for (String pkg : extList) {
7487 try {
7488 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7489 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7490 retList.add(info);
7491 }
7492 } catch (RemoteException e) {
7493 }
7494 }
7495 }
7496 return retList;
7497 }
7498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 @Override
7500 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007501 if (checkCallingPermission(android.Manifest.permission.DUMP)
7502 != PackageManager.PERMISSION_GRANTED) {
7503 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7504 + Binder.getCallingPid()
7505 + ", uid=" + Binder.getCallingUid()
7506 + " without permission "
7507 + android.Manifest.permission.DUMP);
7508 return;
7509 }
7510
7511 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007512 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007513
7514 int opti = 0;
7515 while (opti < args.length) {
7516 String opt = args[opti];
7517 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7518 break;
7519 }
7520 opti++;
7521 if ("-a".equals(opt)) {
7522 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007523 } else if ("-c".equals(opt)) {
7524 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007525 } else if ("-h".equals(opt)) {
7526 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007527 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007528 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007529 pw.println(" a[ctivities]: activity stack state");
7530 pw.println(" b[roadcasts]: broadcast state");
7531 pw.println(" i[ntents]: pending intent state");
7532 pw.println(" p[rocesses]: process state");
7533 pw.println(" o[om]: out of memory management");
7534 pw.println(" prov[iders]: content provider state");
7535 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007536 pw.println(" service [COMP_SPEC]: service client-side state");
7537 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7538 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7539 pw.println(" a partial substring in a component name, an");
7540 pw.println(" ActivityRecord hex object identifier, or");
7541 pw.println(" \"all\" for all objects");
7542 pw.println(" -a: include all available server state.");
7543 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007545 } else {
7546 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 }
7549
7550 // Is the caller requesting to dump a particular piece of data?
7551 if (opti < args.length) {
7552 String cmd = args[opti];
7553 opti++;
7554 if ("activities".equals(cmd) || "a".equals(cmd)) {
7555 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007556 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007558 return;
7559 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7560 synchronized (this) {
7561 dumpBroadcastsLocked(fd, pw, args, opti, true);
7562 }
7563 return;
7564 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7565 synchronized (this) {
7566 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7567 }
7568 return;
7569 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7570 synchronized (this) {
7571 dumpProcessesLocked(fd, pw, args, opti, true);
7572 }
7573 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007574 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7575 synchronized (this) {
7576 dumpOomLocked(fd, pw, args, opti, true);
7577 }
7578 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007579 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7580 synchronized (this) {
7581 dumpProvidersLocked(fd, pw, args, opti, true);
7582 }
7583 return;
7584 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007585 String[] newArgs;
7586 String name;
7587 if (opti >= args.length) {
7588 name = null;
7589 newArgs = EMPTY_STRING_ARRAY;
7590 } else {
7591 name = args[opti];
7592 opti++;
7593 newArgs = new String[args.length - opti];
7594 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7595 }
7596 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7597 pw.println("No services match: " + name);
7598 pw.println("Use -h for help.");
7599 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007600 return;
7601 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7602 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007603 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007604 }
7605 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007606 } else {
7607 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007608 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7609 pw.println("Bad activity command, or no activities match: " + cmd);
7610 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007611 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007612 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007614 }
7615
7616 // No piece of data specified, dump everything.
7617 synchronized (this) {
7618 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007619 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007620 if (needSep) {
7621 pw.println(" ");
7622 }
7623 if (dumpAll) {
7624 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007625 }
7626 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7627 if (needSep) {
7628 pw.println(" ");
7629 }
7630 if (dumpAll) {
7631 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007632 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007633 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007634 if (needSep) {
7635 pw.println(" ");
7636 }
7637 if (dumpAll) {
7638 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007639 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007640 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007641 if (needSep) {
7642 pw.println(" ");
7643 }
7644 if (dumpAll) {
7645 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007646 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007647 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007648 if (needSep) {
7649 pw.println(" ");
7650 }
7651 if (dumpAll) {
7652 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007653 }
7654 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7655 }
7656 }
7657
7658 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007659 int opti, boolean dumpAll, boolean dumpClient) {
7660 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7661 pw.println(" Main stack:");
7662 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007663 pw.println(" ");
7664 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007665 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007666 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007669 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7670 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007671 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007672 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007674 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007675 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7676 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007677 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007678 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7679 pw.println(" ");
7680 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007681 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7682 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007683 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007684 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007685 pw.println(" ");
7686 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007687 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7688 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007689 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007692 if (mMainStack.mPausingActivity != null) {
7693 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7694 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007695 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007696 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007697 if (dumpAll) {
7698 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7699 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007702 if (mRecentTasks.size() > 0) {
7703 pw.println();
7704 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007705
7706 final int N = mRecentTasks.size();
7707 for (int i=0; i<N; i++) {
7708 TaskRecord tr = mRecentTasks.get(i);
7709 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7710 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007711 if (dumpAll) {
7712 mRecentTasks.get(i).dump(pw, " ");
7713 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007714 }
7715 }
7716
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007717 if (dumpAll) {
7718 pw.println(" ");
7719 pw.println(" mCurTask: " + mCurTask);
7720 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007721
7722 return true;
7723 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007724
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007725 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7726 int opti, boolean dumpAll) {
7727 boolean needSep = false;
7728 int numPers = 0;
7729
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007730 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7731
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007732 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7734 final int NA = procs.size();
7735 for (int ia=0; ia<NA; ia++) {
7736 if (!needSep) {
7737 pw.println(" All known processes:");
7738 needSep = true;
7739 }
7740 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007741 pw.print(r.persistent ? " *PERS*" : " *APP*");
7742 pw.print(" UID "); pw.print(procs.keyAt(ia));
7743 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 r.dump(pw, " ");
7745 if (r.persistent) {
7746 numPers++;
7747 }
7748 }
7749 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 }
7751
7752 if (mLruProcesses.size() > 0) {
7753 if (needSep) pw.println(" ");
7754 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007755 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007756 dumpProcessOomList(pw, this, mLruProcesses, " ",
7757 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007758 needSep = true;
7759 }
7760
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007761 if (dumpAll) {
7762 synchronized (mPidsSelfLocked) {
7763 if (mPidsSelfLocked.size() > 0) {
7764 if (needSep) pw.println(" ");
7765 needSep = true;
7766 pw.println(" PID mappings:");
7767 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7768 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7769 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 }
7772 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007773 }
7774
7775 if (mForegroundProcesses.size() > 0) {
7776 if (needSep) pw.println(" ");
7777 needSep = true;
7778 pw.println(" Foreground Processes:");
7779 for (int i=0; i<mForegroundProcesses.size(); i++) {
7780 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7781 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007783 }
7784
7785 if (mPersistentStartingProcesses.size() > 0) {
7786 if (needSep) pw.println(" ");
7787 needSep = true;
7788 pw.println(" Persisent processes that are starting:");
7789 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007790 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007793 if (mStartingProcesses.size() > 0) {
7794 if (needSep) pw.println(" ");
7795 needSep = true;
7796 pw.println(" Processes that are starting:");
7797 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007798 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007801 if (mRemovedProcesses.size() > 0) {
7802 if (needSep) pw.println(" ");
7803 needSep = true;
7804 pw.println(" Processes that are being removed:");
7805 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007806 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007807 }
7808
7809 if (mProcessesOnHold.size() > 0) {
7810 if (needSep) pw.println(" ");
7811 needSep = true;
7812 pw.println(" Processes that are on old until the system is ready:");
7813 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007814 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816
Dianne Hackborn287952c2010-09-22 22:34:31 -07007817 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007818
7819 if (mProcessCrashTimes.getMap().size() > 0) {
7820 if (needSep) pw.println(" ");
7821 needSep = true;
7822 pw.println(" Time since processes crashed:");
7823 long now = SystemClock.uptimeMillis();
7824 for (Map.Entry<String, SparseArray<Long>> procs
7825 : mProcessCrashTimes.getMap().entrySet()) {
7826 SparseArray<Long> uids = procs.getValue();
7827 final int N = uids.size();
7828 for (int i=0; i<N; i++) {
7829 pw.print(" Process "); pw.print(procs.getKey());
7830 pw.print(" uid "); pw.print(uids.keyAt(i));
7831 pw.print(": last crashed ");
7832 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007833 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007834 }
7835 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007838 if (mBadProcesses.getMap().size() > 0) {
7839 if (needSep) pw.println(" ");
7840 needSep = true;
7841 pw.println(" Bad processes:");
7842 for (Map.Entry<String, SparseArray<Long>> procs
7843 : mBadProcesses.getMap().entrySet()) {
7844 SparseArray<Long> uids = procs.getValue();
7845 final int N = uids.size();
7846 for (int i=0; i<N; i++) {
7847 pw.print(" Bad process "); pw.print(procs.getKey());
7848 pw.print(" uid "); pw.print(uids.keyAt(i));
7849 pw.print(": crashed at time ");
7850 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 }
7852 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007855 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007856 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007857 if (mHeavyWeightProcess != null) {
7858 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7859 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007860 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007861 if (dumpAll) {
7862 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
7863 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007864 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7865 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7866 || mOrigWaitForDebugger) {
7867 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7868 + " mDebugTransient=" + mDebugTransient
7869 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7870 }
7871 if (mAlwaysFinishActivities || mController != null) {
7872 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7873 + " mController=" + mController);
7874 }
7875 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007878 + " mProcessesReady=" + mProcessesReady
7879 + " mSystemReady=" + mSystemReady);
7880 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 + " mBooted=" + mBooted
7882 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007883 pw.print(" mLastPowerCheckRealtime=");
7884 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7885 pw.println("");
7886 pw.print(" mLastPowerCheckUptime=");
7887 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7888 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007889 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7890 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007891 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007893
7894 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 }
7896
Dianne Hackborn287952c2010-09-22 22:34:31 -07007897 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7898 int opti, boolean needSep, boolean dumpAll) {
7899 if (mProcessesToGc.size() > 0) {
7900 if (needSep) pw.println(" ");
7901 needSep = true;
7902 pw.println(" Processes that are waiting to GC:");
7903 long now = SystemClock.uptimeMillis();
7904 for (int i=0; i<mProcessesToGc.size(); i++) {
7905 ProcessRecord proc = mProcessesToGc.get(i);
7906 pw.print(" Process "); pw.println(proc);
7907 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7908 pw.print(", last gced=");
7909 pw.print(now-proc.lastRequestedGc);
7910 pw.print(" ms ago, last lowMem=");
7911 pw.print(now-proc.lastLowMemory);
7912 pw.println(" ms ago");
7913
7914 }
7915 }
7916 return needSep;
7917 }
7918
7919 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7920 int opti, boolean dumpAll) {
7921 boolean needSep = false;
7922
7923 if (mLruProcesses.size() > 0) {
7924 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7925
7926 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7927 @Override
7928 public int compare(ProcessRecord object1, ProcessRecord object2) {
7929 if (object1.setAdj != object2.setAdj) {
7930 return object1.setAdj > object2.setAdj ? -1 : 1;
7931 }
7932 if (object1.setSchedGroup != object2.setSchedGroup) {
7933 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7934 }
7935 if (object1.keeping != object2.keeping) {
7936 return object1.keeping ? -1 : 1;
7937 }
7938 if (object1.pid != object2.pid) {
7939 return object1.pid > object2.pid ? -1 : 1;
7940 }
7941 return 0;
7942 }
7943 };
7944
7945 Collections.sort(procs, comparator);
7946
7947 if (needSep) pw.println(" ");
7948 needSep = true;
7949 pw.println(" Process OOM control:");
7950 dumpProcessOomList(pw, this, procs, " ",
7951 "Proc", "PERS", true);
7952 needSep = true;
7953 }
7954
7955 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7956
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007957 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07007958 pw.println(" mHomeProcess: " + mHomeProcess);
7959 if (mHeavyWeightProcess != null) {
7960 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7961 }
7962
7963 return true;
7964 }
7965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007966 /**
7967 * There are three ways to call this:
7968 * - no service specified: dump all the services
7969 * - a flattened component name that matched an existing service was specified as the
7970 * first arg: dump that one service
7971 * - the first arg isn't the flattened component name of an existing service:
7972 * dump all services whose component contains the first arg as a substring
7973 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007974 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7975 int opti, boolean dumpAll) {
7976 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007978 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007979 synchronized (this) {
7980 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007981 services.add(r1);
7982 }
7983 }
7984 } else {
7985 ComponentName componentName = name != null
7986 ? ComponentName.unflattenFromString(name) : null;
7987 int objectId = 0;
7988 if (componentName == null) {
7989 // Not a '/' separated full component name; maybe an object ID?
7990 try {
7991 objectId = Integer.parseInt(name, 16);
7992 name = null;
7993 componentName = null;
7994 } catch (RuntimeException e) {
7995 }
7996 }
7997
7998 synchronized (this) {
7999 for (ServiceRecord r1 : mServices.values()) {
8000 if (componentName != null) {
8001 if (r1.name.equals(componentName)) {
8002 services.add(r1);
8003 }
8004 } else if (name != null) {
8005 if (r1.name.flattenToString().contains(name)) {
8006 services.add(r1);
8007 }
8008 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008009 services.add(r1);
8010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 }
8012 }
8013 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008014
8015 if (services.size() <= 0) {
8016 return false;
8017 }
8018
8019 boolean needSep = false;
8020 for (int i=0; i<services.size(); i++) {
8021 if (needSep) {
8022 pw.println();
8023 }
8024 needSep = true;
8025 dumpService("", fd, pw, services.get(i), args, dumpAll);
8026 }
8027 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 }
8029
8030 /**
8031 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8032 * there is a thread associated with the service.
8033 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008034 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8035 final ServiceRecord r, String[] args, boolean dumpAll) {
8036 String innerPrefix = prefix + " ";
8037 synchronized (this) {
8038 pw.print(prefix); pw.print("SERVICE ");
8039 pw.print(r.shortName); pw.print(" ");
8040 pw.print(Integer.toHexString(System.identityHashCode(r)));
8041 pw.print(" pid=");
8042 if (r.app != null) pw.println(r.app.pid);
8043 else pw.println("(not running)");
8044 if (dumpAll) {
8045 r.dump(pw, innerPrefix);
8046 }
8047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008049 pw.print(prefix); pw.println(" Client:");
8050 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008051 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008052 TransferPipe tp = new TransferPipe();
8053 try {
8054 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8055 tp.setBufferPrefix(prefix + " ");
8056 tp.go(fd);
8057 } finally {
8058 tp.kill();
8059 }
8060 } catch (IOException e) {
8061 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008062 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008063 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 }
8065 }
8066 }
8067
Dianne Hackborn625ac272010-09-17 18:29:22 -07008068 /**
8069 * There are three things that cmd can be:
8070 * - a flattened component name that matched an existing activity
8071 * - the cmd arg isn't the flattened component name of an existing activity:
8072 * dump all activity whose component contains the cmd as a substring
8073 * - A hex number of the ActivityRecord object instance.
8074 */
8075 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8076 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008077 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008078
8079 if ("all".equals(name)) {
8080 synchronized (this) {
8081 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008082 activities.add(r1);
8083 }
8084 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008085 } else {
8086 ComponentName componentName = ComponentName.unflattenFromString(name);
8087 int objectId = 0;
8088 if (componentName == null) {
8089 // Not a '/' separated full component name; maybe an object ID?
8090 try {
8091 objectId = Integer.parseInt(name, 16);
8092 name = null;
8093 componentName = null;
8094 } catch (RuntimeException e) {
8095 }
8096 }
8097
8098 synchronized (this) {
8099 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8100 if (componentName != null) {
8101 if (r1.intent.getComponent().equals(componentName)) {
8102 activities.add(r1);
8103 }
8104 } else if (name != null) {
8105 if (r1.intent.getComponent().flattenToString().contains(name)) {
8106 activities.add(r1);
8107 }
8108 } else if (System.identityHashCode(r1) == objectId) {
8109 activities.add(r1);
8110 }
8111 }
8112 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008113 }
8114
8115 if (activities.size() <= 0) {
8116 return false;
8117 }
8118
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008119 String[] newArgs = new String[args.length - opti];
8120 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8121
Dianne Hackborn30d71892010-12-11 10:37:55 -08008122 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008123 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008124 for (int i=activities.size()-1; i>=0; i--) {
8125 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008126 if (needSep) {
8127 pw.println();
8128 }
8129 needSep = true;
8130 synchronized (this) {
8131 if (lastTask != r.task) {
8132 lastTask = r.task;
8133 pw.print("TASK "); pw.print(lastTask.affinity);
8134 pw.print(" id="); pw.println(lastTask.taskId);
8135 if (dumpAll) {
8136 lastTask.dump(pw, " ");
8137 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008138 }
8139 }
8140 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008141 }
8142 return true;
8143 }
8144
8145 /**
8146 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8147 * there is a thread associated with the activity.
8148 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008149 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008150 final ActivityRecord r, String[] args, boolean dumpAll) {
8151 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008152 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008153 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8154 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8155 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008156 if (r.app != null) pw.println(r.app.pid);
8157 else pw.println("(not running)");
8158 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008159 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008160 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008161 }
8162 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008163 // flush anything that is already in the PrintWriter since the thread is going
8164 // to write to the file descriptor directly
8165 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008166 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008167 TransferPipe tp = new TransferPipe();
8168 try {
8169 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8170 innerPrefix, args);
8171 tp.go(fd);
8172 } finally {
8173 tp.kill();
8174 }
8175 } catch (IOException e) {
8176 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008177 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008178 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008179 }
8180 }
8181 }
8182
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008183 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8184 int opti, boolean dumpAll) {
8185 boolean needSep = false;
8186
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008187 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008188 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 pw.println(" Registered Receivers:");
8191 Iterator it = mRegisteredReceivers.values().iterator();
8192 while (it.hasNext()) {
8193 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008194 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 r.dump(pw, " ");
8196 }
8197 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008198
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008199 pw.println();
8200 pw.println(" Receiver Resolver Table:");
8201 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008202 needSep = true;
8203 }
8204
8205 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8206 || mPendingBroadcast != null) {
8207 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008208 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008209 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008210 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008211 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8212 pw.println(" Broadcast #" + i + ":");
8213 mParallelBroadcasts.get(i).dump(pw, " ");
8214 }
8215 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008216 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008217 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008218 }
8219 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8220 pw.println(" Serialized Broadcast #" + i + ":");
8221 mOrderedBroadcasts.get(i).dump(pw, " ");
8222 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008223 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008224 pw.println(" Pending broadcast:");
8225 if (mPendingBroadcast != null) {
8226 mPendingBroadcast.dump(pw, " ");
8227 } else {
8228 pw.println(" (null)");
8229 }
8230 needSep = true;
8231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008232
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008233 if (needSep) {
8234 pw.println();
8235 }
8236 pw.println(" Historical broadcasts:");
8237 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8238 BroadcastRecord r = mBroadcastHistory[i];
8239 if (r == null) {
8240 break;
8241 }
8242 if (dumpAll) {
8243 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8244 r.dump(pw, " ");
8245 } else {
8246 if (i >= 50) {
8247 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008248 break;
8249 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008250 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008251 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008252 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008253 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008254
8255 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008256 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008257 pw.println(" Sticky broadcasts:");
8258 StringBuilder sb = new StringBuilder(128);
8259 for (Map.Entry<String, ArrayList<Intent>> ent
8260 : mStickyBroadcasts.entrySet()) {
8261 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008262 if (dumpAll) {
8263 pw.println(":");
8264 ArrayList<Intent> intents = ent.getValue();
8265 final int N = intents.size();
8266 for (int i=0; i<N; i++) {
8267 sb.setLength(0);
8268 sb.append(" Intent: ");
8269 intents.get(i).toShortString(sb, true, false);
8270 pw.println(sb.toString());
8271 Bundle bundle = intents.get(i).getExtras();
8272 if (bundle != null) {
8273 pw.print(" ");
8274 pw.println(bundle.toString());
8275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008276 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008277 } else {
8278 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 }
8280 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008281 needSep = true;
8282 }
8283
8284 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008285 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008286 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 pw.println(" mHandler:");
8288 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008289 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008290 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008291
8292 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 }
8294
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008295 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008296 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008297 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008299 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8300 if (mServices.size() > 0) {
8301 pw.println(" Active services:");
8302 long nowReal = SystemClock.elapsedRealtime();
8303 Iterator<ServiceRecord> it = mServices.values().iterator();
8304 needSep = false;
8305 while (it.hasNext()) {
8306 ServiceRecord r = it.next();
8307 if (needSep) {
8308 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008310 pw.print(" * "); pw.println(r);
8311 if (dumpAll) {
8312 r.dump(pw, " ");
8313 needSep = true;
8314 } else {
8315 pw.print(" app="); pw.println(r.app);
8316 pw.print(" created=");
8317 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8318 pw.print(" started="); pw.print(r.startRequested);
8319 pw.print(" connections="); pw.println(r.connections.size());
8320 }
8321 if (dumpClient && r.app != null && r.app.thread != null) {
8322 pw.println(" Client:");
8323 pw.flush();
8324 try {
8325 TransferPipe tp = new TransferPipe();
8326 try {
8327 r.app.thread.dumpService(
8328 tp.getWriteFd().getFileDescriptor(), r, args);
8329 tp.setBufferPrefix(" ");
8330 // Short timeout, since blocking here can
8331 // deadlock with the application.
8332 tp.go(fd, 2000);
8333 } finally {
8334 tp.kill();
8335 }
8336 } catch (IOException e) {
8337 pw.println(" Failure while dumping the service: " + e);
8338 } catch (RemoteException e) {
8339 pw.println(" Got a RemoteException while dumping the service");
8340 }
8341 needSep = true;
8342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008344 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008347 if (mPendingServices.size() > 0) {
8348 if (needSep) pw.println(" ");
8349 pw.println(" Pending services:");
8350 for (int i=0; i<mPendingServices.size(); i++) {
8351 ServiceRecord r = mPendingServices.get(i);
8352 pw.print(" * Pending "); pw.println(r);
8353 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008354 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008355 needSep = true;
8356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008358 if (mRestartingServices.size() > 0) {
8359 if (needSep) pw.println(" ");
8360 pw.println(" Restarting services:");
8361 for (int i=0; i<mRestartingServices.size(); i++) {
8362 ServiceRecord r = mRestartingServices.get(i);
8363 pw.print(" * Restarting "); pw.println(r);
8364 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008366 needSep = true;
8367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008369 if (mStoppingServices.size() > 0) {
8370 if (needSep) pw.println(" ");
8371 pw.println(" Stopping services:");
8372 for (int i=0; i<mStoppingServices.size(); i++) {
8373 ServiceRecord r = mStoppingServices.get(i);
8374 pw.print(" * Stopping "); pw.println(r);
8375 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008377 needSep = true;
8378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008380 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008381 if (mServiceConnections.size() > 0) {
8382 if (needSep) pw.println(" ");
8383 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008384 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 = mServiceConnections.values().iterator();
8386 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008387 ArrayList<ConnectionRecord> r = it.next();
8388 for (int i=0; i<r.size(); i++) {
8389 pw.print(" * "); pw.println(r.get(i));
8390 r.get(i).dump(pw, " ");
8391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008392 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008393 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 }
8395 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008396
8397 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 }
8399
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008400 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8401 int opti, boolean dumpAll) {
8402 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008403
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008404 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8405 if (mProvidersByClass.size() > 0) {
8406 if (needSep) pw.println(" ");
8407 pw.println(" Published content providers (by class):");
8408 Iterator<Map.Entry<String, ContentProviderRecord>> it
8409 = mProvidersByClass.entrySet().iterator();
8410 while (it.hasNext()) {
8411 Map.Entry<String, ContentProviderRecord> e = it.next();
8412 ContentProviderRecord r = e.getValue();
8413 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008414 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008416 } else {
8417 pw.print(" * "); pw.print(r.name.toShortString());
8418 if (r.app != null) {
8419 pw.println(":");
8420 pw.print(" "); pw.println(r.app);
8421 } else {
8422 pw.println();
8423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008426 needSep = true;
8427 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008428
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008429 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008430 if (mProvidersByName.size() > 0) {
8431 pw.println(" ");
8432 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008433 Iterator<Map.Entry<String, ContentProviderRecord>> it
8434 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008435 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008436 Map.Entry<String, ContentProviderRecord> e = it.next();
8437 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008438 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8439 pw.println(r);
8440 }
8441 needSep = true;
8442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008444
8445 if (mLaunchingProviders.size() > 0) {
8446 if (needSep) pw.println(" ");
8447 pw.println(" Launching content providers:");
8448 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8449 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8450 pw.println(mLaunchingProviders.get(i));
8451 }
8452 needSep = true;
8453 }
8454
8455 if (mGrantedUriPermissions.size() > 0) {
8456 pw.println();
8457 pw.println("Granted Uri Permissions:");
8458 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8459 int uid = mGrantedUriPermissions.keyAt(i);
8460 HashMap<Uri, UriPermission> perms
8461 = mGrantedUriPermissions.valueAt(i);
8462 pw.print(" * UID "); pw.print(uid);
8463 pw.println(" holds:");
8464 for (UriPermission perm : perms.values()) {
8465 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008466 if (dumpAll) {
8467 perm.dump(pw, " ");
8468 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008469 }
8470 }
8471 needSep = true;
8472 }
8473
8474 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 }
8476
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008477 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8478 int opti, boolean dumpAll) {
8479 boolean needSep = false;
8480
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008481 if (this.mIntentSenderRecords.size() > 0) {
8482 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8483 Iterator<WeakReference<PendingIntentRecord>> it
8484 = mIntentSenderRecords.values().iterator();
8485 while (it.hasNext()) {
8486 WeakReference<PendingIntentRecord> ref = it.next();
8487 PendingIntentRecord rec = ref != null ? ref.get(): null;
8488 needSep = true;
8489 if (rec != null) {
8490 pw.print(" * "); pw.println(rec);
8491 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008494 } else {
8495 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 }
8497 }
8498 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008499
8500 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008501 }
8502
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008503 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8504 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008506 boolean needNL = false;
8507 final String innerPrefix = prefix + " ";
8508 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008510 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008511 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008512 if (needNL) {
8513 pw.println(" ");
8514 needNL = false;
8515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 if (lastTask != r.task) {
8517 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008518 pw.print(prefix);
8519 pw.print(full ? "* " : " ");
8520 pw.println(lastTask);
8521 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008522 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008523 } else if (complete) {
8524 // Complete + brief == give a summary. Isn't that obvious?!?
8525 if (lastTask.intent != null) {
8526 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8527 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008529 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008530 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8531 pw.print(" #"); pw.print(i); pw.print(": ");
8532 pw.println(r);
8533 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008534 r.dump(pw, innerPrefix);
8535 } else if (complete) {
8536 // Complete + brief == give a summary. Isn't that obvious?!?
8537 pw.print(innerPrefix); pw.println(r.intent);
8538 if (r.app != null) {
8539 pw.print(innerPrefix); pw.println(r.app);
8540 }
8541 }
8542 if (client && r.app != null && r.app.thread != null) {
8543 // flush anything that is already in the PrintWriter since the thread is going
8544 // to write to the file descriptor directly
8545 pw.flush();
8546 try {
8547 TransferPipe tp = new TransferPipe();
8548 try {
8549 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8550 innerPrefix, args);
8551 // Short timeout, since blocking here can
8552 // deadlock with the application.
8553 tp.go(fd, 2000);
8554 } finally {
8555 tp.kill();
8556 }
8557 } catch (IOException e) {
8558 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8559 } catch (RemoteException e) {
8560 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8561 }
8562 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 }
8565 }
8566
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008567 private static String buildOomTag(String prefix, String space, int val, int base) {
8568 if (val == base) {
8569 if (space == null) return prefix;
8570 return prefix + " ";
8571 }
8572 return prefix + "+" + Integer.toString(val-base);
8573 }
8574
8575 private static final int dumpProcessList(PrintWriter pw,
8576 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008577 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008578 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008579 final int N = list.size()-1;
8580 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008581 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008582 pw.println(String.format("%s%s #%2d: %s",
8583 prefix, (r.persistent ? persistentLabel : normalLabel),
8584 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 if (r.persistent) {
8586 numPers++;
8587 }
8588 }
8589 return numPers;
8590 }
8591
Dianne Hackborn287952c2010-09-22 22:34:31 -07008592 private static final void dumpProcessOomList(PrintWriter pw,
8593 ActivityManagerService service, List<ProcessRecord> list,
8594 String prefix, String normalLabel, String persistentLabel,
8595 boolean inclDetails) {
8596
8597 final long curRealtime = SystemClock.elapsedRealtime();
8598 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8599 final long curUptime = SystemClock.uptimeMillis();
8600 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8601
8602 final int N = list.size()-1;
8603 for (int i=N; i>=0; i--) {
8604 ProcessRecord r = list.get(i);
8605 String oomAdj;
8606 if (r.setAdj >= EMPTY_APP_ADJ) {
8607 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8608 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8609 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8610 } else if (r.setAdj >= HOME_APP_ADJ) {
8611 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8612 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8613 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8614 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8615 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8616 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8617 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8618 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8619 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8620 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8621 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8622 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8623 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8624 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8625 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8626 } else if (r.setAdj >= SYSTEM_ADJ) {
8627 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8628 } else {
8629 oomAdj = Integer.toString(r.setAdj);
8630 }
8631 String schedGroup;
8632 switch (r.setSchedGroup) {
8633 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8634 schedGroup = "B";
8635 break;
8636 case Process.THREAD_GROUP_DEFAULT:
8637 schedGroup = "F";
8638 break;
8639 default:
8640 schedGroup = Integer.toString(r.setSchedGroup);
8641 break;
8642 }
8643 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8644 prefix, (r.persistent ? persistentLabel : normalLabel),
8645 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8646 if (r.adjSource != null || r.adjTarget != null) {
8647 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008648 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008649 if (r.adjTarget instanceof ComponentName) {
8650 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8651 } else if (r.adjTarget != null) {
8652 pw.print(r.adjTarget.toString());
8653 } else {
8654 pw.print("{null}");
8655 }
8656 pw.print("<=");
8657 if (r.adjSource instanceof ProcessRecord) {
8658 pw.print("Proc{");
8659 pw.print(((ProcessRecord)r.adjSource).toShortString());
8660 pw.println("}");
8661 } else if (r.adjSource != null) {
8662 pw.println(r.adjSource.toString());
8663 } else {
8664 pw.println("{null}");
8665 }
8666 }
8667 if (inclDetails) {
8668 pw.print(prefix);
8669 pw.print(" ");
8670 pw.print("oom: max="); pw.print(r.maxAdj);
8671 pw.print(" hidden="); pw.print(r.hiddenAdj);
8672 pw.print(" curRaw="); pw.print(r.curRawAdj);
8673 pw.print(" setRaw="); pw.print(r.setRawAdj);
8674 pw.print(" cur="); pw.print(r.curAdj);
8675 pw.print(" set="); pw.println(r.setAdj);
8676 pw.print(prefix);
8677 pw.print(" ");
8678 pw.print("keeping="); pw.print(r.keeping);
8679 pw.print(" hidden="); pw.print(r.hidden);
8680 pw.print(" empty="); pw.println(r.empty);
8681
8682 if (!r.keeping) {
8683 if (r.lastWakeTime != 0) {
8684 long wtime;
8685 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8686 synchronized (stats) {
8687 wtime = stats.getProcessWakeTime(r.info.uid,
8688 r.pid, curRealtime);
8689 }
8690 long timeUsed = wtime - r.lastWakeTime;
8691 pw.print(prefix);
8692 pw.print(" ");
8693 pw.print("keep awake over ");
8694 TimeUtils.formatDuration(realtimeSince, pw);
8695 pw.print(" used ");
8696 TimeUtils.formatDuration(timeUsed, pw);
8697 pw.print(" (");
8698 pw.print((timeUsed*100)/realtimeSince);
8699 pw.println("%)");
8700 }
8701 if (r.lastCpuTime != 0) {
8702 long timeUsed = r.curCpuTime - r.lastCpuTime;
8703 pw.print(prefix);
8704 pw.print(" ");
8705 pw.print("run cpu over ");
8706 TimeUtils.formatDuration(uptimeSince, pw);
8707 pw.print(" used ");
8708 TimeUtils.formatDuration(timeUsed, pw);
8709 pw.print(" (");
8710 pw.print((timeUsed*100)/uptimeSince);
8711 pw.println("%)");
8712 }
8713 }
8714 }
8715 }
8716 }
8717
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008718 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8719 ArrayList<ProcessRecord> procs;
8720 synchronized (this) {
8721 if (args != null && args.length > 0
8722 && args[0].charAt(0) != '-') {
8723 procs = new ArrayList<ProcessRecord>();
8724 int pid = -1;
8725 try {
8726 pid = Integer.parseInt(args[0]);
8727 } catch (NumberFormatException e) {
8728
8729 }
8730 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8731 ProcessRecord proc = mLruProcesses.get(i);
8732 if (proc.pid == pid) {
8733 procs.add(proc);
8734 } else if (proc.processName.equals(args[0])) {
8735 procs.add(proc);
8736 }
8737 }
8738 if (procs.size() <= 0) {
8739 pw.println("No process found for: " + args[0]);
8740 return null;
8741 }
8742 } else {
8743 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8744 }
8745 }
8746 return procs;
8747 }
8748
8749 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8750 PrintWriter pw, String[] args) {
8751 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8752 if (procs == null) {
8753 return;
8754 }
8755
8756 long uptime = SystemClock.uptimeMillis();
8757 long realtime = SystemClock.elapsedRealtime();
8758 pw.println("Applications Graphics Acceleration Info:");
8759 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8760
8761 String callArgs[] = {"graphics"};
8762 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8763 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008764 if (r.thread != null) {
8765 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8766 pw.flush();
8767 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008768 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8769 } catch (IOException e) {
8770 pw.println("Failure: " + e);
8771 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008772 } catch (RemoteException e) {
8773 pw.println("Got RemoteException!");
8774 pw.flush();
8775 }
8776 }
8777 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008778 }
8779
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008780 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8781 PrintWriter pw, String prefix, String[] args) {
8782 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8783 if (procs == null) {
8784 return;
8785 }
8786
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008787 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 long uptime = SystemClock.uptimeMillis();
8789 long realtime = SystemClock.elapsedRealtime();
8790
8791 if (isCheckinRequest) {
8792 // short checkin version
8793 pw.println(uptime + "," + realtime);
8794 pw.flush();
8795 } else {
8796 pw.println("Applications Memory Usage (kB):");
8797 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8798 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008799 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8800 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 if (r.thread != null) {
8802 if (!isCheckinRequest) {
8803 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8804 pw.flush();
8805 }
8806 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008807 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8808 } catch (IOException e) {
8809 pw.println("Failure: " + e);
8810 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 } catch (RemoteException e) {
8812 if (!isCheckinRequest) {
8813 pw.println("Got RemoteException!");
8814 pw.flush();
8815 }
8816 }
8817 }
8818 }
8819 }
8820
8821 /**
8822 * Searches array of arguments for the specified string
8823 * @param args array of argument strings
8824 * @param value value to search for
8825 * @return true if the value is contained in the array
8826 */
8827 private static boolean scanArgs(String[] args, String value) {
8828 if (args != null) {
8829 for (String arg : args) {
8830 if (value.equals(arg)) {
8831 return true;
8832 }
8833 }
8834 }
8835 return false;
8836 }
8837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 private final void killServicesLocked(ProcessRecord app,
8839 boolean allowRestart) {
8840 // Report disconnected services.
8841 if (false) {
8842 // XXX we are letting the client link to the service for
8843 // death notifications.
8844 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008845 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008847 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008849 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008850 = r.connections.values().iterator();
8851 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008852 ArrayList<ConnectionRecord> cl = jt.next();
8853 for (int i=0; i<cl.size(); i++) {
8854 ConnectionRecord c = cl.get(i);
8855 if (c.binding.client != app) {
8856 try {
8857 //c.conn.connected(r.className, null);
8858 } catch (Exception e) {
8859 // todo: this should be asynchronous!
8860 Slog.w(TAG, "Exception thrown disconnected servce "
8861 + r.shortName
8862 + " from app " + app.processName, e);
8863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 }
8865 }
8866 }
8867 }
8868 }
8869 }
8870 }
8871
8872 // Clean up any connections this application has to other services.
8873 if (app.connections.size() > 0) {
8874 Iterator<ConnectionRecord> it = app.connections.iterator();
8875 while (it.hasNext()) {
8876 ConnectionRecord r = it.next();
8877 removeConnectionLocked(r, app, null);
8878 }
8879 }
8880 app.connections.clear();
8881
8882 if (app.services.size() != 0) {
8883 // Any services running in the application need to be placed
8884 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008885 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008887 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008888 synchronized (sr.stats.getBatteryStats()) {
8889 sr.stats.stopLaunchedLocked();
8890 }
8891 sr.app = null;
8892 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008893 if (mStoppingServices.remove(sr)) {
8894 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8895 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008896
8897 boolean hasClients = sr.bindings.size() > 0;
8898 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008899 Iterator<IntentBindRecord> bindings
8900 = sr.bindings.values().iterator();
8901 while (bindings.hasNext()) {
8902 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008903 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 + ": shouldUnbind=" + b.hasBound);
8905 b.binder = null;
8906 b.requested = b.received = b.hasBound = false;
8907 }
8908 }
8909
Dianne Hackborn070783f2010-12-29 16:46:28 -08008910 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8911 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008912 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008913 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008914 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008915 sr.crashCount, sr.shortName, app.pid);
8916 bringDownServiceLocked(sr, true);
8917 } else if (!allowRestart) {
8918 bringDownServiceLocked(sr, true);
8919 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008920 boolean canceled = scheduleServiceRestartLocked(sr, true);
8921
8922 // Should the service remain running? Note that in the
8923 // extreme case of so many attempts to deliver a command
8924 // that it failed, that we also will stop it here.
8925 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8926 if (sr.pendingStarts.size() == 0) {
8927 sr.startRequested = false;
8928 if (!hasClients) {
8929 // Whoops, no reason to restart!
8930 bringDownServiceLocked(sr, true);
8931 }
8932 }
8933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 }
8935 }
8936
8937 if (!allowRestart) {
8938 app.services.clear();
8939 }
8940 }
8941
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008942 // Make sure we have no more records on the stopping list.
8943 int i = mStoppingServices.size();
8944 while (i > 0) {
8945 i--;
8946 ServiceRecord sr = mStoppingServices.get(i);
8947 if (sr.app == app) {
8948 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008949 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008950 }
8951 }
8952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008953 app.executingServices.clear();
8954 }
8955
8956 private final void removeDyingProviderLocked(ProcessRecord proc,
8957 ContentProviderRecord cpr) {
8958 synchronized (cpr) {
8959 cpr.launchingApp = null;
8960 cpr.notifyAll();
8961 }
8962
8963 mProvidersByClass.remove(cpr.info.name);
8964 String names[] = cpr.info.authority.split(";");
8965 for (int j = 0; j < names.length; j++) {
8966 mProvidersByName.remove(names[j]);
8967 }
8968
8969 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8970 while (cit.hasNext()) {
8971 ProcessRecord capp = cit.next();
8972 if (!capp.persistent && capp.thread != null
8973 && capp.pid != 0
8974 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008975 Slog.i(TAG, "Kill " + capp.processName
8976 + " (pid " + capp.pid + "): provider " + cpr.info.name
8977 + " in dying process " + proc.processName);
8978 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8979 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07008980 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008981 }
8982 }
8983
8984 mLaunchingProviders.remove(cpr);
8985 }
8986
8987 /**
8988 * Main code for cleaning up a process when it has gone away. This is
8989 * called both as a result of the process dying, or directly when stopping
8990 * a process when running in single process mode.
8991 */
8992 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8993 boolean restarting, int index) {
8994 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008995 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 }
8997
Dianne Hackborn36124872009-10-08 16:22:03 -07008998 mProcessesToGc.remove(app);
8999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 // Dismiss any open dialogs.
9001 if (app.crashDialog != null) {
9002 app.crashDialog.dismiss();
9003 app.crashDialog = null;
9004 }
9005 if (app.anrDialog != null) {
9006 app.anrDialog.dismiss();
9007 app.anrDialog = null;
9008 }
9009 if (app.waitDialog != null) {
9010 app.waitDialog.dismiss();
9011 app.waitDialog = null;
9012 }
9013
9014 app.crashing = false;
9015 app.notResponding = false;
9016
9017 app.resetPackageList();
9018 app.thread = null;
9019 app.forcingToForeground = null;
9020 app.foregroundServices = false;
9021
9022 killServicesLocked(app, true);
9023
9024 boolean restart = false;
9025
9026 int NL = mLaunchingProviders.size();
9027
9028 // Remove published content providers.
9029 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009030 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009032 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 cpr.provider = null;
9034 cpr.app = null;
9035
9036 // See if someone is waiting for this provider... in which
9037 // case we don't remove it, but just let it restart.
9038 int i = 0;
9039 if (!app.bad) {
9040 for (; i<NL; i++) {
9041 if (mLaunchingProviders.get(i) == cpr) {
9042 restart = true;
9043 break;
9044 }
9045 }
9046 } else {
9047 i = NL;
9048 }
9049
9050 if (i >= NL) {
9051 removeDyingProviderLocked(app, cpr);
9052 NL = mLaunchingProviders.size();
9053 }
9054 }
9055 app.pubProviders.clear();
9056 }
9057
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009058 // Take care of any launching providers waiting for this process.
9059 if (checkAppInLaunchingProvidersLocked(app, false)) {
9060 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 // Unregister from connected content providers.
9064 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009065 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 while (it.hasNext()) {
9067 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9068 cpr.clients.remove(app);
9069 }
9070 app.conProviders.clear();
9071 }
9072
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009073 // At this point there may be remaining entries in mLaunchingProviders
9074 // where we were the only one waiting, so they are no longer of use.
9075 // Look for these and clean up if found.
9076 // XXX Commented out for now. Trying to figure out a way to reproduce
9077 // the actual situation to identify what is actually going on.
9078 if (false) {
9079 for (int i=0; i<NL; i++) {
9080 ContentProviderRecord cpr = (ContentProviderRecord)
9081 mLaunchingProviders.get(i);
9082 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9083 synchronized (cpr) {
9084 cpr.launchingApp = null;
9085 cpr.notifyAll();
9086 }
9087 }
9088 }
9089 }
9090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 skipCurrentReceiverLocked(app);
9092
9093 // Unregister any receivers.
9094 if (app.receivers.size() > 0) {
9095 Iterator<ReceiverList> it = app.receivers.iterator();
9096 while (it.hasNext()) {
9097 removeReceiverLocked(it.next());
9098 }
9099 app.receivers.clear();
9100 }
9101
Christopher Tate181fafa2009-05-14 11:12:14 -07009102 // If the app is undergoing backup, tell the backup manager about it
9103 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009104 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009105 try {
9106 IBackupManager bm = IBackupManager.Stub.asInterface(
9107 ServiceManager.getService(Context.BACKUP_SERVICE));
9108 bm.agentDisconnected(app.info.packageName);
9109 } catch (RemoteException e) {
9110 // can't happen; backup manager is local
9111 }
9112 }
9113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 // If the caller is restarting this app, then leave it in its
9115 // current lists and let the caller take care of it.
9116 if (restarting) {
9117 return;
9118 }
9119
9120 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009121 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122 "Removing non-persistent process during cleanup: " + app);
9123 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009124 if (mHeavyWeightProcess == app) {
9125 mHeavyWeightProcess = null;
9126 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009128 } else if (!app.removed) {
9129 // This app is persistent, so we need to keep its record around.
9130 // If it is not already on the pending app list, add it there
9131 // and start a new process for it.
9132 app.thread = null;
9133 app.forcingToForeground = null;
9134 app.foregroundServices = false;
9135 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9136 mPersistentStartingProcesses.add(app);
9137 restart = true;
9138 }
9139 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009140 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9141 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009142 mProcessesOnHold.remove(app);
9143
The Android Open Source Project4df24232009-03-05 14:34:35 -08009144 if (app == mHomeProcess) {
9145 mHomeProcess = null;
9146 }
9147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 if (restart) {
9149 // We have components that still need to be running in the
9150 // process, so re-launch it.
9151 mProcessNames.put(app.processName, app.info.uid, app);
9152 startProcessLocked(app, "restart", app.processName);
9153 } else if (app.pid > 0 && app.pid != MY_PID) {
9154 // Goodbye!
9155 synchronized (mPidsSelfLocked) {
9156 mPidsSelfLocked.remove(app.pid);
9157 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9158 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009159 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 }
9161 }
9162
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009163 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9164 // Look through the content providers we are waiting to have launched,
9165 // and if any run in this process then either schedule a restart of
9166 // the process or kill the client waiting for it if this process has
9167 // gone bad.
9168 int NL = mLaunchingProviders.size();
9169 boolean restart = false;
9170 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009171 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009172 if (cpr.launchingApp == app) {
9173 if (!alwaysBad && !app.bad) {
9174 restart = true;
9175 } else {
9176 removeDyingProviderLocked(app, cpr);
9177 NL = mLaunchingProviders.size();
9178 }
9179 }
9180 }
9181 return restart;
9182 }
9183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009184 // =========================================================
9185 // SERVICES
9186 // =========================================================
9187
9188 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9189 ActivityManager.RunningServiceInfo info =
9190 new ActivityManager.RunningServiceInfo();
9191 info.service = r.name;
9192 if (r.app != null) {
9193 info.pid = r.app.pid;
9194 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009195 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 info.process = r.processName;
9197 info.foreground = r.isForeground;
9198 info.activeSince = r.createTime;
9199 info.started = r.startRequested;
9200 info.clientCount = r.connections.size();
9201 info.crashCount = r.crashCount;
9202 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009203 if (r.isForeground) {
9204 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9205 }
9206 if (r.startRequested) {
9207 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9208 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009209 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009210 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9211 }
9212 if (r.app != null && r.app.persistent) {
9213 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9214 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009215
9216 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9217 for (int i=0; i<connl.size(); i++) {
9218 ConnectionRecord conn = connl.get(i);
9219 if (conn.clientLabel != 0) {
9220 info.clientPackage = conn.binding.client.info.packageName;
9221 info.clientLabel = conn.clientLabel;
9222 return info;
9223 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009224 }
9225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 return info;
9227 }
9228
9229 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9230 int flags) {
9231 synchronized (this) {
9232 ArrayList<ActivityManager.RunningServiceInfo> res
9233 = new ArrayList<ActivityManager.RunningServiceInfo>();
9234
9235 if (mServices.size() > 0) {
9236 Iterator<ServiceRecord> it = mServices.values().iterator();
9237 while (it.hasNext() && res.size() < maxNum) {
9238 res.add(makeRunningServiceInfoLocked(it.next()));
9239 }
9240 }
9241
9242 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9243 ServiceRecord r = mRestartingServices.get(i);
9244 ActivityManager.RunningServiceInfo info =
9245 makeRunningServiceInfoLocked(r);
9246 info.restarting = r.nextRestartTime;
9247 res.add(info);
9248 }
9249
9250 return res;
9251 }
9252 }
9253
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009254 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9255 synchronized (this) {
9256 ServiceRecord r = mServices.get(name);
9257 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009258 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9259 for (int i=0; i<conn.size(); i++) {
9260 if (conn.get(i).clientIntent != null) {
9261 return conn.get(i).clientIntent;
9262 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009263 }
9264 }
9265 }
9266 }
9267 return null;
9268 }
9269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009270 private final ServiceRecord findServiceLocked(ComponentName name,
9271 IBinder token) {
9272 ServiceRecord r = mServices.get(name);
9273 return r == token ? r : null;
9274 }
9275
9276 private final class ServiceLookupResult {
9277 final ServiceRecord record;
9278 final String permission;
9279
9280 ServiceLookupResult(ServiceRecord _record, String _permission) {
9281 record = _record;
9282 permission = _permission;
9283 }
9284 };
9285
9286 private ServiceLookupResult findServiceLocked(Intent service,
9287 String resolvedType) {
9288 ServiceRecord r = null;
9289 if (service.getComponent() != null) {
9290 r = mServices.get(service.getComponent());
9291 }
9292 if (r == null) {
9293 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9294 r = mServicesByIntent.get(filter);
9295 }
9296
9297 if (r == null) {
9298 try {
9299 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009300 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009301 service, resolvedType, 0);
9302 ServiceInfo sInfo =
9303 rInfo != null ? rInfo.serviceInfo : null;
9304 if (sInfo == null) {
9305 return null;
9306 }
9307
9308 ComponentName name = new ComponentName(
9309 sInfo.applicationInfo.packageName, sInfo.name);
9310 r = mServices.get(name);
9311 } catch (RemoteException ex) {
9312 // pm is in same process, this will never happen.
9313 }
9314 }
9315 if (r != null) {
9316 int callingPid = Binder.getCallingPid();
9317 int callingUid = Binder.getCallingUid();
9318 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009319 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009321 if (!r.exported) {
9322 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9323 + " from pid=" + callingPid
9324 + ", uid=" + callingUid
9325 + " that is not exported from uid " + r.appInfo.uid);
9326 return new ServiceLookupResult(null, "not exported from uid "
9327 + r.appInfo.uid);
9328 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009329 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 + " from pid=" + callingPid
9331 + ", uid=" + callingUid
9332 + " requires " + r.permission);
9333 return new ServiceLookupResult(null, r.permission);
9334 }
9335 return new ServiceLookupResult(r, null);
9336 }
9337 return null;
9338 }
9339
9340 private class ServiceRestarter implements Runnable {
9341 private ServiceRecord mService;
9342
9343 void setService(ServiceRecord service) {
9344 mService = service;
9345 }
9346
9347 public void run() {
9348 synchronized(ActivityManagerService.this) {
9349 performServiceRestartLocked(mService);
9350 }
9351 }
9352 }
9353
9354 private ServiceLookupResult retrieveServiceLocked(Intent service,
9355 String resolvedType, int callingPid, int callingUid) {
9356 ServiceRecord r = null;
9357 if (service.getComponent() != null) {
9358 r = mServices.get(service.getComponent());
9359 }
9360 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9361 r = mServicesByIntent.get(filter);
9362 if (r == null) {
9363 try {
9364 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009365 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009366 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009367 ServiceInfo sInfo =
9368 rInfo != null ? rInfo.serviceInfo : null;
9369 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009370 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 ": not found");
9372 return null;
9373 }
9374
9375 ComponentName name = new ComponentName(
9376 sInfo.applicationInfo.packageName, sInfo.name);
9377 r = mServices.get(name);
9378 if (r == null) {
9379 filter = new Intent.FilterComparison(service.cloneFilter());
9380 ServiceRestarter res = new ServiceRestarter();
9381 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9382 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9383 synchronized (stats) {
9384 ss = stats.getServiceStatsLocked(
9385 sInfo.applicationInfo.uid, sInfo.packageName,
9386 sInfo.name);
9387 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009388 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 res.setService(r);
9390 mServices.put(name, r);
9391 mServicesByIntent.put(filter, r);
9392
9393 // Make sure this component isn't in the pending list.
9394 int N = mPendingServices.size();
9395 for (int i=0; i<N; i++) {
9396 ServiceRecord pr = mPendingServices.get(i);
9397 if (pr.name.equals(name)) {
9398 mPendingServices.remove(i);
9399 i--;
9400 N--;
9401 }
9402 }
9403 }
9404 } catch (RemoteException ex) {
9405 // pm is in same process, this will never happen.
9406 }
9407 }
9408 if (r != null) {
9409 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009410 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009412 if (!r.exported) {
9413 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9414 + " from pid=" + callingPid
9415 + ", uid=" + callingUid
9416 + " that is not exported from uid " + r.appInfo.uid);
9417 return new ServiceLookupResult(null, "not exported from uid "
9418 + r.appInfo.uid);
9419 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009420 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009421 + " from pid=" + callingPid
9422 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009423 + " requires " + r.permission);
9424 return new ServiceLookupResult(null, r.permission);
9425 }
9426 return new ServiceLookupResult(r, null);
9427 }
9428 return null;
9429 }
9430
Dianne Hackborn287952c2010-09-22 22:34:31 -07009431 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9432 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9433 + why + " of " + r + " in app " + r.app);
9434 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9435 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 long now = SystemClock.uptimeMillis();
9437 if (r.executeNesting == 0 && r.app != null) {
9438 if (r.app.executingServices.size() == 0) {
9439 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9440 msg.obj = r.app;
9441 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9442 }
9443 r.app.executingServices.add(r);
9444 }
9445 r.executeNesting++;
9446 r.executingStart = now;
9447 }
9448
9449 private final void sendServiceArgsLocked(ServiceRecord r,
9450 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009451 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 if (N == 0) {
9453 return;
9454 }
9455
Dianne Hackborn39792d22010-08-19 18:01:52 -07009456 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009457 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009458 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009459 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9460 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009461 if (si.intent == null && N > 1) {
9462 // If somehow we got a dummy null intent in the middle,
9463 // then skip it. DO NOT skip a null intent when it is
9464 // the only one in the list -- this is to support the
9465 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009466 continue;
9467 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009468 si.deliveredTime = SystemClock.uptimeMillis();
9469 r.deliveredStarts.add(si);
9470 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009471 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009472 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009473 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009474 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009475 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 if (!oomAdjusted) {
9477 oomAdjusted = true;
9478 updateOomAdjLocked(r.app);
9479 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009480 int flags = 0;
9481 if (si.deliveryCount > 0) {
9482 flags |= Service.START_FLAG_RETRY;
9483 }
9484 if (si.doneExecutingCount > 0) {
9485 flags |= Service.START_FLAG_REDELIVERY;
9486 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009487 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009488 } catch (RemoteException e) {
9489 // Remote process gone... we'll let the normal cleanup take
9490 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009491 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009492 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009494 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009495 break;
9496 }
9497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 }
9499
9500 private final boolean requestServiceBindingLocked(ServiceRecord r,
9501 IntentBindRecord i, boolean rebind) {
9502 if (r.app == null || r.app.thread == null) {
9503 // If service is not currently running, can't yet bind.
9504 return false;
9505 }
9506 if ((!i.requested || rebind) && i.apps.size() > 0) {
9507 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009508 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009509 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9510 if (!rebind) {
9511 i.requested = true;
9512 }
9513 i.hasBound = true;
9514 i.doRebind = false;
9515 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009516 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 return false;
9518 }
9519 }
9520 return true;
9521 }
9522
9523 private final void requestServiceBindingsLocked(ServiceRecord r) {
9524 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9525 while (bindings.hasNext()) {
9526 IntentBindRecord i = bindings.next();
9527 if (!requestServiceBindingLocked(r, i, false)) {
9528 break;
9529 }
9530 }
9531 }
9532
9533 private final void realStartServiceLocked(ServiceRecord r,
9534 ProcessRecord app) throws RemoteException {
9535 if (app.thread == null) {
9536 throw new RemoteException();
9537 }
9538
9539 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009540 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009541
9542 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009543 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009544 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545
9546 boolean created = false;
9547 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009548 mStringBuilder.setLength(0);
9549 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009550 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009551 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009552 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009553 synchronized (r.stats.getBatteryStats()) {
9554 r.stats.startLaunchedLocked();
9555 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009556 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009557 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009558 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 created = true;
9560 } finally {
9561 if (!created) {
9562 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009563 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009564 }
9565 }
9566
9567 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009568
9569 // If the service is in the started state, and there are no
9570 // pending arguments, then fake up one so its onStartCommand() will
9571 // be called.
9572 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009573 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9574 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009575 }
9576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 sendServiceArgsLocked(r, true);
9578 }
9579
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009580 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9581 boolean allowCancel) {
9582 boolean canceled = false;
9583
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009584 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009585 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009586 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009587
Dianne Hackborn070783f2010-12-29 16:46:28 -08009588 if ((r.serviceInfo.applicationInfo.flags
9589 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9590 minDuration /= 4;
9591 }
9592
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009593 // Any delivered but not yet finished starts should be put back
9594 // on the pending list.
9595 final int N = r.deliveredStarts.size();
9596 if (N > 0) {
9597 for (int i=N-1; i>=0; i--) {
9598 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009599 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009600 if (si.intent == null) {
9601 // We'll generate this again if needed.
9602 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9603 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9604 r.pendingStarts.add(0, si);
9605 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9606 dur *= 2;
9607 if (minDuration < dur) minDuration = dur;
9608 if (resetTime < dur) resetTime = dur;
9609 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009610 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009611 + r.name);
9612 canceled = true;
9613 }
9614 }
9615 r.deliveredStarts.clear();
9616 }
9617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 r.totalRestartCount++;
9619 if (r.restartDelay == 0) {
9620 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009621 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009622 } else {
9623 // If it has been a "reasonably long time" since the service
9624 // was started, then reset our restart duration back to
9625 // the beginning, so we don't infinitely increase the duration
9626 // on a service that just occasionally gets killed (which is
9627 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009628 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009629 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009630 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009631 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009632 if ((r.serviceInfo.applicationInfo.flags
9633 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9634 // Services in peristent processes will restart much more
9635 // quickly, since they are pretty important. (Think SystemUI).
9636 r.restartDelay += minDuration/2;
9637 } else {
9638 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9639 if (r.restartDelay < minDuration) {
9640 r.restartDelay = minDuration;
9641 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 }
9644 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009645
9646 r.nextRestartTime = now + r.restartDelay;
9647
9648 // Make sure that we don't end up restarting a bunch of services
9649 // all at the same time.
9650 boolean repeat;
9651 do {
9652 repeat = false;
9653 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9654 ServiceRecord r2 = mRestartingServices.get(i);
9655 if (r2 != r && r.nextRestartTime
9656 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9657 && r.nextRestartTime
9658 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9659 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9660 r.restartDelay = r.nextRestartTime - now;
9661 repeat = true;
9662 break;
9663 }
9664 }
9665 } while (repeat);
9666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 if (!mRestartingServices.contains(r)) {
9668 mRestartingServices.add(r);
9669 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009670
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009671 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009674 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009676 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009678 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 r.shortName, r.restartDelay);
9680
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009681 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009682 }
9683
9684 final void performServiceRestartLocked(ServiceRecord r) {
9685 if (!mRestartingServices.contains(r)) {
9686 return;
9687 }
9688 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9689 }
9690
9691 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9692 if (r.restartDelay == 0) {
9693 return false;
9694 }
9695 r.resetRestartCounter();
9696 mRestartingServices.remove(r);
9697 mHandler.removeCallbacks(r.restarter);
9698 return true;
9699 }
9700
9701 private final boolean bringUpServiceLocked(ServiceRecord r,
9702 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009703 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 //r.dump(" ");
9705
Dianne Hackborn36124872009-10-08 16:22:03 -07009706 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009707 sendServiceArgsLocked(r, false);
9708 return true;
9709 }
9710
9711 if (!whileRestarting && r.restartDelay > 0) {
9712 // If waiting for a restart, then do nothing.
9713 return true;
9714 }
9715
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009716 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009718 // We are now bringing the service up, so no longer in the
9719 // restarting state.
9720 mRestartingServices.remove(r);
9721
Dianne Hackborne7f97212011-02-24 14:40:20 -08009722 // Service is now being launched, its package can't be stopped.
9723 try {
9724 AppGlobals.getPackageManager().setPackageStoppedState(
9725 r.packageName, false);
9726 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009727 } catch (IllegalArgumentException e) {
9728 Slog.w(TAG, "Failed trying to unstop package "
9729 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009730 }
9731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009732 final String appName = r.processName;
9733 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9734 if (app != null && app.thread != null) {
9735 try {
9736 realStartServiceLocked(r, app);
9737 return true;
9738 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009739 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 }
9741
9742 // If a dead object exception was thrown -- fall through to
9743 // restart the application.
9744 }
9745
Dianne Hackborn36124872009-10-08 16:22:03 -07009746 // Not running -- get it started, and enqueue this service record
9747 // to be executed when the app comes up.
9748 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9749 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009750 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009751 + r.appInfo.packageName + "/"
9752 + r.appInfo.uid + " for service "
9753 + r.intent.getIntent() + ": process is bad");
9754 bringDownServiceLocked(r, true);
9755 return false;
9756 }
9757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 mPendingServices.add(r);
9760 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 return true;
9763 }
9764
9765 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009766 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 //r.dump(" ");
9768
9769 // Does it still need to run?
9770 if (!force && r.startRequested) {
9771 return;
9772 }
9773 if (r.connections.size() > 0) {
9774 if (!force) {
9775 // XXX should probably keep a count of the number of auto-create
9776 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009777 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009779 ArrayList<ConnectionRecord> cr = it.next();
9780 for (int i=0; i<cr.size(); i++) {
9781 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9782 return;
9783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 }
9785 }
9786 }
9787
9788 // Report to all of the connections that the service is no longer
9789 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009790 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009792 ArrayList<ConnectionRecord> c = it.next();
9793 for (int i=0; i<c.size(); i++) {
9794 try {
9795 c.get(i).conn.connected(r.name, null);
9796 } catch (Exception e) {
9797 Slog.w(TAG, "Failure disconnecting service " + r.name +
9798 " to connection " + c.get(i).conn.asBinder() +
9799 " (in " + c.get(i).binding.client.processName + ")", e);
9800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009801 }
9802 }
9803 }
9804
9805 // Tell the service that it has been unbound.
9806 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9807 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9808 while (it.hasNext()) {
9809 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009810 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811 + ": hasBound=" + ibr.hasBound);
9812 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9813 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009814 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009815 updateOomAdjLocked(r.app);
9816 ibr.hasBound = false;
9817 r.app.thread.scheduleUnbindService(r,
9818 ibr.intent.getIntent());
9819 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009820 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 + r.shortName, e);
9822 serviceDoneExecutingLocked(r, true);
9823 }
9824 }
9825 }
9826 }
9827
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009828 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009829 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 System.identityHashCode(r), r.shortName,
9831 (r.app != null) ? r.app.pid : -1);
9832
9833 mServices.remove(r.name);
9834 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 r.totalRestartCount = 0;
9836 unscheduleServiceRestartLocked(r);
9837
9838 // Also make sure it is not on the pending list.
9839 int N = mPendingServices.size();
9840 for (int i=0; i<N; i++) {
9841 if (mPendingServices.get(i) == r) {
9842 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009843 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 i--;
9845 N--;
9846 }
9847 }
9848
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009849 r.cancelNotification();
9850 r.isForeground = false;
9851 r.foregroundId = 0;
9852 r.foregroundNoti = null;
9853
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009854 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009855 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009856 r.pendingStarts.clear();
9857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009858 if (r.app != null) {
9859 synchronized (r.stats.getBatteryStats()) {
9860 r.stats.stopLaunchedLocked();
9861 }
9862 r.app.services.remove(r);
9863 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009865 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009866 mStoppingServices.add(r);
9867 updateOomAdjLocked(r.app);
9868 r.app.thread.scheduleStopService(r);
9869 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009870 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 + r.shortName, e);
9872 serviceDoneExecutingLocked(r, true);
9873 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009874 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009876 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009877 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 }
9879 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009880 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009881 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009882 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009883
9884 if (r.bindings.size() > 0) {
9885 r.bindings.clear();
9886 }
9887
9888 if (r.restarter instanceof ServiceRestarter) {
9889 ((ServiceRestarter)r.restarter).setService(null);
9890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009891 }
9892
9893 ComponentName startServiceLocked(IApplicationThread caller,
9894 Intent service, String resolvedType,
9895 int callingPid, int callingUid) {
9896 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009897 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 + " type=" + resolvedType + " args=" + service.getExtras());
9899
9900 if (caller != null) {
9901 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9902 if (callerApp == null) {
9903 throw new SecurityException(
9904 "Unable to find app for caller " + caller
9905 + " (pid=" + Binder.getCallingPid()
9906 + ") when starting service " + service);
9907 }
9908 }
9909
9910 ServiceLookupResult res =
9911 retrieveServiceLocked(service, resolvedType,
9912 callingPid, callingUid);
9913 if (res == null) {
9914 return null;
9915 }
9916 if (res.record == null) {
9917 return new ComponentName("!", res.permission != null
9918 ? res.permission : "private to package");
9919 }
9920 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009921 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9922 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009924 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 }
9926 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009927 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009928 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -07009929 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 r.lastActivity = SystemClock.uptimeMillis();
9931 synchronized (r.stats.getBatteryStats()) {
9932 r.stats.startRunningLocked();
9933 }
9934 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9935 return new ComponentName("!", "Service process is bad");
9936 }
9937 return r.name;
9938 }
9939 }
9940
9941 public ComponentName startService(IApplicationThread caller, Intent service,
9942 String resolvedType) {
9943 // Refuse possible leaked file descriptors
9944 if (service != null && service.hasFileDescriptors() == true) {
9945 throw new IllegalArgumentException("File descriptors passed in Intent");
9946 }
9947
9948 synchronized(this) {
9949 final int callingPid = Binder.getCallingPid();
9950 final int callingUid = Binder.getCallingUid();
9951 final long origId = Binder.clearCallingIdentity();
9952 ComponentName res = startServiceLocked(caller, service,
9953 resolvedType, callingPid, callingUid);
9954 Binder.restoreCallingIdentity(origId);
9955 return res;
9956 }
9957 }
9958
9959 ComponentName startServiceInPackage(int uid,
9960 Intent service, String resolvedType) {
9961 synchronized(this) {
9962 final long origId = Binder.clearCallingIdentity();
9963 ComponentName res = startServiceLocked(null, service,
9964 resolvedType, -1, uid);
9965 Binder.restoreCallingIdentity(origId);
9966 return res;
9967 }
9968 }
9969
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009970 private void stopServiceLocked(ServiceRecord service) {
9971 synchronized (service.stats.getBatteryStats()) {
9972 service.stats.stopRunningLocked();
9973 }
9974 service.startRequested = false;
9975 service.callStart = false;
9976 bringDownServiceLocked(service, false);
9977 }
9978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 public int stopService(IApplicationThread caller, Intent service,
9980 String resolvedType) {
9981 // Refuse possible leaked file descriptors
9982 if (service != null && service.hasFileDescriptors() == true) {
9983 throw new IllegalArgumentException("File descriptors passed in Intent");
9984 }
9985
9986 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009987 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 + " type=" + resolvedType);
9989
9990 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9991 if (caller != null && callerApp == null) {
9992 throw new SecurityException(
9993 "Unable to find app for caller " + caller
9994 + " (pid=" + Binder.getCallingPid()
9995 + ") when stopping service " + service);
9996 }
9997
9998 // If this service is active, make sure it is stopped.
9999 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10000 if (r != null) {
10001 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010003 try {
10004 stopServiceLocked(r.record);
10005 } finally {
10006 Binder.restoreCallingIdentity(origId);
10007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010008 return 1;
10009 }
10010 return -1;
10011 }
10012 }
10013
10014 return 0;
10015 }
10016
10017 public IBinder peekService(Intent service, String resolvedType) {
10018 // Refuse possible leaked file descriptors
10019 if (service != null && service.hasFileDescriptors() == true) {
10020 throw new IllegalArgumentException("File descriptors passed in Intent");
10021 }
10022
10023 IBinder ret = null;
10024
10025 synchronized(this) {
10026 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10027
10028 if (r != null) {
10029 // r.record is null if findServiceLocked() failed the caller permission check
10030 if (r.record == null) {
10031 throw new SecurityException(
10032 "Permission Denial: Accessing service " + r.record.name
10033 + " from pid=" + Binder.getCallingPid()
10034 + ", uid=" + Binder.getCallingUid()
10035 + " requires " + r.permission);
10036 }
10037 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10038 if (ib != null) {
10039 ret = ib.binder;
10040 }
10041 }
10042 }
10043
10044 return ret;
10045 }
10046
10047 public boolean stopServiceToken(ComponentName className, IBinder token,
10048 int startId) {
10049 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010050 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 + " " + token + " startId=" + startId);
10052 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010053 if (r != null) {
10054 if (startId >= 0) {
10055 // Asked to only stop if done with all work. Note that
10056 // to avoid leaks, we will take this as dropping all
10057 // start items up to and including this one.
10058 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10059 if (si != null) {
10060 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010061 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10062 cur.removeUriPermissionsLocked();
10063 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010064 break;
10065 }
10066 }
10067 }
10068
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010069 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010070 return false;
10071 }
10072
10073 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010074 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010075 + " is last, but have " + r.deliveredStarts.size()
10076 + " remaining args");
10077 }
10078 }
10079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 synchronized (r.stats.getBatteryStats()) {
10081 r.stats.stopRunningLocked();
10082 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010083 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 }
10085 final long origId = Binder.clearCallingIdentity();
10086 bringDownServiceLocked(r, false);
10087 Binder.restoreCallingIdentity(origId);
10088 return true;
10089 }
10090 }
10091 return false;
10092 }
10093
10094 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010095 int id, Notification notification, boolean removeNotification) {
10096 final long origId = Binder.clearCallingIdentity();
10097 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 synchronized(this) {
10099 ServiceRecord r = findServiceLocked(className, token);
10100 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010101 if (id != 0) {
10102 if (notification == null) {
10103 throw new IllegalArgumentException("null notification");
10104 }
10105 if (r.foregroundId != id) {
10106 r.cancelNotification();
10107 r.foregroundId = id;
10108 }
10109 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10110 r.foregroundNoti = notification;
10111 r.isForeground = true;
10112 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113 if (r.app != null) {
10114 updateServiceForegroundLocked(r.app, true);
10115 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010116 } else {
10117 if (r.isForeground) {
10118 r.isForeground = false;
10119 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010120 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010121 updateServiceForegroundLocked(r.app, true);
10122 }
10123 }
10124 if (removeNotification) {
10125 r.cancelNotification();
10126 r.foregroundId = 0;
10127 r.foregroundNoti = null;
10128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129 }
10130 }
10131 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010132 } finally {
10133 Binder.restoreCallingIdentity(origId);
10134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 }
10136
10137 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10138 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010139 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 if (sr.isForeground) {
10141 anyForeground = true;
10142 break;
10143 }
10144 }
10145 if (anyForeground != proc.foregroundServices) {
10146 proc.foregroundServices = anyForeground;
10147 if (oomAdj) {
10148 updateOomAdjLocked();
10149 }
10150 }
10151 }
10152
10153 public int bindService(IApplicationThread caller, IBinder token,
10154 Intent service, String resolvedType,
10155 IServiceConnection connection, int flags) {
10156 // Refuse possible leaked file descriptors
10157 if (service != null && service.hasFileDescriptors() == true) {
10158 throw new IllegalArgumentException("File descriptors passed in Intent");
10159 }
10160
10161 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010162 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 + " type=" + resolvedType + " conn=" + connection.asBinder()
10164 + " flags=0x" + Integer.toHexString(flags));
10165 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10166 if (callerApp == null) {
10167 throw new SecurityException(
10168 "Unable to find app for caller " + caller
10169 + " (pid=" + Binder.getCallingPid()
10170 + ") when binding service " + service);
10171 }
10172
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010173 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010175 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010177 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 return 0;
10179 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010180 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010181 }
10182
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010183 int clientLabel = 0;
10184 PendingIntent clientIntent = null;
10185
10186 if (callerApp.info.uid == Process.SYSTEM_UID) {
10187 // Hacky kind of thing -- allow system stuff to tell us
10188 // what they are, so we can report this elsewhere for
10189 // others to know why certain services are running.
10190 try {
10191 clientIntent = (PendingIntent)service.getParcelableExtra(
10192 Intent.EXTRA_CLIENT_INTENT);
10193 } catch (RuntimeException e) {
10194 }
10195 if (clientIntent != null) {
10196 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10197 if (clientLabel != 0) {
10198 // There are no useful extras in the intent, trash them.
10199 // System code calling with this stuff just needs to know
10200 // this will happen.
10201 service = service.cloneFilter();
10202 }
10203 }
10204 }
10205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 ServiceLookupResult res =
10207 retrieveServiceLocked(service, resolvedType,
10208 Binder.getCallingPid(), Binder.getCallingUid());
10209 if (res == null) {
10210 return 0;
10211 }
10212 if (res.record == null) {
10213 return -1;
10214 }
10215 ServiceRecord s = res.record;
10216
10217 final long origId = Binder.clearCallingIdentity();
10218
10219 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010220 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010221 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010222 }
10223
10224 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10225 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010226 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227
10228 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010229 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10230 if (clist == null) {
10231 clist = new ArrayList<ConnectionRecord>();
10232 s.connections.put(binder, clist);
10233 }
10234 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 b.connections.add(c);
10236 if (activity != null) {
10237 if (activity.connections == null) {
10238 activity.connections = new HashSet<ConnectionRecord>();
10239 }
10240 activity.connections.add(c);
10241 }
10242 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010243 clist = mServiceConnections.get(binder);
10244 if (clist == null) {
10245 clist = new ArrayList<ConnectionRecord>();
10246 mServiceConnections.put(binder, clist);
10247 }
10248 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249
10250 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10251 s.lastActivity = SystemClock.uptimeMillis();
10252 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10253 return 0;
10254 }
10255 }
10256
10257 if (s.app != null) {
10258 // This could have made the service more important.
10259 updateOomAdjLocked(s.app);
10260 }
10261
Joe Onorato8a9b2202010-02-26 18:56:32 -080010262 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010263 + ": received=" + b.intent.received
10264 + " apps=" + b.intent.apps.size()
10265 + " doRebind=" + b.intent.doRebind);
10266
10267 if (s.app != null && b.intent.received) {
10268 // Service is already running, so we can immediately
10269 // publish the connection.
10270 try {
10271 c.conn.connected(s.name, b.intent.binder);
10272 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010273 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 + " to connection " + c.conn.asBinder()
10275 + " (in " + c.binding.client.processName + ")", e);
10276 }
10277
10278 // If this is the first app connected back to this binding,
10279 // and the service had previously asked to be told when
10280 // rebound, then do so.
10281 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10282 requestServiceBindingLocked(s, b.intent, true);
10283 }
10284 } else if (!b.intent.requested) {
10285 requestServiceBindingLocked(s, b.intent, false);
10286 }
10287
10288 Binder.restoreCallingIdentity(origId);
10289 }
10290
10291 return 1;
10292 }
10293
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010294 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010295 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 IBinder binder = c.conn.asBinder();
10297 AppBindRecord b = c.binding;
10298 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010299 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10300 if (clist != null) {
10301 clist.remove(c);
10302 if (clist.size() == 0) {
10303 s.connections.remove(binder);
10304 }
10305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010306 b.connections.remove(c);
10307 if (c.activity != null && c.activity != skipAct) {
10308 if (c.activity.connections != null) {
10309 c.activity.connections.remove(c);
10310 }
10311 }
10312 if (b.client != skipApp) {
10313 b.client.connections.remove(c);
10314 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010315 clist = mServiceConnections.get(binder);
10316 if (clist != null) {
10317 clist.remove(c);
10318 if (clist.size() == 0) {
10319 mServiceConnections.remove(binder);
10320 }
10321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322
10323 if (b.connections.size() == 0) {
10324 b.intent.apps.remove(b.client);
10325 }
10326
Joe Onorato8a9b2202010-02-26 18:56:32 -080010327 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 + ": shouldUnbind=" + b.intent.hasBound);
10329 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10330 && b.intent.hasBound) {
10331 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010332 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 updateOomAdjLocked(s.app);
10334 b.intent.hasBound = false;
10335 // Assume the client doesn't want to know about a rebind;
10336 // we will deal with that later if it asks for one.
10337 b.intent.doRebind = false;
10338 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10339 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010340 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 serviceDoneExecutingLocked(s, true);
10342 }
10343 }
10344
10345 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10346 bringDownServiceLocked(s, false);
10347 }
10348 }
10349
10350 public boolean unbindService(IServiceConnection connection) {
10351 synchronized (this) {
10352 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010353 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010354 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10355 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010356 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 + connection.asBinder());
10358 return false;
10359 }
10360
10361 final long origId = Binder.clearCallingIdentity();
10362
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010363 while (clist.size() > 0) {
10364 ConnectionRecord r = clist.get(0);
10365 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010366
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010367 if (r.binding.service.app != null) {
10368 // This could have made the service less important.
10369 updateOomAdjLocked(r.binding.service.app);
10370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 }
10372
10373 Binder.restoreCallingIdentity(origId);
10374 }
10375
10376 return true;
10377 }
10378
10379 public void publishService(IBinder token, Intent intent, IBinder service) {
10380 // Refuse possible leaked file descriptors
10381 if (intent != null && intent.hasFileDescriptors() == true) {
10382 throw new IllegalArgumentException("File descriptors passed in Intent");
10383 }
10384
10385 synchronized(this) {
10386 if (!(token instanceof ServiceRecord)) {
10387 throw new IllegalArgumentException("Invalid service token");
10388 }
10389 ServiceRecord r = (ServiceRecord)token;
10390
10391 final long origId = Binder.clearCallingIdentity();
10392
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010393 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 + " " + intent + ": " + service);
10395 if (r != null) {
10396 Intent.FilterComparison filter
10397 = new Intent.FilterComparison(intent);
10398 IntentBindRecord b = r.bindings.get(filter);
10399 if (b != null && !b.received) {
10400 b.binder = service;
10401 b.requested = true;
10402 b.received = true;
10403 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010404 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 = r.connections.values().iterator();
10406 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010407 ArrayList<ConnectionRecord> clist = it.next();
10408 for (int i=0; i<clist.size(); i++) {
10409 ConnectionRecord c = clist.get(i);
10410 if (!filter.equals(c.binding.intent.intent)) {
10411 if (DEBUG_SERVICE) Slog.v(
10412 TAG, "Not publishing to: " + c);
10413 if (DEBUG_SERVICE) Slog.v(
10414 TAG, "Bound intent: " + c.binding.intent.intent);
10415 if (DEBUG_SERVICE) Slog.v(
10416 TAG, "Published intent: " + intent);
10417 continue;
10418 }
10419 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10420 try {
10421 c.conn.connected(r.name, service);
10422 } catch (Exception e) {
10423 Slog.w(TAG, "Failure sending service " + r.name +
10424 " to connection " + c.conn.asBinder() +
10425 " (in " + c.binding.client.processName + ")", e);
10426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 }
10428 }
10429 }
10430 }
10431
10432 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10433
10434 Binder.restoreCallingIdentity(origId);
10435 }
10436 }
10437 }
10438
10439 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10440 // Refuse possible leaked file descriptors
10441 if (intent != null && intent.hasFileDescriptors() == true) {
10442 throw new IllegalArgumentException("File descriptors passed in Intent");
10443 }
10444
10445 synchronized(this) {
10446 if (!(token instanceof ServiceRecord)) {
10447 throw new IllegalArgumentException("Invalid service token");
10448 }
10449 ServiceRecord r = (ServiceRecord)token;
10450
10451 final long origId = Binder.clearCallingIdentity();
10452
10453 if (r != null) {
10454 Intent.FilterComparison filter
10455 = new Intent.FilterComparison(intent);
10456 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010457 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 + " at " + b + ": apps="
10459 + (b != null ? b.apps.size() : 0));
10460 if (b != null) {
10461 if (b.apps.size() > 0) {
10462 // Applications have already bound since the last
10463 // unbind, so just rebind right here.
10464 requestServiceBindingLocked(r, b, true);
10465 } else {
10466 // Note to tell the service the next time there is
10467 // a new client.
10468 b.doRebind = true;
10469 }
10470 }
10471
10472 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10473
10474 Binder.restoreCallingIdentity(origId);
10475 }
10476 }
10477 }
10478
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010479 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010480 synchronized(this) {
10481 if (!(token instanceof ServiceRecord)) {
10482 throw new IllegalArgumentException("Invalid service token");
10483 }
10484 ServiceRecord r = (ServiceRecord)token;
10485 boolean inStopping = mStoppingServices.contains(token);
10486 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010488 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010489 + " with incorrect token: given " + token
10490 + ", expected " + r);
10491 return;
10492 }
10493
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010494 if (type == 1) {
10495 // This is a call from a service start... take care of
10496 // book-keeping.
10497 r.callStart = true;
10498 switch (res) {
10499 case Service.START_STICKY_COMPATIBILITY:
10500 case Service.START_STICKY: {
10501 // We are done with the associated start arguments.
10502 r.findDeliveredStart(startId, true);
10503 // Don't stop if killed.
10504 r.stopIfKilled = false;
10505 break;
10506 }
10507 case Service.START_NOT_STICKY: {
10508 // We are done with the associated start arguments.
10509 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010510 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010511 // There is no more work, and this service
10512 // doesn't want to hang around if killed.
10513 r.stopIfKilled = true;
10514 }
10515 break;
10516 }
10517 case Service.START_REDELIVER_INTENT: {
10518 // We'll keep this item until they explicitly
10519 // call stop for it, but keep track of the fact
10520 // that it was delivered.
10521 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10522 if (si != null) {
10523 si.deliveryCount = 0;
10524 si.doneExecutingCount++;
10525 // Don't stop if killed.
10526 r.stopIfKilled = true;
10527 }
10528 break;
10529 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010530 case Service.START_TASK_REMOVED_COMPLETE: {
10531 // Special processing for onTaskRemoved(). Don't
10532 // impact normal onStartCommand() processing.
10533 r.findDeliveredStart(startId, true);
10534 break;
10535 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010536 default:
10537 throw new IllegalArgumentException(
10538 "Unknown service start result: " + res);
10539 }
10540 if (res == Service.START_STICKY_COMPATIBILITY) {
10541 r.callStart = false;
10542 }
10543 }
10544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 final long origId = Binder.clearCallingIdentity();
10546 serviceDoneExecutingLocked(r, inStopping);
10547 Binder.restoreCallingIdentity(origId);
10548 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010549 Slog.w(TAG, "Done executing unknown service from pid "
10550 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 }
10552 }
10553 }
10554
10555 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010556 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10557 + ": nesting=" + r.executeNesting
10558 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010559 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 r.executeNesting--;
10561 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010562 if (DEBUG_SERVICE) Slog.v(TAG,
10563 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010564 r.app.executingServices.remove(r);
10565 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010566 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10567 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10569 }
10570 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010571 if (DEBUG_SERVICE) Slog.v(TAG,
10572 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010573 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010574 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 }
10576 updateOomAdjLocked(r.app);
10577 }
10578 }
10579
10580 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010581 String anrMessage = null;
10582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 synchronized(this) {
10584 if (proc.executingServices.size() == 0 || proc.thread == null) {
10585 return;
10586 }
10587 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10588 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10589 ServiceRecord timeout = null;
10590 long nextTime = 0;
10591 while (it.hasNext()) {
10592 ServiceRecord sr = it.next();
10593 if (sr.executingStart < maxTime) {
10594 timeout = sr;
10595 break;
10596 }
10597 if (sr.executingStart > nextTime) {
10598 nextTime = sr.executingStart;
10599 }
10600 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010601 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010602 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010603 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 } else {
10605 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10606 msg.obj = proc;
10607 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10608 }
10609 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010610
10611 if (anrMessage != null) {
10612 appNotResponding(proc, null, null, anrMessage);
10613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 }
10615
10616 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010617 // BACKUP AND RESTORE
10618 // =========================================================
10619
10620 // Cause the target app to be launched if necessary and its backup agent
10621 // instantiated. The backup agent will invoke backupAgentCreated() on the
10622 // activity manager to announce its creation.
10623 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010624 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010625 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10626
10627 synchronized(this) {
10628 // !!! TODO: currently no check here that we're already bound
10629 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10630 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10631 synchronized (stats) {
10632 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10633 }
10634
Dianne Hackborne7f97212011-02-24 14:40:20 -080010635 // Backup agent is now in use, its package can't be stopped.
10636 try {
10637 AppGlobals.getPackageManager().setPackageStoppedState(
10638 app.packageName, false);
10639 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010640 } catch (IllegalArgumentException e) {
10641 Slog.w(TAG, "Failed trying to unstop package "
10642 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010643 }
10644
Christopher Tate181fafa2009-05-14 11:12:14 -070010645 BackupRecord r = new BackupRecord(ss, app, backupMode);
10646 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10647 // startProcessLocked() returns existing proc's record if it's already running
10648 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010649 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010650 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010651 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010652 return false;
10653 }
10654
10655 r.app = proc;
10656 mBackupTarget = r;
10657 mBackupAppName = app.packageName;
10658
Christopher Tate6fa95972009-06-05 18:43:55 -070010659 // Try not to kill the process during backup
10660 updateOomAdjLocked(proc);
10661
Christopher Tate181fafa2009-05-14 11:12:14 -070010662 // If the process is already attached, schedule the creation of the backup agent now.
10663 // If it is not yet live, this will be done when it attaches to the framework.
10664 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010665 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010666 try {
10667 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10668 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010669 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010670 }
10671 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010672 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010673 }
10674 // Invariants: at this point, the target app process exists and the application
10675 // is either already running or in the process of coming up. mBackupTarget and
10676 // mBackupAppName describe the app, so that when it binds back to the AM we
10677 // know that it's scheduled for a backup-agent operation.
10678 }
10679
10680 return true;
10681 }
10682
10683 // A backup agent has just come up
10684 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010685 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010686 + " = " + agent);
10687
10688 synchronized(this) {
10689 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010690 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010691 return;
10692 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010693 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010694
Dianne Hackborn06740692010-09-22 22:46:21 -070010695 long oldIdent = Binder.clearCallingIdentity();
10696 try {
10697 IBackupManager bm = IBackupManager.Stub.asInterface(
10698 ServiceManager.getService(Context.BACKUP_SERVICE));
10699 bm.agentConnected(agentPackageName, agent);
10700 } catch (RemoteException e) {
10701 // can't happen; the backup manager service is local
10702 } catch (Exception e) {
10703 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10704 e.printStackTrace();
10705 } finally {
10706 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010707 }
10708 }
10709
10710 // done with this agent
10711 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010712 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010713 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010714 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010715 return;
10716 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010717
10718 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010719 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010720 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010721 return;
10722 }
10723
Christopher Tate181fafa2009-05-14 11:12:14 -070010724 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010725 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010726 return;
10727 }
10728
Christopher Tate6fa95972009-06-05 18:43:55 -070010729 ProcessRecord proc = mBackupTarget.app;
10730 mBackupTarget = null;
10731 mBackupAppName = null;
10732
10733 // Not backing this app up any more; reset its OOM adjustment
10734 updateOomAdjLocked(proc);
10735
Christopher Tatec7b31e32009-06-10 15:49:30 -070010736 // If the app crashed during backup, 'thread' will be null here
10737 if (proc.thread != null) {
10738 try {
10739 proc.thread.scheduleDestroyBackupAgent(appInfo);
10740 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010741 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010742 e.printStackTrace();
10743 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010744 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010745 }
10746 }
10747 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 // BROADCASTS
10749 // =========================================================
10750
Josh Bartel7f208742010-02-25 11:01:44 -060010751 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 List cur) {
10753 final ContentResolver resolver = mContext.getContentResolver();
10754 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10755 if (list == null) {
10756 return cur;
10757 }
10758 int N = list.size();
10759 for (int i=0; i<N; i++) {
10760 Intent intent = list.get(i);
10761 if (filter.match(resolver, intent, true, TAG) >= 0) {
10762 if (cur == null) {
10763 cur = new ArrayList<Intent>();
10764 }
10765 cur.add(intent);
10766 }
10767 }
10768 return cur;
10769 }
10770
10771 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010772 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 + mBroadcastsScheduled);
10774
10775 if (mBroadcastsScheduled) {
10776 return;
10777 }
10778 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10779 mBroadcastsScheduled = true;
10780 }
10781
10782 public Intent registerReceiver(IApplicationThread caller,
10783 IIntentReceiver receiver, IntentFilter filter, String permission) {
10784 synchronized(this) {
10785 ProcessRecord callerApp = null;
10786 if (caller != null) {
10787 callerApp = getRecordForAppLocked(caller);
10788 if (callerApp == null) {
10789 throw new SecurityException(
10790 "Unable to find app for caller " + caller
10791 + " (pid=" + Binder.getCallingPid()
10792 + ") when registering receiver " + receiver);
10793 }
10794 }
10795
10796 List allSticky = null;
10797
10798 // Look for any matching sticky broadcasts...
10799 Iterator actions = filter.actionsIterator();
10800 if (actions != null) {
10801 while (actions.hasNext()) {
10802 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010803 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010804 }
10805 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010806 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 }
10808
10809 // The first sticky in the list is returned directly back to
10810 // the client.
10811 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10812
Joe Onorato8a9b2202010-02-26 18:56:32 -080010813 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010814 + ": " + sticky);
10815
10816 if (receiver == null) {
10817 return sticky;
10818 }
10819
10820 ReceiverList rl
10821 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10822 if (rl == null) {
10823 rl = new ReceiverList(this, callerApp,
10824 Binder.getCallingPid(),
10825 Binder.getCallingUid(), receiver);
10826 if (rl.app != null) {
10827 rl.app.receivers.add(rl);
10828 } else {
10829 try {
10830 receiver.asBinder().linkToDeath(rl, 0);
10831 } catch (RemoteException e) {
10832 return sticky;
10833 }
10834 rl.linkedToDeath = true;
10835 }
10836 mRegisteredReceivers.put(receiver.asBinder(), rl);
10837 }
10838 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10839 rl.add(bf);
10840 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010841 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010842 }
10843 mReceiverResolver.addFilter(bf);
10844
10845 // Enqueue broadcasts for all existing stickies that match
10846 // this filter.
10847 if (allSticky != null) {
10848 ArrayList receivers = new ArrayList();
10849 receivers.add(bf);
10850
10851 int N = allSticky.size();
10852 for (int i=0; i<N; i++) {
10853 Intent intent = (Intent)allSticky.get(i);
10854 BroadcastRecord r = new BroadcastRecord(intent, null,
10855 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010856 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 if (mParallelBroadcasts.size() == 0) {
10858 scheduleBroadcastsLocked();
10859 }
10860 mParallelBroadcasts.add(r);
10861 }
10862 }
10863
10864 return sticky;
10865 }
10866 }
10867
10868 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010869 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010870
10871 boolean doNext = false;
10872
10873 synchronized(this) {
10874 ReceiverList rl
10875 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10876 if (rl != null) {
10877 if (rl.curBroadcast != null) {
10878 BroadcastRecord r = rl.curBroadcast;
10879 doNext = finishReceiverLocked(
10880 receiver.asBinder(), r.resultCode, r.resultData,
10881 r.resultExtras, r.resultAbort, true);
10882 }
10883
10884 if (rl.app != null) {
10885 rl.app.receivers.remove(rl);
10886 }
10887 removeReceiverLocked(rl);
10888 if (rl.linkedToDeath) {
10889 rl.linkedToDeath = false;
10890 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10891 }
10892 }
10893 }
10894
10895 if (!doNext) {
10896 return;
10897 }
10898
10899 final long origId = Binder.clearCallingIdentity();
10900 processNextBroadcast(false);
10901 trimApplications();
10902 Binder.restoreCallingIdentity(origId);
10903 }
10904
10905 void removeReceiverLocked(ReceiverList rl) {
10906 mRegisteredReceivers.remove(rl.receiver.asBinder());
10907 int N = rl.size();
10908 for (int i=0; i<N; i++) {
10909 mReceiverResolver.removeFilter(rl.get(i));
10910 }
10911 }
10912
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010913 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10914 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10915 ProcessRecord r = mLruProcesses.get(i);
10916 if (r.thread != null) {
10917 try {
10918 r.thread.dispatchPackageBroadcast(cmd, packages);
10919 } catch (RemoteException ex) {
10920 }
10921 }
10922 }
10923 }
10924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 private final int broadcastIntentLocked(ProcessRecord callerApp,
10926 String callerPackage, Intent intent, String resolvedType,
10927 IIntentReceiver resultTo, int resultCode, String resultData,
10928 Bundle map, String requiredPermission,
10929 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10930 intent = new Intent(intent);
10931
Dianne Hackborne7f97212011-02-24 14:40:20 -080010932 // By default broadcasts do not go to stopped apps.
10933 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10934
Joe Onorato8a9b2202010-02-26 18:56:32 -080010935 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10937 + " ordered=" + ordered);
10938 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010939 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 }
10941
10942 // Handle special intents: if this broadcast is from the package
10943 // manager about a package being removed, we need to remove all of
10944 // its activities from the history stack.
10945 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10946 intent.getAction());
10947 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10948 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010949 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 || uidRemoved) {
10951 if (checkComponentPermission(
10952 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010953 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 == PackageManager.PERMISSION_GRANTED) {
10955 if (uidRemoved) {
10956 final Bundle intentExtras = intent.getExtras();
10957 final int uid = intentExtras != null
10958 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10959 if (uid >= 0) {
10960 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10961 synchronized (bs) {
10962 bs.removeUidStatsLocked(uid);
10963 }
10964 }
10965 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010966 // If resources are unvailble just force stop all
10967 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010968 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010969 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10970 if (list != null && (list.length > 0)) {
10971 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010972 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010973 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010974 sendPackageBroadcastLocked(
10975 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010976 }
10977 } else {
10978 Uri data = intent.getData();
10979 String ssp;
10980 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10981 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10982 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010983 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010984 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010985 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10986 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10987 new String[] {ssp});
10988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 }
10990 }
10991 }
10992 } else {
10993 String msg = "Permission Denial: " + intent.getAction()
10994 + " broadcast from " + callerPackage + " (pid=" + callingPid
10995 + ", uid=" + callingUid + ")"
10996 + " requires "
10997 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010998 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010999 throw new SecurityException(msg);
11000 }
11001 }
11002
11003 /*
11004 * If this is the time zone changed action, queue up a message that will reset the timezone
11005 * of all currently running processes. This message will get queued up before the broadcast
11006 * happens.
11007 */
11008 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11009 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11010 }
11011
Robert Greenwalt03595d02010-11-02 14:08:23 -070011012 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11013 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11014 }
11015
Robert Greenwalt434203a2010-10-11 16:00:27 -070011016 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11017 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11018 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11019 }
11020
Dianne Hackborn854060af2009-07-09 18:14:31 -070011021 /*
11022 * Prevent non-system code (defined here to be non-persistent
11023 * processes) from sending protected broadcasts.
11024 */
11025 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11026 || callingUid == Process.SHELL_UID || callingUid == 0) {
11027 // Always okay.
11028 } else if (callerApp == null || !callerApp.persistent) {
11029 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011030 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011031 intent.getAction())) {
11032 String msg = "Permission Denial: not allowed to send broadcast "
11033 + intent.getAction() + " from pid="
11034 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011035 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011036 throw new SecurityException(msg);
11037 }
11038 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011039 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011040 return BROADCAST_SUCCESS;
11041 }
11042 }
11043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 // Add to the sticky list if requested.
11045 if (sticky) {
11046 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11047 callingPid, callingUid)
11048 != PackageManager.PERMISSION_GRANTED) {
11049 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11050 + callingPid + ", uid=" + callingUid
11051 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011052 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 throw new SecurityException(msg);
11054 }
11055 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011056 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 + " and enforce permission " + requiredPermission);
11058 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11059 }
11060 if (intent.getComponent() != null) {
11061 throw new SecurityException(
11062 "Sticky broadcasts can't target a specific component");
11063 }
11064 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11065 if (list == null) {
11066 list = new ArrayList<Intent>();
11067 mStickyBroadcasts.put(intent.getAction(), list);
11068 }
11069 int N = list.size();
11070 int i;
11071 for (i=0; i<N; i++) {
11072 if (intent.filterEquals(list.get(i))) {
11073 // This sticky already exists, replace it.
11074 list.set(i, new Intent(intent));
11075 break;
11076 }
11077 }
11078 if (i >= N) {
11079 list.add(new Intent(intent));
11080 }
11081 }
11082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083 // Figure out who all will receive this broadcast.
11084 List receivers = null;
11085 List<BroadcastFilter> registeredReceivers = null;
11086 try {
11087 if (intent.getComponent() != null) {
11088 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011089 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011090 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 if (ai != null) {
11092 receivers = new ArrayList();
11093 ResolveInfo ri = new ResolveInfo();
11094 ri.activityInfo = ai;
11095 receivers.add(ri);
11096 }
11097 } else {
11098 // Need to resolve the intent to interested receivers...
11099 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11100 == 0) {
11101 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011102 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011103 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 }
Mihai Preda074edef2009-05-18 17:13:31 +020011105 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 }
11107 } catch (RemoteException ex) {
11108 // pm is in same process, this will never happen.
11109 }
11110
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011111 final boolean replacePending =
11112 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11113
Joe Onorato8a9b2202010-02-26 18:56:32 -080011114 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011115 + " replacePending=" + replacePending);
11116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11118 if (!ordered && NR > 0) {
11119 // If we are not serializing this broadcast, then send the
11120 // registered receivers separately so they don't wait for the
11121 // components to be launched.
11122 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11123 callerPackage, callingPid, callingUid, requiredPermission,
11124 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011125 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011126 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 TAG, "Enqueueing parallel broadcast " + r
11128 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011129 boolean replaced = false;
11130 if (replacePending) {
11131 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11132 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011133 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011134 "***** DROPPING PARALLEL: " + intent);
11135 mParallelBroadcasts.set(i, r);
11136 replaced = true;
11137 break;
11138 }
11139 }
11140 }
11141 if (!replaced) {
11142 mParallelBroadcasts.add(r);
11143 scheduleBroadcastsLocked();
11144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 registeredReceivers = null;
11146 NR = 0;
11147 }
11148
11149 // Merge into one list.
11150 int ir = 0;
11151 if (receivers != null) {
11152 // A special case for PACKAGE_ADDED: do not allow the package
11153 // being added to see this broadcast. This prevents them from
11154 // using this as a back door to get run as soon as they are
11155 // installed. Maybe in the future we want to have a special install
11156 // broadcast or such for apps, but we'd like to deliberately make
11157 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011158 String skipPackages[] = null;
11159 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11160 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11161 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
11162 Uri data = intent.getData();
11163 if (data != null) {
11164 String pkgName = data.getSchemeSpecificPart();
11165 if (pkgName != null) {
11166 skipPackages = new String[] { pkgName };
11167 }
11168 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011169 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011170 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011171 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011172 if (skipPackages != null && (skipPackages.length > 0)) {
11173 for (String skipPackage : skipPackages) {
11174 if (skipPackage != null) {
11175 int NT = receivers.size();
11176 for (int it=0; it<NT; it++) {
11177 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11178 if (curt.activityInfo.packageName.equals(skipPackage)) {
11179 receivers.remove(it);
11180 it--;
11181 NT--;
11182 }
11183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 }
11185 }
11186 }
11187
11188 int NT = receivers != null ? receivers.size() : 0;
11189 int it = 0;
11190 ResolveInfo curt = null;
11191 BroadcastFilter curr = null;
11192 while (it < NT && ir < NR) {
11193 if (curt == null) {
11194 curt = (ResolveInfo)receivers.get(it);
11195 }
11196 if (curr == null) {
11197 curr = registeredReceivers.get(ir);
11198 }
11199 if (curr.getPriority() >= curt.priority) {
11200 // Insert this broadcast record into the final list.
11201 receivers.add(it, curr);
11202 ir++;
11203 curr = null;
11204 it++;
11205 NT++;
11206 } else {
11207 // Skip to the next ResolveInfo in the final list.
11208 it++;
11209 curt = null;
11210 }
11211 }
11212 }
11213 while (ir < NR) {
11214 if (receivers == null) {
11215 receivers = new ArrayList();
11216 }
11217 receivers.add(registeredReceivers.get(ir));
11218 ir++;
11219 }
11220
11221 if ((receivers != null && receivers.size() > 0)
11222 || resultTo != null) {
11223 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11224 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011225 receivers, resultTo, resultCode, resultData, map, ordered,
11226 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011227 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 TAG, "Enqueueing ordered broadcast " + r
11229 + ": prev had " + mOrderedBroadcasts.size());
11230 if (DEBUG_BROADCAST) {
11231 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011232 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011234 boolean replaced = false;
11235 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011236 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011237 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011238 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011239 "***** DROPPING ORDERED: " + intent);
11240 mOrderedBroadcasts.set(i, r);
11241 replaced = true;
11242 break;
11243 }
11244 }
11245 }
11246 if (!replaced) {
11247 mOrderedBroadcasts.add(r);
11248 scheduleBroadcastsLocked();
11249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 }
11251
11252 return BROADCAST_SUCCESS;
11253 }
11254
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011255 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 // Refuse possible leaked file descriptors
11257 if (intent != null && intent.hasFileDescriptors() == true) {
11258 throw new IllegalArgumentException("File descriptors passed in Intent");
11259 }
11260
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011261 int flags = intent.getFlags();
11262
11263 if (!mProcessesReady) {
11264 // if the caller really truly claims to know what they're doing, go
11265 // ahead and allow the broadcast without launching any receivers
11266 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11267 intent = new Intent(intent);
11268 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11269 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11270 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11271 + " before boot completion");
11272 throw new IllegalStateException("Cannot broadcast before boot completed");
11273 }
11274 }
11275
11276 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11277 throw new IllegalArgumentException(
11278 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11279 }
11280
11281 return intent;
11282 }
11283
11284 public final int broadcastIntent(IApplicationThread caller,
11285 Intent intent, String resolvedType, IIntentReceiver resultTo,
11286 int resultCode, String resultData, Bundle map,
11287 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011289 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11292 final int callingPid = Binder.getCallingPid();
11293 final int callingUid = Binder.getCallingUid();
11294 final long origId = Binder.clearCallingIdentity();
11295 int res = broadcastIntentLocked(callerApp,
11296 callerApp != null ? callerApp.info.packageName : null,
11297 intent, resolvedType, resultTo,
11298 resultCode, resultData, map, requiredPermission, serialized,
11299 sticky, callingPid, callingUid);
11300 Binder.restoreCallingIdentity(origId);
11301 return res;
11302 }
11303 }
11304
11305 int broadcastIntentInPackage(String packageName, int uid,
11306 Intent intent, String resolvedType, IIntentReceiver resultTo,
11307 int resultCode, String resultData, Bundle map,
11308 String requiredPermission, boolean serialized, boolean sticky) {
11309 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011310 intent = verifyBroadcastLocked(intent);
11311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 final long origId = Binder.clearCallingIdentity();
11313 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11314 resultTo, resultCode, resultData, map, requiredPermission,
11315 serialized, sticky, -1, uid);
11316 Binder.restoreCallingIdentity(origId);
11317 return res;
11318 }
11319 }
11320
11321 public final void unbroadcastIntent(IApplicationThread caller,
11322 Intent intent) {
11323 // Refuse possible leaked file descriptors
11324 if (intent != null && intent.hasFileDescriptors() == true) {
11325 throw new IllegalArgumentException("File descriptors passed in Intent");
11326 }
11327
11328 synchronized(this) {
11329 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11330 != PackageManager.PERMISSION_GRANTED) {
11331 String msg = "Permission Denial: unbroadcastIntent() from pid="
11332 + Binder.getCallingPid()
11333 + ", uid=" + Binder.getCallingUid()
11334 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011335 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011336 throw new SecurityException(msg);
11337 }
11338 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11339 if (list != null) {
11340 int N = list.size();
11341 int i;
11342 for (i=0; i<N; i++) {
11343 if (intent.filterEquals(list.get(i))) {
11344 list.remove(i);
11345 break;
11346 }
11347 }
11348 }
11349 }
11350 }
11351
11352 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11353 String resultData, Bundle resultExtras, boolean resultAbort,
11354 boolean explicit) {
11355 if (mOrderedBroadcasts.size() == 0) {
11356 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011357 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 }
11359 return false;
11360 }
11361 BroadcastRecord r = mOrderedBroadcasts.get(0);
11362 if (r.receiver == null) {
11363 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011364 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011365 }
11366 return false;
11367 }
11368 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011369 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 return false;
11371 }
11372 int state = r.state;
11373 r.state = r.IDLE;
11374 if (state == r.IDLE) {
11375 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011376 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011377 }
11378 }
11379 r.receiver = null;
11380 r.intent.setComponent(null);
11381 if (r.curApp != null) {
11382 r.curApp.curReceiver = null;
11383 }
11384 if (r.curFilter != null) {
11385 r.curFilter.receiverList.curBroadcast = null;
11386 }
11387 r.curFilter = null;
11388 r.curApp = null;
11389 r.curComponent = null;
11390 r.curReceiver = null;
11391 mPendingBroadcast = null;
11392
11393 r.resultCode = resultCode;
11394 r.resultData = resultData;
11395 r.resultExtras = resultExtras;
11396 r.resultAbort = resultAbort;
11397
11398 // We will process the next receiver right now if this is finishing
11399 // an app receiver (which is always asynchronous) or after we have
11400 // come back from calling a receiver.
11401 return state == BroadcastRecord.APP_RECEIVE
11402 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11403 }
11404
11405 public void finishReceiver(IBinder who, int resultCode, String resultData,
11406 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011407 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408
11409 // Refuse possible leaked file descriptors
11410 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11411 throw new IllegalArgumentException("File descriptors passed in Bundle");
11412 }
11413
11414 boolean doNext;
11415
11416 final long origId = Binder.clearCallingIdentity();
11417
11418 synchronized(this) {
11419 doNext = finishReceiverLocked(
11420 who, resultCode, resultData, resultExtras, resultAbort, true);
11421 }
11422
11423 if (doNext) {
11424 processNextBroadcast(false);
11425 }
11426 trimApplications();
11427
11428 Binder.restoreCallingIdentity(origId);
11429 }
11430
Jeff Brown4d94a762010-09-23 11:33:28 -070011431 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 if (r.nextReceiver > 0) {
11433 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11434 if (curReceiver instanceof BroadcastFilter) {
11435 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011436 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 System.identityHashCode(r),
11438 r.intent.getAction(),
11439 r.nextReceiver - 1,
11440 System.identityHashCode(bf));
11441 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011442 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 System.identityHashCode(r),
11444 r.intent.getAction(),
11445 r.nextReceiver - 1,
11446 ((ResolveInfo)curReceiver).toString());
11447 }
11448 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011449 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011450 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011451 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 System.identityHashCode(r),
11453 r.intent.getAction(),
11454 r.nextReceiver,
11455 "NONE");
11456 }
11457 }
11458
Jeff Brown4d94a762010-09-23 11:33:28 -070011459 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11460 if (! mPendingBroadcastTimeoutMessage) {
11461 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11462 mHandler.sendMessageAtTime(msg, timeoutTime);
11463 mPendingBroadcastTimeoutMessage = true;
11464 }
11465 }
11466
11467 private final void cancelBroadcastTimeoutLocked() {
11468 if (mPendingBroadcastTimeoutMessage) {
11469 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11470 mPendingBroadcastTimeoutMessage = false;
11471 }
11472 }
11473
11474 private final void broadcastTimeoutLocked(boolean fromMsg) {
11475 if (fromMsg) {
11476 mPendingBroadcastTimeoutMessage = false;
11477 }
11478
11479 if (mOrderedBroadcasts.size() == 0) {
11480 return;
11481 }
11482
11483 long now = SystemClock.uptimeMillis();
11484 BroadcastRecord r = mOrderedBroadcasts.get(0);
11485 if (fromMsg) {
11486 if (mDidDexOpt) {
11487 // Delay timeouts until dexopt finishes.
11488 mDidDexOpt = false;
11489 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11490 setBroadcastTimeoutLocked(timeoutTime);
11491 return;
11492 }
11493 if (! mProcessesReady) {
11494 // Only process broadcast timeouts if the system is ready. That way
11495 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11496 // to do heavy lifting for system up.
11497 return;
11498 }
11499
11500 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11501 if (timeoutTime > now) {
11502 // We can observe premature timeouts because we do not cancel and reset the
11503 // broadcast timeout message after each receiver finishes. Instead, we set up
11504 // an initial timeout then kick it down the road a little further as needed
11505 // when it expires.
11506 if (DEBUG_BROADCAST) Slog.v(TAG,
11507 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11508 + timeoutTime);
11509 setBroadcastTimeoutLocked(timeoutTime);
11510 return;
11511 }
11512 }
11513
11514 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11515 + ", started " + (now - r.receiverTime) + "ms ago");
11516 r.receiverTime = now;
11517 r.anrCount++;
11518
11519 // Current receiver has passed its expiration date.
11520 if (r.nextReceiver <= 0) {
11521 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11522 return;
11523 }
11524
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011525 ProcessRecord app = null;
11526 String anrMessage = null;
11527
Jeff Brown4d94a762010-09-23 11:33:28 -070011528 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11529 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11530 logBroadcastReceiverDiscardLocked(r);
11531 if (curReceiver instanceof BroadcastFilter) {
11532 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11533 if (bf.receiverList.pid != 0
11534 && bf.receiverList.pid != MY_PID) {
11535 synchronized (this.mPidsSelfLocked) {
11536 app = this.mPidsSelfLocked.get(
11537 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011540 } else {
11541 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011543
Jeff Brown4d94a762010-09-23 11:33:28 -070011544 if (app != null) {
11545 anrMessage = "Broadcast of " + r.intent.toString();
11546 }
11547
11548 if (mPendingBroadcast == r) {
11549 mPendingBroadcast = null;
11550 }
11551
11552 // Move on to the next receiver.
11553 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11554 r.resultExtras, r.resultAbort, true);
11555 scheduleBroadcastsLocked();
11556
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011557 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011558 // Post the ANR to the handler since we do not want to process ANRs while
11559 // potentially holding our lock.
11560 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562 }
11563
11564 private final void processCurBroadcastLocked(BroadcastRecord r,
11565 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011566 if (DEBUG_BROADCAST) Slog.v(TAG,
11567 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 if (app.thread == null) {
11569 throw new RemoteException();
11570 }
11571 r.receiver = app.thread.asBinder();
11572 r.curApp = app;
11573 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011574 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575
11576 // Tell the application to launch this receiver.
11577 r.intent.setComponent(r.curComponent);
11578
11579 boolean started = false;
11580 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011581 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 "Delivering to component " + r.curComponent
11583 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011584 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11586 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011587 if (DEBUG_BROADCAST) Slog.v(TAG,
11588 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 started = true;
11590 } finally {
11591 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011592 if (DEBUG_BROADCAST) Slog.v(TAG,
11593 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 r.receiver = null;
11595 r.curApp = null;
11596 app.curReceiver = null;
11597 }
11598 }
11599
11600 }
11601
Jeff Brown4d94a762010-09-23 11:33:28 -070011602 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011603 Intent intent, int resultCode, String data, Bundle extras,
11604 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011605 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011606 if (app != null && app.thread != null) {
11607 // If we have an app thread, do the call through that so it is
11608 // correctly ordered with other one-way calls.
11609 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011610 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011612 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 }
11614 }
11615
Jeff Brown4d94a762010-09-23 11:33:28 -070011616 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 BroadcastFilter filter, boolean ordered) {
11618 boolean skip = false;
11619 if (filter.requiredPermission != null) {
11620 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011621 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011623 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 + r.intent.toString()
11625 + " from " + r.callerPackage + " (pid="
11626 + r.callingPid + ", uid=" + r.callingUid + ")"
11627 + " requires " + filter.requiredPermission
11628 + " due to registered receiver " + filter);
11629 skip = true;
11630 }
11631 }
11632 if (r.requiredPermission != null) {
11633 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011634 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011636 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 + r.intent.toString()
11638 + " to " + filter.receiverList.app
11639 + " (pid=" + filter.receiverList.pid
11640 + ", uid=" + filter.receiverList.uid + ")"
11641 + " requires " + r.requiredPermission
11642 + " due to sender " + r.callerPackage
11643 + " (uid " + r.callingUid + ")");
11644 skip = true;
11645 }
11646 }
11647
11648 if (!skip) {
11649 // If this is not being sent as an ordered broadcast, then we
11650 // don't want to touch the fields that keep track of the current
11651 // state of ordered broadcasts.
11652 if (ordered) {
11653 r.receiver = filter.receiverList.receiver.asBinder();
11654 r.curFilter = filter;
11655 filter.receiverList.curBroadcast = r;
11656 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011657 if (filter.receiverList.app != null) {
11658 // Bump hosting application to no longer be in background
11659 // scheduling class. Note that we can't do that if there
11660 // isn't an app... but we can only be in that case for
11661 // things that directly call the IActivityManager API, which
11662 // are already core system stuff so don't matter for this.
11663 r.curApp = filter.receiverList.app;
11664 filter.receiverList.app.curReceiver = r;
11665 updateOomAdjLocked();
11666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011667 }
11668 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011669 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011671 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011672 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011674 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011675 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011676 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677 if (ordered) {
11678 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11679 }
11680 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011681 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 if (ordered) {
11683 r.receiver = null;
11684 r.curFilter = null;
11685 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011686 if (filter.receiverList.app != null) {
11687 filter.receiverList.app.curReceiver = null;
11688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 }
11690 }
11691 }
11692 }
11693
Dianne Hackborn12527f92009-11-11 17:39:50 -080011694 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11695 if (r.callingUid < 0) {
11696 // This was from a registerReceiver() call; ignore it.
11697 return;
11698 }
11699 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11700 MAX_BROADCAST_HISTORY-1);
11701 r.finishTime = SystemClock.uptimeMillis();
11702 mBroadcastHistory[0] = r;
11703 }
11704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705 private final void processNextBroadcast(boolean fromMsg) {
11706 synchronized(this) {
11707 BroadcastRecord r;
11708
Joe Onorato8a9b2202010-02-26 18:56:32 -080011709 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011711 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712
11713 updateCpuStats();
11714
11715 if (fromMsg) {
11716 mBroadcastsScheduled = false;
11717 }
11718
11719 // First, deliver any non-serialized broadcasts right away.
11720 while (mParallelBroadcasts.size() > 0) {
11721 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011722 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011723 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011724 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011725 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011726 for (int i=0; i<N; i++) {
11727 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011728 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011729 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011731 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011732 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011733 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011734 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011735 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011736 }
11737
11738 // Now take care of the next serialized one...
11739
11740 // If we are waiting for a process to come up to handle the next
11741 // broadcast, then do nothing at this point. Just in case, we
11742 // check that the process we're waiting for still exists.
11743 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011744 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011745 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011746 + mPendingBroadcast.curApp);
11747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748
11749 boolean isDead;
11750 synchronized (mPidsSelfLocked) {
11751 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11752 }
11753 if (!isDead) {
11754 // It's still alive, so keep waiting
11755 return;
11756 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011757 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011759 mPendingBroadcast.state = BroadcastRecord.IDLE;
11760 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 mPendingBroadcast = null;
11762 }
11763 }
11764
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011765 boolean looped = false;
11766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 do {
11768 if (mOrderedBroadcasts.size() == 0) {
11769 // No more broadcasts pending, so all done!
11770 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011771 if (looped) {
11772 // If we had finished the last ordered broadcast, then
11773 // make sure all processes have correct oom and sched
11774 // adjustments.
11775 updateOomAdjLocked();
11776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011777 return;
11778 }
11779 r = mOrderedBroadcasts.get(0);
11780 boolean forceReceive = false;
11781
11782 // Ensure that even if something goes awry with the timeout
11783 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011784 // and continue to make progress.
11785 //
11786 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011787 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011788 // one time heavy lifting after system upgrades and can take
11789 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011791 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011792 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 if ((numReceivers > 0) &&
11794 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011795 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 + " now=" + now
11797 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011798 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799 + " intent=" + r.intent
11800 + " numReceivers=" + numReceivers
11801 + " nextReceiver=" + r.nextReceiver
11802 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011803 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 forceReceive = true;
11805 r.state = BroadcastRecord.IDLE;
11806 }
11807 }
11808
11809 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011810 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011811 "processNextBroadcast() called when not idle (state="
11812 + r.state + ")");
11813 return;
11814 }
11815
11816 if (r.receivers == null || r.nextReceiver >= numReceivers
11817 || r.resultAbort || forceReceive) {
11818 // No more receivers for this broadcast! Send the final
11819 // result if requested...
11820 if (r.resultTo != null) {
11821 try {
11822 if (DEBUG_BROADCAST) {
11823 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011824 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011825 + " seq=" + seq + " app=" + r.callerApp);
11826 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011827 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011828 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011829 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011830 // Set this to null so that the reference
11831 // (local and remote) isnt kept in the mBroadcastHistory.
11832 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011834 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 }
11836 }
11837
Joe Onorato8a9b2202010-02-26 18:56:32 -080011838 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011839 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840
Joe Onorato8a9b2202010-02-26 18:56:32 -080011841 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011842 + r);
11843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011844 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011845 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 mOrderedBroadcasts.remove(0);
11847 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011848 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011849 continue;
11850 }
11851 } while (r == null);
11852
11853 // Get the next receiver...
11854 int recIdx = r.nextReceiver++;
11855
11856 // Keep track of when this receiver started, and make sure there
11857 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011858 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011860 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861
Joe Onorato8a9b2202010-02-26 18:56:32 -080011862 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011863 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011864 }
11865 if (! mPendingBroadcastTimeoutMessage) {
11866 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011867 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011868 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11869 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 }
11871
11872 Object nextReceiver = r.receivers.get(recIdx);
11873 if (nextReceiver instanceof BroadcastFilter) {
11874 // Simple case: this is a registered receiver who gets
11875 // a direct call.
11876 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011877 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011878 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011880 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 if (r.receiver == null || !r.ordered) {
11882 // The receiver has already finished, so schedule to
11883 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011884 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11885 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886 r.state = BroadcastRecord.IDLE;
11887 scheduleBroadcastsLocked();
11888 }
11889 return;
11890 }
11891
11892 // Hard case: need to instantiate the receiver, possibly
11893 // starting its application process to host it.
11894
11895 ResolveInfo info =
11896 (ResolveInfo)nextReceiver;
11897
11898 boolean skip = false;
11899 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011900 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11901 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011902 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011903 if (!info.activityInfo.exported) {
11904 Slog.w(TAG, "Permission Denial: broadcasting "
11905 + r.intent.toString()
11906 + " from " + r.callerPackage + " (pid=" + r.callingPid
11907 + ", uid=" + r.callingUid + ")"
11908 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11909 + " due to receiver " + info.activityInfo.packageName
11910 + "/" + info.activityInfo.name);
11911 } else {
11912 Slog.w(TAG, "Permission Denial: broadcasting "
11913 + r.intent.toString()
11914 + " from " + r.callerPackage + " (pid=" + r.callingPid
11915 + ", uid=" + r.callingUid + ")"
11916 + " requires " + info.activityInfo.permission
11917 + " due to receiver " + info.activityInfo.packageName
11918 + "/" + info.activityInfo.name);
11919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011920 skip = true;
11921 }
11922 if (r.callingUid != Process.SYSTEM_UID &&
11923 r.requiredPermission != null) {
11924 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011925 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 checkPermission(r.requiredPermission,
11927 info.activityInfo.applicationInfo.packageName);
11928 } catch (RemoteException e) {
11929 perm = PackageManager.PERMISSION_DENIED;
11930 }
11931 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011932 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011933 + r.intent + " to "
11934 + info.activityInfo.applicationInfo.packageName
11935 + " requires " + r.requiredPermission
11936 + " due to sender " + r.callerPackage
11937 + " (uid " + r.callingUid + ")");
11938 skip = true;
11939 }
11940 }
11941 if (r.curApp != null && r.curApp.crashing) {
11942 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011943 if (DEBUG_BROADCAST) Slog.v(TAG,
11944 "Skipping deliver ordered " + r + " to " + r.curApp
11945 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 skip = true;
11947 }
11948
11949 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011950 if (DEBUG_BROADCAST) Slog.v(TAG,
11951 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 r.receiver = null;
11953 r.curFilter = null;
11954 r.state = BroadcastRecord.IDLE;
11955 scheduleBroadcastsLocked();
11956 return;
11957 }
11958
11959 r.state = BroadcastRecord.APP_RECEIVE;
11960 String targetProcess = info.activityInfo.processName;
11961 r.curComponent = new ComponentName(
11962 info.activityInfo.applicationInfo.packageName,
11963 info.activityInfo.name);
11964 r.curReceiver = info.activityInfo;
11965
Dianne Hackborne7f97212011-02-24 14:40:20 -080011966 // Broadcast is being executed, its package can't be stopped.
11967 try {
11968 AppGlobals.getPackageManager().setPackageStoppedState(
11969 r.curComponent.getPackageName(), false);
11970 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011971 } catch (IllegalArgumentException e) {
11972 Slog.w(TAG, "Failed trying to unstop package "
11973 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011974 }
11975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 // Is this receiver's application already running?
11977 ProcessRecord app = getProcessRecordLocked(targetProcess,
11978 info.activityInfo.applicationInfo.uid);
11979 if (app != null && app.thread != null) {
11980 try {
11981 processCurBroadcastLocked(r, app);
11982 return;
11983 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011984 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011985 + r.curComponent, e);
11986 }
11987
11988 // If a dead object exception was thrown -- fall through to
11989 // restart the application.
11990 }
11991
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011992 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011993 if (DEBUG_BROADCAST) Slog.v(TAG,
11994 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011995 if ((r.curApp=startProcessLocked(targetProcess,
11996 info.activityInfo.applicationInfo, true,
11997 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011998 "broadcast", r.curComponent,
11999 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12000 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012001 // Ah, this recipient is unavailable. Finish it if necessary,
12002 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012003 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 + info.activityInfo.applicationInfo.packageName + "/"
12005 + info.activityInfo.applicationInfo.uid + " for broadcast "
12006 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012007 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12009 r.resultExtras, r.resultAbort, true);
12010 scheduleBroadcastsLocked();
12011 r.state = BroadcastRecord.IDLE;
12012 return;
12013 }
12014
12015 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012016 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 }
12018 }
12019
12020 // =========================================================
12021 // INSTRUMENTATION
12022 // =========================================================
12023
12024 public boolean startInstrumentation(ComponentName className,
12025 String profileFile, int flags, Bundle arguments,
12026 IInstrumentationWatcher watcher) {
12027 // Refuse possible leaked file descriptors
12028 if (arguments != null && arguments.hasFileDescriptors()) {
12029 throw new IllegalArgumentException("File descriptors passed in Bundle");
12030 }
12031
12032 synchronized(this) {
12033 InstrumentationInfo ii = null;
12034 ApplicationInfo ai = null;
12035 try {
12036 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012037 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012038 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012039 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012040 } catch (PackageManager.NameNotFoundException e) {
12041 }
12042 if (ii == null) {
12043 reportStartInstrumentationFailure(watcher, className,
12044 "Unable to find instrumentation info for: " + className);
12045 return false;
12046 }
12047 if (ai == null) {
12048 reportStartInstrumentationFailure(watcher, className,
12049 "Unable to find instrumentation target package: " + ii.targetPackage);
12050 return false;
12051 }
12052
12053 int match = mContext.getPackageManager().checkSignatures(
12054 ii.targetPackage, ii.packageName);
12055 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12056 String msg = "Permission Denial: starting instrumentation "
12057 + className + " from pid="
12058 + Binder.getCallingPid()
12059 + ", uid=" + Binder.getCallingPid()
12060 + " not allowed because package " + ii.packageName
12061 + " does not have a signature matching the target "
12062 + ii.targetPackage;
12063 reportStartInstrumentationFailure(watcher, className, msg);
12064 throw new SecurityException(msg);
12065 }
12066
12067 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012068 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012069 ProcessRecord app = addAppLocked(ai);
12070 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012071 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012072 app.instrumentationProfileFile = profileFile;
12073 app.instrumentationArguments = arguments;
12074 app.instrumentationWatcher = watcher;
12075 app.instrumentationResultClass = className;
12076 Binder.restoreCallingIdentity(origId);
12077 }
12078
12079 return true;
12080 }
12081
12082 /**
12083 * Report errors that occur while attempting to start Instrumentation. Always writes the
12084 * error to the logs, but if somebody is watching, send the report there too. This enables
12085 * the "am" command to report errors with more information.
12086 *
12087 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12088 * @param cn The component name of the instrumentation.
12089 * @param report The error report.
12090 */
12091 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12092 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012093 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 try {
12095 if (watcher != null) {
12096 Bundle results = new Bundle();
12097 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12098 results.putString("Error", report);
12099 watcher.instrumentationStatus(cn, -1, results);
12100 }
12101 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012102 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 }
12104 }
12105
12106 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12107 if (app.instrumentationWatcher != null) {
12108 try {
12109 // NOTE: IInstrumentationWatcher *must* be oneway here
12110 app.instrumentationWatcher.instrumentationFinished(
12111 app.instrumentationClass,
12112 resultCode,
12113 results);
12114 } catch (RemoteException e) {
12115 }
12116 }
12117 app.instrumentationWatcher = null;
12118 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012119 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 app.instrumentationProfileFile = null;
12121 app.instrumentationArguments = null;
12122
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012123 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012124 }
12125
12126 public void finishInstrumentation(IApplicationThread target,
12127 int resultCode, Bundle results) {
12128 // Refuse possible leaked file descriptors
12129 if (results != null && results.hasFileDescriptors()) {
12130 throw new IllegalArgumentException("File descriptors passed in Intent");
12131 }
12132
12133 synchronized(this) {
12134 ProcessRecord app = getRecordForAppLocked(target);
12135 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012136 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012137 return;
12138 }
12139 final long origId = Binder.clearCallingIdentity();
12140 finishInstrumentationLocked(app, resultCode, results);
12141 Binder.restoreCallingIdentity(origId);
12142 }
12143 }
12144
12145 // =========================================================
12146 // CONFIGURATION
12147 // =========================================================
12148
12149 public ConfigurationInfo getDeviceConfigurationInfo() {
12150 ConfigurationInfo config = new ConfigurationInfo();
12151 synchronized (this) {
12152 config.reqTouchScreen = mConfiguration.touchscreen;
12153 config.reqKeyboardType = mConfiguration.keyboard;
12154 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012155 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12156 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012157 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12158 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012159 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12160 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012161 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12162 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012163 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012164 }
12165 return config;
12166 }
12167
12168 public Configuration getConfiguration() {
12169 Configuration ci;
12170 synchronized(this) {
12171 ci = new Configuration(mConfiguration);
12172 }
12173 return ci;
12174 }
12175
12176 public void updateConfiguration(Configuration values) {
12177 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12178 "updateConfiguration()");
12179
12180 synchronized(this) {
12181 if (values == null && mWindowManager != null) {
12182 // sentinel: fetch the current configuration from the window manager
12183 values = mWindowManager.computeNewConfiguration();
12184 }
12185
12186 final long origId = Binder.clearCallingIdentity();
12187 updateConfigurationLocked(values, null);
12188 Binder.restoreCallingIdentity(origId);
12189 }
12190 }
12191
12192 /**
12193 * Do either or both things: (1) change the current configuration, and (2)
12194 * make sure the given activity is running with the (now) current
12195 * configuration. Returns true if the activity has been left running, or
12196 * false if <var>starting</var> is being destroyed to match the new
12197 * configuration.
12198 */
12199 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012200 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012201 int changes = 0;
12202
12203 boolean kept = true;
12204
12205 if (values != null) {
12206 Configuration newConfig = new Configuration(mConfiguration);
12207 changes = newConfig.updateFrom(values);
12208 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012209 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012210 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012211 }
12212
Doug Zongker2bec3d42009-12-04 12:52:44 -080012213 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012214
12215 if (values.locale != null) {
12216 saveLocaleLocked(values.locale,
12217 !values.locale.equals(mConfiguration.locale),
12218 values.userSetLocale);
12219 }
12220
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012221 mConfigurationSeq++;
12222 if (mConfigurationSeq <= 0) {
12223 mConfigurationSeq = 1;
12224 }
12225 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012227 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012228
12229 AttributeCache ac = AttributeCache.instance();
12230 if (ac != null) {
12231 ac.updateConfiguration(mConfiguration);
12232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012234 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12235 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12236 msg.obj = new Configuration(mConfiguration);
12237 mHandler.sendMessage(msg);
12238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012240 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12241 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 try {
12243 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012244 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012245 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012246 app.thread.scheduleConfigurationChanged(mConfiguration);
12247 }
12248 } catch (Exception e) {
12249 }
12250 }
12251 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012252 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12253 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12255 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012256 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12257 broadcastIntentLocked(null, null,
12258 new Intent(Intent.ACTION_LOCALE_CHANGED),
12259 null, null, 0, null, null,
12260 null, false, false, MY_PID, Process.SYSTEM_UID);
12261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 }
12263 }
12264
12265 if (changes != 0 && starting == null) {
12266 // If the configuration changed, and the caller is not already
12267 // in the process of starting an activity, then find the top
12268 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012269 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012270 }
12271
12272 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012273 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012274 // And we need to make sure at this point that all other activities
12275 // are made visible with the correct configuration.
12276 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277 }
12278
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012279 if (values != null && mWindowManager != null) {
12280 mWindowManager.setNewConfiguration(mConfiguration);
12281 }
12282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012283 return kept;
12284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012285
12286 /**
12287 * Save the locale. You must be inside a synchronized (this) block.
12288 */
12289 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12290 if(isDiff) {
12291 SystemProperties.set("user.language", l.getLanguage());
12292 SystemProperties.set("user.region", l.getCountry());
12293 }
12294
12295 if(isPersist) {
12296 SystemProperties.set("persist.sys.language", l.getLanguage());
12297 SystemProperties.set("persist.sys.country", l.getCountry());
12298 SystemProperties.set("persist.sys.localevar", l.getVariant());
12299 }
12300 }
12301
12302 // =========================================================
12303 // LIFETIME MANAGEMENT
12304 // =========================================================
12305
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012306 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12307 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012309 // This adjustment has already been computed. If we are calling
12310 // from the top, we may have already computed our adjustment with
12311 // an earlier hidden adjustment that isn't really for us... if
12312 // so, use the new hidden adjustment.
12313 if (!recursed && app.hidden) {
12314 app.curAdj = hiddenAdj;
12315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 return app.curAdj;
12317 }
12318
12319 if (app.thread == null) {
12320 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012321 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012322 return (app.curAdj=EMPTY_APP_ADJ);
12323 }
12324
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012325 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12326 // The max adjustment doesn't allow this app to be anything
12327 // below foreground, so it is not worth doing work for it.
12328 app.adjType = "fixed";
12329 app.adjSeq = mAdjSeq;
12330 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012331 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012332 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12333 return (app.curAdj=app.maxAdj);
12334 }
12335
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012336 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012337 app.adjSource = null;
12338 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012339 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012340 app.empty = false;
12341 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342
The Android Open Source Project4df24232009-03-05 14:34:35 -080012343 // Determine the importance of the process, starting with most
12344 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012346 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012348 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012349 // The last app on the list is the foreground app.
12350 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012351 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012352 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012353 } else if (app.instrumentationClass != null) {
12354 // Don't want to kill running instrumentation.
12355 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012356 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012357 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 } else if (app.curReceiver != null ||
12359 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12360 // An app that is currently receiving a broadcast also
12361 // counts as being in the foreground.
12362 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012363 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012364 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 } else if (app.executingServices.size() > 0) {
12366 // An app that is currently executing a service callback also
12367 // counts as being in the foreground.
12368 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012369 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012370 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 } else if ((N=app.activities.size()) != 0) {
12372 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012373 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012374 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012375 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012376 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012377 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012378 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012379 ActivityRecord r = app.activities.get(j);
12380 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012381 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012382 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012383 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012384 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012385 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012386 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012387 } else if (r.state == ActivityState.PAUSING
12388 || r.state == ActivityState.PAUSED
12389 || r.state == ActivityState.STOPPING) {
12390 adj = PERCEPTIBLE_APP_ADJ;
12391 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 }
12393 }
12394 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012395 // A very not-needed process. If this is lower in the lru list,
12396 // we will push it in to the empty bucket.
12397 app.hidden = true;
12398 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012399 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012400 adj = hiddenAdj;
12401 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012403
12404 if (adj > PERCEPTIBLE_APP_ADJ) {
12405 if (app.foregroundServices) {
12406 // The user is aware of this app, so make it visible.
12407 adj = PERCEPTIBLE_APP_ADJ;
12408 schedGroup = Process.THREAD_GROUP_DEFAULT;
12409 app.adjType = "foreground-service";
12410 } else if (app.forcingToForeground != null) {
12411 // The user is aware of this app, so make it visible.
12412 adj = PERCEPTIBLE_APP_ADJ;
12413 schedGroup = Process.THREAD_GROUP_DEFAULT;
12414 app.adjType = "force-foreground";
12415 app.adjSource = app.forcingToForeground;
12416 }
12417 }
12418
12419 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12420 // We don't want to kill the current heavy-weight process.
12421 adj = HEAVY_WEIGHT_APP_ADJ;
12422 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12423 app.adjType = "heavy";
12424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012426 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12427 // This process is hosting what we currently consider to be the
12428 // home app, so we don't want to let it go into the background.
12429 adj = HOME_APP_ADJ;
12430 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12431 app.adjType = "home";
12432 }
12433
Joe Onorato8a9b2202010-02-26 18:56:32 -080012434 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012435
The Android Open Source Project4df24232009-03-05 14:34:35 -080012436 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012437 // there are applications dependent on our services or providers, but
12438 // this gives us a baseline and makes sure we don't get into an
12439 // infinite recursion.
12440 app.adjSeq = mAdjSeq;
12441 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012442
Christopher Tate6fa95972009-06-05 18:43:55 -070012443 if (mBackupTarget != null && app == mBackupTarget.app) {
12444 // If possible we want to avoid killing apps while they're being backed up
12445 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012446 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012447 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012448 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012449 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012450 }
12451 }
12452
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012453 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12454 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012455 final long now = SystemClock.uptimeMillis();
12456 // This process is more important if the top activity is
12457 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012458 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012460 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012461 if (s.startRequested) {
12462 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12463 // This service has seen some activity within
12464 // recent memory, so we will keep its process ahead
12465 // of the background processes.
12466 if (adj > SECONDARY_SERVER_ADJ) {
12467 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012468 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012469 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012470 }
12471 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012472 // If we have let the service slide into the background
12473 // state, still have some text describing what it is doing
12474 // even though the service no longer has an impact.
12475 if (adj > SECONDARY_SERVER_ADJ) {
12476 app.adjType = "started-bg-services";
12477 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012478 // Don't kill this process because it is doing work; it
12479 // has said it is doing work.
12480 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012481 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012482 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12483 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012484 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 = s.connections.values().iterator();
12486 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012487 ArrayList<ConnectionRecord> clist = kt.next();
12488 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12489 // XXX should compute this based on the max of
12490 // all connected clients.
12491 ConnectionRecord cr = clist.get(i);
12492 if (cr.binding.client == app) {
12493 // Binding to ourself is not interesting.
12494 continue;
12495 }
12496 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12497 ProcessRecord client = cr.binding.client;
12498 int myHiddenAdj = hiddenAdj;
12499 if (myHiddenAdj > client.hiddenAdj) {
12500 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12501 myHiddenAdj = client.hiddenAdj;
12502 } else {
12503 myHiddenAdj = VISIBLE_APP_ADJ;
12504 }
12505 }
12506 int clientAdj = computeOomAdjLocked(
12507 client, myHiddenAdj, TOP_APP, true);
12508 if (adj > clientAdj) {
12509 adj = clientAdj >= VISIBLE_APP_ADJ
12510 ? clientAdj : VISIBLE_APP_ADJ;
12511 if (!client.hidden) {
12512 app.hidden = false;
12513 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012514 if (client.keeping) {
12515 app.keeping = true;
12516 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012517 app.adjType = "service";
12518 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12519 .REASON_SERVICE_IN_USE;
12520 app.adjSource = cr.binding.client;
12521 app.adjTarget = s.name;
12522 }
12523 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12524 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12525 schedGroup = Process.THREAD_GROUP_DEFAULT;
12526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012527 }
12528 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012529 ActivityRecord a = cr.activity;
12530 //if (a != null) {
12531 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12532 //}
12533 if (a != null && adj > FOREGROUND_APP_ADJ &&
12534 (a.state == ActivityState.RESUMED
12535 || a.state == ActivityState.PAUSING)) {
12536 adj = FOREGROUND_APP_ADJ;
12537 schedGroup = Process.THREAD_GROUP_DEFAULT;
12538 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012539 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012540 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12541 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012542 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012543 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 }
12546 }
12547 }
12548 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012549
Dianne Hackborn287952c2010-09-22 22:34:31 -070012550 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012551 // would like to avoid killing it unless it would prevent the current
12552 // application from running. By default we put the process in
12553 // with the rest of the background processes; as we scan through
12554 // its services we may bump it up from there.
12555 if (adj > hiddenAdj) {
12556 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012557 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012558 app.adjType = "bg-services";
12559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 }
12561
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012562 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12563 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012564 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012565 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12566 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012567 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568 if (cpr.clients.size() != 0) {
12569 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12570 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12571 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012572 if (client == app) {
12573 // Being our own client is not interesting.
12574 continue;
12575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 int myHiddenAdj = hiddenAdj;
12577 if (myHiddenAdj > client.hiddenAdj) {
12578 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12579 myHiddenAdj = client.hiddenAdj;
12580 } else {
12581 myHiddenAdj = FOREGROUND_APP_ADJ;
12582 }
12583 }
12584 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012585 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012586 if (adj > clientAdj) {
12587 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012588 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012589 if (!client.hidden) {
12590 app.hidden = false;
12591 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012592 if (client.keeping) {
12593 app.keeping = true;
12594 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012595 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012596 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12597 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012598 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012599 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012601 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12602 schedGroup = Process.THREAD_GROUP_DEFAULT;
12603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 }
12605 }
12606 // If the provider has external (non-framework) process
12607 // dependencies, ensure that its adjustment is at least
12608 // FOREGROUND_APP_ADJ.
12609 if (cpr.externals != 0) {
12610 if (adj > FOREGROUND_APP_ADJ) {
12611 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012612 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012613 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012614 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012615 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012616 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 }
12618 }
12619 }
12620 }
12621
12622 app.curRawAdj = adj;
12623
Joe Onorato8a9b2202010-02-26 18:56:32 -080012624 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012625 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12626 if (adj > app.maxAdj) {
12627 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012628 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012629 schedGroup = Process.THREAD_GROUP_DEFAULT;
12630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012631 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012632 if (adj < HIDDEN_APP_MIN_ADJ) {
12633 app.keeping = true;
12634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635
12636 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012637 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012639 return adj;
12640 }
12641
12642 /**
12643 * Ask a given process to GC right now.
12644 */
12645 final void performAppGcLocked(ProcessRecord app) {
12646 try {
12647 app.lastRequestedGc = SystemClock.uptimeMillis();
12648 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012649 if (app.reportLowMemory) {
12650 app.reportLowMemory = false;
12651 app.thread.scheduleLowMemory();
12652 } else {
12653 app.thread.processInBackground();
12654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012655 }
12656 } catch (Exception e) {
12657 // whatever.
12658 }
12659 }
12660
12661 /**
12662 * Returns true if things are idle enough to perform GCs.
12663 */
Josh Bartel7f208742010-02-25 11:01:44 -060012664 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 return mParallelBroadcasts.size() == 0
12666 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012667 && (mSleeping || (mMainStack.mResumedActivity != null &&
12668 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669 }
12670
12671 /**
12672 * Perform GCs on all processes that are waiting for it, but only
12673 * if things are idle.
12674 */
12675 final void performAppGcsLocked() {
12676 final int N = mProcessesToGc.size();
12677 if (N <= 0) {
12678 return;
12679 }
Josh Bartel7f208742010-02-25 11:01:44 -060012680 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012681 while (mProcessesToGc.size() > 0) {
12682 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012683 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012684 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12685 <= SystemClock.uptimeMillis()) {
12686 // To avoid spamming the system, we will GC processes one
12687 // at a time, waiting a few seconds between each.
12688 performAppGcLocked(proc);
12689 scheduleAppGcsLocked();
12690 return;
12691 } else {
12692 // It hasn't been long enough since we last GCed this
12693 // process... put it in the list to wait for its time.
12694 addProcessToGcListLocked(proc);
12695 break;
12696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 }
12698 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012699
12700 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012701 }
12702 }
12703
12704 /**
12705 * If all looks good, perform GCs on all processes waiting for them.
12706 */
12707 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012708 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012709 performAppGcsLocked();
12710 return;
12711 }
12712 // Still not idle, wait some more.
12713 scheduleAppGcsLocked();
12714 }
12715
12716 /**
12717 * Schedule the execution of all pending app GCs.
12718 */
12719 final void scheduleAppGcsLocked() {
12720 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012721
12722 if (mProcessesToGc.size() > 0) {
12723 // Schedule a GC for the time to the next process.
12724 ProcessRecord proc = mProcessesToGc.get(0);
12725 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12726
12727 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12728 long now = SystemClock.uptimeMillis();
12729 if (when < (now+GC_TIMEOUT)) {
12730 when = now + GC_TIMEOUT;
12731 }
12732 mHandler.sendMessageAtTime(msg, when);
12733 }
12734 }
12735
12736 /**
12737 * Add a process to the array of processes waiting to be GCed. Keeps the
12738 * list in sorted order by the last GC time. The process can't already be
12739 * on the list.
12740 */
12741 final void addProcessToGcListLocked(ProcessRecord proc) {
12742 boolean added = false;
12743 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12744 if (mProcessesToGc.get(i).lastRequestedGc <
12745 proc.lastRequestedGc) {
12746 added = true;
12747 mProcessesToGc.add(i+1, proc);
12748 break;
12749 }
12750 }
12751 if (!added) {
12752 mProcessesToGc.add(0, proc);
12753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012754 }
12755
12756 /**
12757 * Set up to ask a process to GC itself. This will either do it
12758 * immediately, or put it on the list of processes to gc the next
12759 * time things are idle.
12760 */
12761 final void scheduleAppGcLocked(ProcessRecord app) {
12762 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012763 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 return;
12765 }
12766 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012767 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012768 scheduleAppGcsLocked();
12769 }
12770 }
12771
Dianne Hackborn287952c2010-09-22 22:34:31 -070012772 final void checkExcessivePowerUsageLocked(boolean doKills) {
12773 updateCpuStatsNow();
12774
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012775 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012776 boolean doWakeKills = doKills;
12777 boolean doCpuKills = doKills;
12778 if (mLastPowerCheckRealtime == 0) {
12779 doWakeKills = false;
12780 }
12781 if (mLastPowerCheckUptime == 0) {
12782 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012783 }
12784 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012785 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012786 }
12787 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012788 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12789 final long curUptime = SystemClock.uptimeMillis();
12790 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12791 mLastPowerCheckRealtime = curRealtime;
12792 mLastPowerCheckUptime = curUptime;
12793 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12794 doWakeKills = false;
12795 }
12796 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12797 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012798 }
12799 int i = mLruProcesses.size();
12800 while (i > 0) {
12801 i--;
12802 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012803 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012804 long wtime;
12805 synchronized (stats) {
12806 wtime = stats.getProcessWakeTime(app.info.uid,
12807 app.pid, curRealtime);
12808 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012809 long wtimeUsed = wtime - app.lastWakeTime;
12810 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12811 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012812 StringBuilder sb = new StringBuilder(128);
12813 sb.append("Wake for ");
12814 app.toShortString(sb);
12815 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012816 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012817 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012818 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012819 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012820 sb.append((wtimeUsed*100)/realtimeSince);
12821 sb.append("%)");
12822 Slog.i(TAG, sb.toString());
12823 sb.setLength(0);
12824 sb.append("CPU for ");
12825 app.toShortString(sb);
12826 sb.append(": over ");
12827 TimeUtils.formatDuration(uptimeSince, sb);
12828 sb.append(" used ");
12829 TimeUtils.formatDuration(cputimeUsed, sb);
12830 sb.append(" (");
12831 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012832 sb.append("%)");
12833 Slog.i(TAG, sb.toString());
12834 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012835 // If a process has held a wake lock for more
12836 // than 50% of the time during this period,
12837 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012838 if (doWakeKills && realtimeSince > 0
12839 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12840 synchronized (stats) {
12841 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12842 realtimeSince, wtimeUsed);
12843 }
12844 Slog.w(TAG, "Excessive wake lock in " + app.processName
12845 + " (pid " + app.pid + "): held " + wtimeUsed
12846 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012847 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12848 app.processName, app.setAdj, "excessive wake lock");
12849 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012850 } else if (doCpuKills && uptimeSince > 0
12851 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12852 synchronized (stats) {
12853 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12854 uptimeSince, cputimeUsed);
12855 }
12856 Slog.w(TAG, "Excessive CPU in " + app.processName
12857 + " (pid " + app.pid + "): used " + cputimeUsed
12858 + " during " + uptimeSince);
12859 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12860 app.processName, app.setAdj, "excessive cpu");
12861 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012862 } else {
12863 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012864 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012865 }
12866 }
12867 }
12868 }
12869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 private final boolean updateOomAdjLocked(
12871 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12872 app.hiddenAdj = hiddenAdj;
12873
12874 if (app.thread == null) {
12875 return true;
12876 }
12877
Dianne Hackborn287952c2010-09-22 22:34:31 -070012878 final boolean wasKeeping = app.keeping;
12879
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012880 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012882 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012883 if (app.curRawAdj != app.setRawAdj) {
12884 if (app.curRawAdj > FOREGROUND_APP_ADJ
12885 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12886 // If this app is transitioning from foreground to
12887 // non-foreground, have it do a gc.
12888 scheduleAppGcLocked(app);
12889 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12890 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12891 // Likewise do a gc when an app is moving in to the
12892 // background (such as a service stopping).
12893 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012894 }
12895
12896 if (wasKeeping && !app.keeping) {
12897 // This app is no longer something we want to keep. Note
12898 // its current wake lock time to later know to kill it if
12899 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012900 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12901 synchronized (stats) {
12902 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12903 app.pid, SystemClock.elapsedRealtime());
12904 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012905 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012908 app.setRawAdj = app.curRawAdj;
12909 }
12910 if (adj != app.setAdj) {
12911 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012912 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012913 TAG, "Set app " + app.processName +
12914 " oom adj to " + adj);
12915 app.setAdj = adj;
12916 } else {
12917 return false;
12918 }
12919 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012920 if (app.setSchedGroup != app.curSchedGroup) {
12921 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012922 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012923 "Setting process group of " + app.processName
12924 + " to " + app.curSchedGroup);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012925 if (app.waitingToKill != null &&
12926 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
12927 Slog.i(TAG, "Killing " + app + ": " + app.waitingToKill);
12928 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12929 app.processName, app.setAdj, app.waitingToKill);
12930 Process.killProcessQuiet(app.pid);
12931 } else {
12932 if (true) {
12933 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012934 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070012935 Process.setProcessGroup(app.pid, app.curSchedGroup);
12936 } catch (Exception e) {
12937 Slog.w(TAG, "Failed setting process group of " + app.pid
12938 + " to " + app.curSchedGroup);
12939 e.printStackTrace();
12940 } finally {
12941 Binder.restoreCallingIdentity(oldId);
12942 }
12943 }
12944 if (false) {
12945 if (app.thread != null) {
12946 try {
12947 app.thread.setSchedulingGroup(app.curSchedGroup);
12948 } catch (RemoteException e) {
12949 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012950 }
12951 }
12952 }
12953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012954 }
12955
12956 return true;
12957 }
12958
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012959 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012960 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012961 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012962 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012963 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012964 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012965 }
12966 }
12967 return resumedActivity;
12968 }
12969
12970 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012971 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012972 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12973 int curAdj = app.curAdj;
12974 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12975 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12976
12977 mAdjSeq++;
12978
12979 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12980 if (res) {
12981 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12982 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12983 if (nowHidden != wasHidden) {
12984 // Changed to/from hidden state, so apps after it in the LRU
12985 // list may also be changed.
12986 updateOomAdjLocked();
12987 }
12988 }
12989 return res;
12990 }
12991
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012992 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012993 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012994 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012995 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12996
12997 if (false) {
12998 RuntimeException e = new RuntimeException();
12999 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013000 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013001 }
13002
13003 mAdjSeq++;
13004
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013005 // Let's determine how many processes we have running vs.
13006 // how many slots we have for background processes; we may want
13007 // to put multiple processes in a slot of there are enough of
13008 // them.
13009 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13010 int factor = (mLruProcesses.size()-4)/numSlots;
13011 if (factor < 1) factor = 1;
13012 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013013 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013015 // First try updating the OOM adjustment for each of the
13016 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013017 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013018 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13019 while (i > 0) {
13020 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013021 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013022 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013023 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013024 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013025 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013026 step++;
13027 if (step >= factor) {
13028 step = 0;
13029 curHiddenAdj++;
13030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013031 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013032 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070013033 if (!app.killedBackground) {
13034 numHidden++;
13035 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070013036 Slog.i(TAG, "No longer want " + app.processName
13037 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013038 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13039 app.processName, app.setAdj, "too many background");
13040 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070013041 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013042 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013043 }
13044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013045 } else {
13046 didOomAdj = false;
13047 }
13048 }
13049
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013050 // If we return false, we will fall back on killing processes to
13051 // have a fixed limit. Do this if a limit has been requested; else
13052 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013053 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13054 }
13055
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013056 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013057 synchronized (this) {
13058 int i;
13059
13060 // First remove any unused application processes whose package
13061 // has been removed.
13062 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13063 final ProcessRecord app = mRemovedProcesses.get(i);
13064 if (app.activities.size() == 0
13065 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013066 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013067 TAG, "Exiting empty application process "
13068 + app.processName + " ("
13069 + (app.thread != null ? app.thread.asBinder() : null)
13070 + ")\n");
13071 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013072 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13073 app.processName, app.setAdj, "empty");
13074 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013075 } else {
13076 try {
13077 app.thread.scheduleExit();
13078 } catch (Exception e) {
13079 // Ignore exceptions.
13080 }
13081 }
13082 cleanUpApplicationRecordLocked(app, false, -1);
13083 mRemovedProcesses.remove(i);
13084
13085 if (app.persistent) {
13086 if (app.persistent) {
13087 addAppLocked(app.info);
13088 }
13089 }
13090 }
13091 }
13092
13093 // Now try updating the OOM adjustment for each of the
13094 // application processes based on their current state.
13095 // If the setOomAdj() API is not supported, then go with our
13096 // back-up plan...
13097 if (!updateOomAdjLocked()) {
13098
13099 // Count how many processes are running services.
13100 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013101 for (i=mLruProcesses.size()-1; i>=0; i--) {
13102 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013103
13104 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013105 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013106 // Don't count processes holding services against our
13107 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013108 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 TAG, "Not trimming app " + app + " with services: "
13110 + app.services);
13111 numServiceProcs++;
13112 }
13113 }
13114
13115 int curMaxProcs = mProcessLimit;
13116 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13117 if (mAlwaysFinishActivities) {
13118 curMaxProcs = 1;
13119 }
13120 curMaxProcs += numServiceProcs;
13121
13122 // Quit as many processes as we can to get down to the desired
13123 // process count. First remove any processes that no longer
13124 // have activites running in them.
13125 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013126 i<mLruProcesses.size()
13127 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013128 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013129 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013130 // Quit an application only if it is not currently
13131 // running any activities.
13132 if (!app.persistent && app.activities.size() == 0
13133 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013134 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013135 TAG, "Exiting empty application process "
13136 + app.processName + " ("
13137 + (app.thread != null ? app.thread.asBinder() : null)
13138 + ")\n");
13139 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013140 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13141 app.processName, app.setAdj, "empty");
13142 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013143 } else {
13144 try {
13145 app.thread.scheduleExit();
13146 } catch (Exception e) {
13147 // Ignore exceptions.
13148 }
13149 }
13150 // todo: For now we assume the application is not buggy
13151 // or evil, and will quit as a result of our request.
13152 // Eventually we need to drive this off of the death
13153 // notification, and kill the process if it takes too long.
13154 cleanUpApplicationRecordLocked(app, false, i);
13155 i--;
13156 }
13157 }
13158
13159 // If we still have too many processes, now from the least
13160 // recently used process we start finishing activities.
Joe Onorato43a17652011-04-06 19:22:23 -070013161 if (false) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013162 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013163 " of " + curMaxProcs + " processes");
13164 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013165 i<mLruProcesses.size()
13166 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013167 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013168 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013169 // Quit the application only if we have a state saved for
13170 // all of its activities.
13171 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013172 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013173 int NUMA = app.activities.size();
13174 int j;
Joe Onorato43a17652011-04-06 19:22:23 -070013175 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013176 TAG, "Looking to quit " + app.processName);
13177 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013178 ActivityRecord r = app.activities.get(j);
Joe Onorato43a17652011-04-06 19:22:23 -070013179 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013180 TAG, " " + r.intent.getComponent().flattenToShortString()
13181 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13182 canQuit = (r.haveState || !r.stateNotNeeded)
13183 && !r.visible && r.stopped;
13184 }
13185 if (canQuit) {
13186 // Finish all of the activities, and then the app itself.
13187 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013188 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013189 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013190 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013191 }
13192 r.resultTo = null;
13193 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013194 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013195 + app.processName + " ("
13196 + (app.thread != null ? app.thread.asBinder() : null)
13197 + ")\n");
13198 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013199 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13200 app.processName, app.setAdj, "old background");
13201 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013202 } else {
13203 try {
13204 app.thread.scheduleExit();
13205 } catch (Exception e) {
13206 // Ignore exceptions.
13207 }
13208 }
13209 // todo: For now we assume the application is not buggy
13210 // or evil, and will quit as a result of our request.
13211 // Eventually we need to drive this off of the death
13212 // notification, and kill the process if it takes too long.
13213 cleanUpApplicationRecordLocked(app, false, i);
13214 i--;
13215 //dump();
13216 }
13217 }
13218
13219 }
13220
13221 int curMaxActivities = MAX_ACTIVITIES;
13222 if (mAlwaysFinishActivities) {
13223 curMaxActivities = 1;
13224 }
13225
13226 // Finally, if there are too many activities now running, try to
13227 // finish as many as we can to get back down to the limit.
13228 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013229 i<mMainStack.mLRUActivities.size()
13230 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013231 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013232 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013233 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013234
13235 // We can finish this one if we have its icicle saved and
13236 // it is not persistent.
13237 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013238 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013239 final int origSize = mMainStack.mLRUActivities.size();
13240 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013241
13242 // This will remove it from the LRU list, so keep
13243 // our index at the same value. Note that this check to
13244 // see if the size changes is just paranoia -- if
13245 // something unexpected happens, we don't want to end up
13246 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013247 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 i--;
13249 }
13250 }
13251 }
13252 }
13253 }
13254
13255 /** This method sends the specified signal to each of the persistent apps */
13256 public void signalPersistentProcesses(int sig) throws RemoteException {
13257 if (sig != Process.SIGNAL_USR1) {
13258 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13259 }
13260
13261 synchronized (this) {
13262 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13263 != PackageManager.PERMISSION_GRANTED) {
13264 throw new SecurityException("Requires permission "
13265 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13266 }
13267
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013268 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13269 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013270 if (r.thread != null && r.persistent) {
13271 Process.sendSignal(r.pid, sig);
13272 }
13273 }
13274 }
13275 }
13276
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013277 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013278 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013279
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013280 try {
13281 synchronized (this) {
13282 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13283 // its own permission.
13284 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13285 != PackageManager.PERMISSION_GRANTED) {
13286 throw new SecurityException("Requires permission "
13287 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013288 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013289
13290 if (start && fd == null) {
13291 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013292 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013293
13294 ProcessRecord proc = null;
13295 try {
13296 int pid = Integer.parseInt(process);
13297 synchronized (mPidsSelfLocked) {
13298 proc = mPidsSelfLocked.get(pid);
13299 }
13300 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013301 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013302
13303 if (proc == null) {
13304 HashMap<String, SparseArray<ProcessRecord>> all
13305 = mProcessNames.getMap();
13306 SparseArray<ProcessRecord> procs = all.get(process);
13307 if (procs != null && procs.size() > 0) {
13308 proc = procs.valueAt(0);
13309 }
13310 }
13311
13312 if (proc == null || proc.thread == null) {
13313 throw new IllegalArgumentException("Unknown process: " + process);
13314 }
13315
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013316 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13317 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013318 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13319 throw new SecurityException("Process not debuggable: " + proc);
13320 }
13321 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013322
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013323 proc.thread.profilerControl(start, path, fd);
13324 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013325 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013326 }
13327 } catch (RemoteException e) {
13328 throw new IllegalStateException("Process disappeared");
13329 } finally {
13330 if (fd != null) {
13331 try {
13332 fd.close();
13333 } catch (IOException e) {
13334 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013335 }
13336 }
13337 }
Andy McFadden824c5102010-07-09 16:26:57 -070013338
13339 public boolean dumpHeap(String process, boolean managed,
13340 String path, ParcelFileDescriptor fd) throws RemoteException {
13341
13342 try {
13343 synchronized (this) {
13344 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13345 // its own permission (same as profileControl).
13346 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13347 != PackageManager.PERMISSION_GRANTED) {
13348 throw new SecurityException("Requires permission "
13349 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13350 }
13351
13352 if (fd == null) {
13353 throw new IllegalArgumentException("null fd");
13354 }
13355
13356 ProcessRecord proc = null;
13357 try {
13358 int pid = Integer.parseInt(process);
13359 synchronized (mPidsSelfLocked) {
13360 proc = mPidsSelfLocked.get(pid);
13361 }
13362 } catch (NumberFormatException e) {
13363 }
13364
13365 if (proc == null) {
13366 HashMap<String, SparseArray<ProcessRecord>> all
13367 = mProcessNames.getMap();
13368 SparseArray<ProcessRecord> procs = all.get(process);
13369 if (procs != null && procs.size() > 0) {
13370 proc = procs.valueAt(0);
13371 }
13372 }
13373
13374 if (proc == null || proc.thread == null) {
13375 throw new IllegalArgumentException("Unknown process: " + process);
13376 }
13377
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013378 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13379 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013380 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13381 throw new SecurityException("Process not debuggable: " + proc);
13382 }
13383 }
13384
13385 proc.thread.dumpHeap(managed, path, fd);
13386 fd = null;
13387 return true;
13388 }
13389 } catch (RemoteException e) {
13390 throw new IllegalStateException("Process disappeared");
13391 } finally {
13392 if (fd != null) {
13393 try {
13394 fd.close();
13395 } catch (IOException e) {
13396 }
13397 }
13398 }
13399 }
13400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13402 public void monitor() {
13403 synchronized (this) { }
13404 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013405
13406 public void onCoreSettingsChange(Bundle settings) {
13407 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13408 ProcessRecord processRecord = mLruProcesses.get(i);
13409 try {
13410 if (processRecord.thread != null) {
13411 processRecord.thread.setCoreSettings(settings);
13412 }
13413 } catch (RemoteException re) {
13414 /* ignore */
13415 }
13416 }
13417 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013418
13419 // Multi-user methods
13420
13421 public boolean switchUser(int userid) {
13422 // TODO
13423 return true;
13424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013425}