blob: e5d102519f74007ba3fb5867cb824a4b90a5b1ba [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;
20import com.android.internal.app.HeavyWeightSwitcherActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
25import com.android.server.ProcessStats;
26import com.android.server.SystemServer;
27import com.android.server.Watchdog;
28import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070029import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Dianne Hackborndd71fc82009-12-16 19:24:32 -080031import dalvik.system.Zygote;
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.app.Activity;
34import android.app.ActivityManager;
35import android.app.ActivityManagerNative;
36import android.app.ActivityThread;
37import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070038import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020039import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070041import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080042import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.app.IActivityWatcher;
44import android.app.IApplicationThread;
45import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070046import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.app.IServiceConnection;
48import android.app.IThumbnailReceiver;
49import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070050import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070051import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.app.PendingIntent;
53import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070054import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080055import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020056import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080057import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.ComponentName;
59import android.content.ContentResolver;
60import android.content.Context;
61import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.content.res.Configuration;
80import android.graphics.Bitmap;
81import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
97import android.os.PowerManager;
98import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070099import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.RemoteException;
101import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700102import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.os.SystemClock;
104import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.Config;
107import 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;
112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.io.File;
119import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200121import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800122import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.PrintWriter;
124import java.lang.IllegalStateException;
125import java.lang.ref.WeakReference;
126import java.util.ArrayList;
127import java.util.HashMap;
128import java.util.HashSet;
129import java.util.Iterator;
130import java.util.List;
131import java.util.Locale;
132import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700133import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700134import java.util.concurrent.atomic.AtomicBoolean;
135import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136
137public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
138 static final String TAG = "ActivityManager";
139 static final boolean DEBUG = false;
140 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
141 static final boolean DEBUG_SWITCH = localLOGV || false;
142 static final boolean DEBUG_TASKS = localLOGV || false;
143 static final boolean DEBUG_PAUSE = localLOGV || false;
144 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
145 static final boolean DEBUG_TRANSITION = localLOGV || false;
146 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700147 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final boolean DEBUG_SERVICE = localLOGV || false;
149 static final boolean DEBUG_VISBILITY = localLOGV || false;
150 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700151 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800152 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700154 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700155 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700156 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean VALIDATE_TOKENS = false;
158 static final boolean SHOW_ACTIVITY_START_TIME = true;
159
160 // Control over CPU and battery monitoring.
161 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
162 static final boolean MONITOR_CPU_USAGE = true;
163 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
164 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
165 static final boolean MONITOR_THREAD_CPU_USAGE = false;
166
Dianne Hackborn1655be42009-05-08 14:29:01 -0700167 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700168 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 private static final String SYSTEM_SECURE = "ro.secure";
171
172 // This is the maximum number of application processes we would like
173 // to have running. Due to the asynchronous nature of things, we can
174 // temporarily go beyond this limit.
175 static final int MAX_PROCESSES = 2;
176
177 // Set to false to leave processes running indefinitely, relying on
178 // the kernel killing them as resources are required.
179 static final boolean ENFORCE_PROCESS_LIMIT = false;
180
181 // This is the maximum number of activities that we would like to have
182 // running at a given time.
183 static final int MAX_ACTIVITIES = 20;
184
185 // Maximum number of recent tasks that we can remember.
186 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700187
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700188 // Amount of time after a call to stopAppSwitches() during which we will
189 // prevent further untrusted switches from happening.
190 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191
192 // How long we wait for a launched process to attach to the activity manager
193 // before we decide it's never going to come up for real.
194 static final int PROC_START_TIMEOUT = 10*1000;
195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 // How long to wait after going idle before forcing apps to GC.
197 static final int GC_TIMEOUT = 5*1000;
198
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700199 // The minimum amount of time between successive GC requests for a process.
200 static final int GC_MIN_INTERVAL = 60*1000;
201
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700202 // The rate at which we check for apps using excessive wake locks -- 15 mins.
203 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 // How long we allow a receiver to run before giving up on it.
206 static final int BROADCAST_TIMEOUT = 10*1000;
207
208 // How long we wait for a service to finish executing.
209 static final int SERVICE_TIMEOUT = 20*1000;
210
211 // How long a service needs to be running until restarting its process
212 // is no longer considered to be a relaunch of the service.
213 static final int SERVICE_RESTART_DURATION = 5*1000;
214
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700215 // How long a service needs to be running until it will start back at
216 // SERVICE_RESTART_DURATION after being killed.
217 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
218
219 // Multiplying factor to increase restart duration time by, for each time
220 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
221 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
222
223 // The minimum amount of time between restarting services that we allow.
224 // That is, when multiple services are restarting, we won't allow each
225 // to restart less than this amount of time from the last one.
226 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 // Maximum amount of time for there to be no activity on a service before
229 // we consider it non-essential and allow its process to go on the
230 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700231 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
233 // How long we wait until we timeout on key dispatching.
234 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
235
236 // The minimum time we allow between crashes, for us to consider this
237 // application to be bad and stop and its services and reject broadcasts.
238 static final int MIN_CRASH_INTERVAL = 60*1000;
239
240 // How long we wait until we timeout on key dispatching during instrumentation.
241 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
242
243 // OOM adjustments for processes in various states:
244
245 // This is a process without anything currently running in it. Definitely
246 // the first to go! Value set in system/rootdir/init.rc on startup.
247 // This value is initalized in the constructor, careful when refering to
248 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800249 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250
251 // This is a process only hosting activities that are not visible,
252 // so it can be killed without any disruption. Value set in
253 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800254 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 static int HIDDEN_APP_MIN_ADJ;
256
The Android Open Source Project4df24232009-03-05 14:34:35 -0800257 // This is a process holding the home application -- we want to try
258 // avoiding killing it, even if it would normally be in the background,
259 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800260 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800261
Christopher Tate6fa95972009-06-05 18:43:55 -0700262 // This is a process currently hosting a backup operation. Killing it
263 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 // This is a process holding a secondary server -- killing it will not
267 // have much of an impact as far as the user is concerned. Value set in
268 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700271 // This is a process with a heavy-weight application. It is in the
272 // background, but we want to try to avoid killing it. Value set in
273 // system/rootdir/init.rc on startup.
274 static final int HEAVY_WEIGHT_APP_ADJ;
275
276 // This is a process only hosting components that are perceptible to the
277 // user, and we really want to avoid killing them, but they are not
278 // immediately visible. An example is background music playback. Value set in
279 // system/rootdir/init.rc on startup.
280 static final int PERCEPTIBLE_APP_ADJ;
281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 // This is a process only hosting activities that are visible to the
283 // user, so we'd prefer they don't disappear. Value set in
284 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // This is the process running the current foreground app. We'd really
288 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is a process running a core server, such as telephony. Definitely
292 // don't want to kill it, but doing so is not completely fatal.
293 static final int CORE_SERVER_ADJ = -12;
294
295 // The system process runs at the default adjustment.
296 static final int SYSTEM_ADJ = -16;
297
298 // Memory pages are 4K.
299 static final int PAGE_SIZE = 4*1024;
300
301 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800302 static final int EMPTY_APP_MEM;
303 static final int HIDDEN_APP_MEM;
304 static final int HOME_APP_MEM;
305 static final int BACKUP_APP_MEM;
306 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700307 static final int HEAVY_WEIGHT_APP_MEM;
308 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800309 static final int VISIBLE_APP_MEM;
310 static final int FOREGROUND_APP_MEM;
311
312 // The minimum number of hidden apps we want to be able to keep around,
313 // without empty apps being able to push them out of memory.
314 static final int MIN_HIDDEN_APPS = 2;
315
Dianne Hackborn8633e682010-04-22 16:03:41 -0700316 // The maximum number of hidden processes we will keep around before
317 // killing them; this is just a control to not let us go too crazy with
318 // keeping around processes on devices with large amounts of RAM.
319 static final int MAX_HIDDEN_APPS = 15;
320
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800321 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700322 // been idle for less than 15 seconds.
323 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800324
325 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700326 // been idle for less than 120 seconds.
327 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800328
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700329 static int getIntProp(String name, boolean allowZero) {
330 String str = SystemProperties.get(name);
331 if (str == null) {
332 throw new IllegalArgumentException("Property not defined: " + name);
333 }
334 int val = Integer.valueOf(str);
335 if (val == 0 && !allowZero) {
336 throw new IllegalArgumentException("Property must not be zero: " + name);
337 }
338 return val;
339 }
340
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341 static {
342 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700343 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
344 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
345 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
346 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
347 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
348 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
349 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
350 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
351 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
352 // These days we use the last empty slot for hidden apps as well.
353 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
354 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
355 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
356 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
357 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
358 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
359 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
360 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
361 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
362 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
Dan Egnor42471dd2010-01-07 17:25:22 -0800365 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366
367 static final String[] EMPTY_STRING_ARRAY = new String[0];
368
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700369 public ActivityStack mMainStack;
370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700372 * Description of a request to start a new activity, which has been held
373 * due to app switches being disabled.
374 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700375 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700376 ActivityRecord r;
377 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700378 Uri[] grantedUriPermissions;
379 int grantedMode;
380 boolean onlyIfNeeded;
381 }
382
383 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
384 = new ArrayList<PendingActivityLaunch>();
385
386 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 * List of all active broadcasts that are to be executed immediately
388 * (without waiting for another broadcast to finish). Currently this only
389 * contains broadcasts to registered receivers, to avoid spinning up
390 * a bunch of processes to execute IntentReceiver components.
391 */
392 final ArrayList<BroadcastRecord> mParallelBroadcasts
393 = new ArrayList<BroadcastRecord>();
394
395 /**
396 * List of all active broadcasts that are to be executed one at a time.
397 * The object at the top of the list is the currently activity broadcasts;
398 * those after it are waiting for the top to finish..
399 */
400 final ArrayList<BroadcastRecord> mOrderedBroadcasts
401 = new ArrayList<BroadcastRecord>();
402
403 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800404 * Historical data of past broadcasts, for debugging.
405 */
406 static final int MAX_BROADCAST_HISTORY = 100;
407 final BroadcastRecord[] mBroadcastHistory
408 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
409
410 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 * Set when we current have a BROADCAST_INTENT_MSG in flight.
412 */
413 boolean mBroadcastsScheduled = false;
414
415 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 * Activity we have told the window manager to have key focus.
417 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700418 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700419 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 * List of intents that were used to start the most recent tasks.
421 */
422 final ArrayList<TaskRecord> mRecentTasks
423 = new ArrayList<TaskRecord>();
424
425 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 * All of the applications we currently have running organized by name.
427 * The keys are strings of the application package name (as
428 * returned by the package manager), and the keys are ApplicationRecord
429 * objects.
430 */
431 final ProcessMap<ProcessRecord> mProcessNames
432 = new ProcessMap<ProcessRecord>();
433
434 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700435 * The currently running heavy-weight process, if any.
436 */
437 ProcessRecord mHeavyWeightProcess = null;
438
439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * The last time that various processes have crashed.
441 */
442 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
443
444 /**
445 * Set of applications that we consider to be bad, and will reject
446 * incoming broadcasts from (which the user has no control over).
447 * Processes are added to this set when they have crashed twice within
448 * a minimum amount of time; they are removed from it when they are
449 * later restarted (hopefully due to some user action). The value is the
450 * time it was added to the list.
451 */
452 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
453
454 /**
455 * All of the processes we currently have running organized by pid.
456 * The keys are the pid running the application.
457 *
458 * <p>NOTE: This object is protected by its own lock, NOT the global
459 * activity manager lock!
460 */
461 final SparseArray<ProcessRecord> mPidsSelfLocked
462 = new SparseArray<ProcessRecord>();
463
464 /**
465 * All of the processes that have been forced to be foreground. The key
466 * is the pid of the caller who requested it (we hold a death
467 * link on it).
468 */
469 abstract class ForegroundToken implements IBinder.DeathRecipient {
470 int pid;
471 IBinder token;
472 }
473 final SparseArray<ForegroundToken> mForegroundProcesses
474 = new SparseArray<ForegroundToken>();
475
476 /**
477 * List of records for processes that someone had tried to start before the
478 * system was ready. We don't start them at that point, but ensure they
479 * are started by the time booting is complete.
480 */
481 final ArrayList<ProcessRecord> mProcessesOnHold
482 = new ArrayList<ProcessRecord>();
483
484 /**
485 * List of records for processes that we have started and are waiting
486 * for them to call back. This is really only needed when running in
487 * single processes mode, in which case we do not have a unique pid for
488 * each process.
489 */
490 final ArrayList<ProcessRecord> mStartingProcesses
491 = new ArrayList<ProcessRecord>();
492
493 /**
494 * List of persistent applications that are in the process
495 * of being started.
496 */
497 final ArrayList<ProcessRecord> mPersistentStartingProcesses
498 = new ArrayList<ProcessRecord>();
499
500 /**
501 * Processes that are being forcibly torn down.
502 */
503 final ArrayList<ProcessRecord> mRemovedProcesses
504 = new ArrayList<ProcessRecord>();
505
506 /**
507 * List of running applications, sorted by recent usage.
508 * The first entry in the list is the least recently used.
509 * It contains ApplicationRecord objects. This list does NOT include
510 * any persistent application records (since we never want to exit them).
511 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800512 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 = new ArrayList<ProcessRecord>();
514
515 /**
516 * List of processes that should gc as soon as things are idle.
517 */
518 final ArrayList<ProcessRecord> mProcessesToGc
519 = new ArrayList<ProcessRecord>();
520
521 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800522 * This is the process holding what we currently consider to be
523 * the "home" activity.
524 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700525 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800526
527 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 * Set of PendingResultRecord objects that are currently active.
529 */
530 final HashSet mPendingResultRecords = new HashSet();
531
532 /**
533 * Set of IntentSenderRecord objects that are currently active.
534 */
535 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
536 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
537
538 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700539 * Fingerprints (String.hashCode()) of stack traces that we've
540 * already logged DropBox entries for. Guarded by itself. If
541 * something (rogue user app) forces this over
542 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
543 */
544 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
545 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
546
547 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700548 * Strict Mode background batched logging state.
549 *
550 * The string buffer is guarded by itself, and its lock is also
551 * used to determine if another batched write is already
552 * in-flight.
553 */
554 private final StringBuilder mStrictModeBuffer = new StringBuilder();
555
556 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 * Intent broadcast that we have tried to start, but are
558 * waiting for its application's process to be created. We only
559 * need one (instead of a list) because we always process broadcasts
560 * one at a time, so no others can be started while waiting for this
561 * one.
562 */
563 BroadcastRecord mPendingBroadcast = null;
564
565 /**
566 * Keeps track of all IIntentReceivers that have been registered for
567 * broadcasts. Hash keys are the receiver IBinder, hash value is
568 * a ReceiverList.
569 */
570 final HashMap mRegisteredReceivers = new HashMap();
571
572 /**
573 * Resolver for broadcast intents to registered receivers.
574 * Holds BroadcastFilter (subclass of IntentFilter).
575 */
576 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
577 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
578 @Override
579 protected boolean allowFilterResult(
580 BroadcastFilter filter, List<BroadcastFilter> dest) {
581 IBinder target = filter.receiverList.receiver.asBinder();
582 for (int i=dest.size()-1; i>=0; i--) {
583 if (dest.get(i).receiverList.receiver.asBinder() == target) {
584 return false;
585 }
586 }
587 return true;
588 }
589 };
590
591 /**
592 * State of all active sticky broadcasts. Keys are the action of the
593 * sticky Intent, values are an ArrayList of all broadcasted intents with
594 * that action (which should usually be one).
595 */
596 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
597 new HashMap<String, ArrayList<Intent>>();
598
599 /**
600 * All currently running services.
601 */
602 final HashMap<ComponentName, ServiceRecord> mServices =
603 new HashMap<ComponentName, ServiceRecord>();
604
605 /**
606 * All currently running services indexed by the Intent used to start them.
607 */
608 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
609 new HashMap<Intent.FilterComparison, ServiceRecord>();
610
611 /**
612 * All currently bound service connections. Keys are the IBinder of
613 * the client's IServiceConnection.
614 */
615 final HashMap<IBinder, ConnectionRecord> mServiceConnections
616 = new HashMap<IBinder, ConnectionRecord>();
617
618 /**
619 * List of services that we have been asked to start,
620 * but haven't yet been able to. It is used to hold start requests
621 * while waiting for their corresponding application thread to get
622 * going.
623 */
624 final ArrayList<ServiceRecord> mPendingServices
625 = new ArrayList<ServiceRecord>();
626
627 /**
628 * List of services that are scheduled to restart following a crash.
629 */
630 final ArrayList<ServiceRecord> mRestartingServices
631 = new ArrayList<ServiceRecord>();
632
633 /**
634 * List of services that are in the process of being stopped.
635 */
636 final ArrayList<ServiceRecord> mStoppingServices
637 = new ArrayList<ServiceRecord>();
638
639 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700640 * Backup/restore process management
641 */
642 String mBackupAppName = null;
643 BackupRecord mBackupTarget = null;
644
645 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 * List of PendingThumbnailsRecord objects of clients who are still
647 * waiting to receive all of the thumbnails for a task.
648 */
649 final ArrayList mPendingThumbnails = new ArrayList();
650
651 /**
652 * List of HistoryRecord objects that have been finished and must
653 * still report back to a pending thumbnail receiver.
654 */
655 final ArrayList mCancelledThumbnails = new ArrayList();
656
657 /**
658 * All of the currently running global content providers. Keys are a
659 * string containing the provider name and values are a
660 * ContentProviderRecord object containing the data about it. Note
661 * that a single provider may be published under multiple names, so
662 * there may be multiple entries here for a single one in mProvidersByClass.
663 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700664 final HashMap<String, ContentProviderRecord> mProvidersByName
665 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666
667 /**
668 * All of the currently running global content providers. Keys are a
669 * string containing the provider's implementation class and values are a
670 * ContentProviderRecord object containing the data about it.
671 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700672 final HashMap<String, ContentProviderRecord> mProvidersByClass
673 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674
675 /**
676 * List of content providers who have clients waiting for them. The
677 * application is currently being launched and the provider will be
678 * removed from this list once it is published.
679 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700680 final ArrayList<ContentProviderRecord> mLaunchingProviders
681 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682
683 /**
684 * Global set of specific Uri permissions that have been granted.
685 */
686 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
687 = new SparseArray<HashMap<Uri, UriPermission>>();
688
689 /**
690 * Thread-local storage used to carry caller permissions over through
691 * indirect content-provider access.
692 * @see #ActivityManagerService.openContentUri()
693 */
694 private class Identity {
695 public int pid;
696 public int uid;
697
698 Identity(int _pid, int _uid) {
699 pid = _pid;
700 uid = _uid;
701 }
702 }
703 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
704
705 /**
706 * All information we have collected about the runtime performance of
707 * any user id that can impact battery performance.
708 */
709 final BatteryStatsService mBatteryStatsService;
710
711 /**
712 * information about component usage
713 */
714 final UsageStatsService mUsageStatsService;
715
716 /**
717 * Current configuration information. HistoryRecord objects are given
718 * a reference to this object to indicate which configuration they are
719 * currently running in, so this object must be kept immutable.
720 */
721 Configuration mConfiguration = new Configuration();
722
723 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800724 * Current sequencing integer of the configuration, for skipping old
725 * configurations.
726 */
727 int mConfigurationSeq = 0;
728
729 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700730 * Hardware-reported OpenGLES version.
731 */
732 final int GL_ES_VERSION;
733
734 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 * List of initialization arguments to pass to all processes when binding applications to them.
736 * For example, references to the commonly used services.
737 */
738 HashMap<String, IBinder> mAppBindArgs;
739
740 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700741 * Temporary to avoid allocations. Protected by main lock.
742 */
743 final StringBuilder mStringBuilder = new StringBuilder(256);
744
745 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 * Used to control how we initialize the service.
747 */
748 boolean mStartRunning = false;
749 ComponentName mTopComponent;
750 String mTopAction;
751 String mTopData;
752 boolean mSystemReady = false;
753 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700754 boolean mWaitingUpdate = false;
755 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756
757 Context mContext;
758
759 int mFactoryTest;
760
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700761 boolean mCheckedForSetup;
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700764 * The time at which we will allow normal application switches again,
765 * after a call to {@link #stopAppSwitches()}.
766 */
767 long mAppSwitchesAllowedTime;
768
769 /**
770 * This is set to true after the first switch after mAppSwitchesAllowedTime
771 * is set; any switches after that will clear the time.
772 */
773 boolean mDidAppSwitch;
774
775 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700776 * Last time (in realtime) at which we checked for wake lock usage.
777 */
778 long mLastWakeLockCheckTime;
779
780 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 * Set while we are wanting to sleep, to prevent any
782 * activities from being started/resumed.
783 */
784 boolean mSleeping = false;
785
786 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700787 * Set if we are shutting down the system, similar to sleeping.
788 */
789 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 /**
792 * Task identifier that activities are currently being started
793 * in. Incremented each time a new task is created.
794 * todo: Replace this with a TokenSpace class that generates non-repeating
795 * integers that won't wrap.
796 */
797 int mCurTask = 1;
798
799 /**
800 * Current sequence id for oom_adj computation traversal.
801 */
802 int mAdjSeq = 0;
803
804 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700805 * Current sequence id for process LRU updating.
806 */
807 int mLruSeq = 0;
808
809 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
811 * is set, indicating the user wants processes started in such a way
812 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
813 * running in each process (thus no pre-initialized process, etc).
814 */
815 boolean mSimpleProcessManagement = false;
816
817 /**
818 * System monitoring: number of processes that died since the last
819 * N procs were started.
820 */
821 int[] mProcDeaths = new int[20];
822
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700823 /**
824 * This is set if we had to do a delayed dexopt of an app before launching
825 * it, to increasing the ANR timeouts in that case.
826 */
827 boolean mDidDexOpt;
828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 String mDebugApp = null;
830 boolean mWaitForDebugger = false;
831 boolean mDebugTransient = false;
832 String mOrigDebugApp = null;
833 boolean mOrigWaitForDebugger = false;
834 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700835 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700837 final RemoteCallbackList<IActivityWatcher> mWatchers
838 = new RemoteCallbackList<IActivityWatcher>();
839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 /**
841 * Callback of last caller to {@link #requestPss}.
842 */
843 Runnable mRequestPssCallback;
844
845 /**
846 * Remaining processes for which we are waiting results from the last
847 * call to {@link #requestPss}.
848 */
849 final ArrayList<ProcessRecord> mRequestPssList
850 = new ArrayList<ProcessRecord>();
851
852 /**
853 * Runtime statistics collection thread. This object's lock is used to
854 * protect all related state.
855 */
856 final Thread mProcessStatsThread;
857
858 /**
859 * Used to collect process stats when showing not responding dialog.
860 * Protected by mProcessStatsThread.
861 */
862 final ProcessStats mProcessStats = new ProcessStats(
863 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700864 final AtomicLong mLastCpuTime = new AtomicLong(0);
865 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 long mLastWriteTime = 0;
868
869 /**
870 * Set to true after the system has finished booting.
871 */
872 boolean mBooted = false;
873
874 int mProcessLimit = 0;
875
876 WindowManagerService mWindowManager;
877
878 static ActivityManagerService mSelf;
879 static ActivityThread mSystemThread;
880
881 private final class AppDeathRecipient implements IBinder.DeathRecipient {
882 final ProcessRecord mApp;
883 final int mPid;
884 final IApplicationThread mAppThread;
885
886 AppDeathRecipient(ProcessRecord app, int pid,
887 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800888 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 TAG, "New death recipient " + this
890 + " for thread " + thread.asBinder());
891 mApp = app;
892 mPid = pid;
893 mAppThread = thread;
894 }
895
896 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800897 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 TAG, "Death received in " + this
899 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 synchronized(ActivityManagerService.this) {
901 appDiedLocked(mApp, mPid, mAppThread);
902 }
903 }
904 }
905
906 static final int SHOW_ERROR_MSG = 1;
907 static final int SHOW_NOT_RESPONDING_MSG = 2;
908 static final int SHOW_FACTORY_ERROR_MSG = 3;
909 static final int UPDATE_CONFIGURATION_MSG = 4;
910 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
911 static final int WAIT_FOR_DEBUGGER_MSG = 6;
912 static final int BROADCAST_INTENT_MSG = 7;
913 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 static final int SERVICE_TIMEOUT_MSG = 12;
915 static final int UPDATE_TIME_ZONE = 13;
916 static final int SHOW_UID_ERROR_MSG = 14;
917 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700919 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700920 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800921 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700922 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
923 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700924 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700925 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926
927 AlertDialog mUidAlert;
928
929 final Handler mHandler = new Handler() {
930 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800931 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 //}
933
934 public void handleMessage(Message msg) {
935 switch (msg.what) {
936 case SHOW_ERROR_MSG: {
937 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 synchronized (ActivityManagerService.this) {
939 ProcessRecord proc = (ProcessRecord)data.get("app");
940 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800941 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 return;
943 }
944 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700945 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800946 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 d.show();
948 proc.crashDialog = d;
949 } else {
950 // The device is asleep, so just pretend that the user
951 // saw a crash dialog and hit "force quit".
952 res.set(0);
953 }
954 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700955
956 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 } break;
958 case SHOW_NOT_RESPONDING_MSG: {
959 synchronized (ActivityManagerService.this) {
960 HashMap data = (HashMap) msg.obj;
961 ProcessRecord proc = (ProcessRecord)data.get("app");
962 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800963 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 return;
965 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800966
967 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
968 null, null, 0, null, null, null,
969 false, false, MY_PID, Process.SYSTEM_UID);
970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700972 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 d.show();
974 proc.anrDialog = d;
975 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700976
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700977 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700979 case SHOW_STRICT_MODE_VIOLATION_MSG: {
980 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
981 synchronized (ActivityManagerService.this) {
982 ProcessRecord proc = (ProcessRecord) data.get("app");
983 if (proc == null) {
984 Slog.e(TAG, "App not found when showing strict mode dialog.");
985 break;
986 }
987 if (proc.crashDialog != null) {
988 Slog.e(TAG, "App already has strict mode dialog: " + proc);
989 return;
990 }
991 AppErrorResult res = (AppErrorResult) data.get("result");
992 if (!mSleeping && !mShuttingDown) {
993 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
994 d.show();
995 proc.crashDialog = d;
996 } else {
997 // The device is asleep, so just pretend that the user
998 // saw a crash dialog and hit "force quit".
999 res.set(0);
1000 }
1001 }
1002 ensureBootCompleted();
1003 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 case SHOW_FACTORY_ERROR_MSG: {
1005 Dialog d = new FactoryErrorDialog(
1006 mContext, msg.getData().getCharSequence("msg"));
1007 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001008 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 } break;
1010 case UPDATE_CONFIGURATION_MSG: {
1011 final ContentResolver resolver = mContext.getContentResolver();
1012 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1013 } break;
1014 case GC_BACKGROUND_PROCESSES_MSG: {
1015 synchronized (ActivityManagerService.this) {
1016 performAppGcsIfAppropriateLocked();
1017 }
1018 } break;
1019 case WAIT_FOR_DEBUGGER_MSG: {
1020 synchronized (ActivityManagerService.this) {
1021 ProcessRecord app = (ProcessRecord)msg.obj;
1022 if (msg.arg1 != 0) {
1023 if (!app.waitedForDebugger) {
1024 Dialog d = new AppWaitingForDebuggerDialog(
1025 ActivityManagerService.this,
1026 mContext, app);
1027 app.waitDialog = d;
1028 app.waitedForDebugger = true;
1029 d.show();
1030 }
1031 } else {
1032 if (app.waitDialog != null) {
1033 app.waitDialog.dismiss();
1034 app.waitDialog = null;
1035 }
1036 }
1037 }
1038 } break;
1039 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001040 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 TAG, "Received BROADCAST_INTENT_MSG");
1042 processNextBroadcast(true);
1043 } break;
1044 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001045 if (mDidDexOpt) {
1046 mDidDexOpt = false;
1047 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1048 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1049 return;
1050 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001051 // Only process broadcast timeouts if the system is ready. That way
1052 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1053 // to do heavy lifting for system up
1054 if (mSystemReady) {
1055 broadcastTimeout();
1056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001059 if (mDidDexOpt) {
1060 mDidDexOpt = false;
1061 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1062 nmsg.obj = msg.obj;
1063 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1064 return;
1065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 serviceTimeout((ProcessRecord)msg.obj);
1067 } break;
1068 case UPDATE_TIME_ZONE: {
1069 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001070 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1071 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 if (r.thread != null) {
1073 try {
1074 r.thread.updateTimeZone();
1075 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 }
1078 }
1079 }
1080 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001081 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 case SHOW_UID_ERROR_MSG: {
1083 // XXX This is a temporary dialog, no need to localize.
1084 AlertDialog d = new BaseErrorDialog(mContext);
1085 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1086 d.setCancelable(false);
1087 d.setTitle("System UIDs Inconsistent");
1088 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1089 d.setButton("I'm Feeling Lucky",
1090 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1091 mUidAlert = d;
1092 d.show();
1093 } break;
1094 case IM_FEELING_LUCKY_MSG: {
1095 if (mUidAlert != null) {
1096 mUidAlert.dismiss();
1097 mUidAlert = null;
1098 }
1099 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001101 if (mDidDexOpt) {
1102 mDidDexOpt = false;
1103 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1104 nmsg.obj = msg.obj;
1105 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1106 return;
1107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 ProcessRecord app = (ProcessRecord)msg.obj;
1109 synchronized (ActivityManagerService.this) {
1110 processStartTimedOutLocked(app);
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001113 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1114 synchronized (ActivityManagerService.this) {
1115 doPendingActivityLaunchesLocked(true);
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001118 case KILL_APPLICATION_MSG: {
1119 synchronized (ActivityManagerService.this) {
1120 int uid = msg.arg1;
1121 boolean restart = (msg.arg2 == 1);
1122 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001123 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001124 }
1125 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001126 case FINALIZE_PENDING_INTENT_MSG: {
1127 ((PendingIntentRecord)msg.obj).completeFinalize();
1128 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001129 case POST_HEAVY_NOTIFICATION_MSG: {
1130 INotificationManager inm = NotificationManager.getService();
1131 if (inm == null) {
1132 return;
1133 }
1134
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001135 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001136 ProcessRecord process = root.app;
1137 if (process == null) {
1138 return;
1139 }
1140
1141 try {
1142 Context context = mContext.createPackageContext(process.info.packageName, 0);
1143 String text = mContext.getString(R.string.heavy_weight_notification,
1144 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1145 Notification notification = new Notification();
1146 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1147 notification.when = 0;
1148 notification.flags = Notification.FLAG_ONGOING_EVENT;
1149 notification.tickerText = text;
1150 notification.defaults = 0; // please be quiet
1151 notification.sound = null;
1152 notification.vibrate = null;
1153 notification.setLatestEventInfo(context, text,
1154 mContext.getText(R.string.heavy_weight_notification_detail),
1155 PendingIntent.getActivity(mContext, 0, root.intent,
1156 PendingIntent.FLAG_CANCEL_CURRENT));
1157
1158 try {
1159 int[] outId = new int[1];
1160 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1161 notification, outId);
1162 } catch (RuntimeException e) {
1163 Slog.w(ActivityManagerService.TAG,
1164 "Error showing notification for heavy-weight app", e);
1165 } catch (RemoteException e) {
1166 }
1167 } catch (NameNotFoundException e) {
1168 Log.w(TAG, "Unable to create context for heavy notification", e);
1169 }
1170 } break;
1171 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1172 INotificationManager inm = NotificationManager.getService();
1173 if (inm == null) {
1174 return;
1175 }
1176 try {
1177 inm.cancelNotification("android",
1178 R.string.heavy_weight_notification);
1179 } catch (RuntimeException e) {
1180 Slog.w(ActivityManagerService.TAG,
1181 "Error canceling notification for service", e);
1182 } catch (RemoteException e) {
1183 }
1184 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001185 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1186 synchronized (ActivityManagerService.this) {
1187 checkExcessiveWakeLocksLocked(true);
1188 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1189 if (mSleeping) {
1190 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1191 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
1192 }
1193 }
1194 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 }
1196 }
1197 };
1198
1199 public static void setSystemProcess() {
1200 try {
1201 ActivityManagerService m = mSelf;
1202
1203 ServiceManager.addService("activity", m);
1204 ServiceManager.addService("meminfo", new MemBinder(m));
1205 if (MONITOR_CPU_USAGE) {
1206 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 ServiceManager.addService("permission", new PermissionController(m));
1209
1210 ApplicationInfo info =
1211 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001212 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001213 mSystemThread.installSystemApplicationInfo(info);
1214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 synchronized (mSelf) {
1216 ProcessRecord app = mSelf.newProcessRecordLocked(
1217 mSystemThread.getApplicationThread(), info,
1218 info.processName);
1219 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001220 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 app.maxAdj = SYSTEM_ADJ;
1222 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1223 synchronized (mSelf.mPidsSelfLocked) {
1224 mSelf.mPidsSelfLocked.put(app.pid, app);
1225 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001226 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 }
1228 } catch (PackageManager.NameNotFoundException e) {
1229 throw new RuntimeException(
1230 "Unable to find android system package", e);
1231 }
1232 }
1233
1234 public void setWindowManager(WindowManagerService wm) {
1235 mWindowManager = wm;
1236 }
1237
1238 public static final Context main(int factoryTest) {
1239 AThread thr = new AThread();
1240 thr.start();
1241
1242 synchronized (thr) {
1243 while (thr.mService == null) {
1244 try {
1245 thr.wait();
1246 } catch (InterruptedException e) {
1247 }
1248 }
1249 }
1250
1251 ActivityManagerService m = thr.mService;
1252 mSelf = m;
1253 ActivityThread at = ActivityThread.systemMain();
1254 mSystemThread = at;
1255 Context context = at.getSystemContext();
1256 m.mContext = context;
1257 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001258 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259
1260 m.mBatteryStatsService.publish(context);
1261 m.mUsageStatsService.publish(context);
1262
1263 synchronized (thr) {
1264 thr.mReady = true;
1265 thr.notifyAll();
1266 }
1267
1268 m.startRunning(null, null, null, null);
1269
1270 return context;
1271 }
1272
1273 public static ActivityManagerService self() {
1274 return mSelf;
1275 }
1276
1277 static class AThread extends Thread {
1278 ActivityManagerService mService;
1279 boolean mReady = false;
1280
1281 public AThread() {
1282 super("ActivityManager");
1283 }
1284
1285 public void run() {
1286 Looper.prepare();
1287
1288 android.os.Process.setThreadPriority(
1289 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001290 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291
1292 ActivityManagerService m = new ActivityManagerService();
1293
1294 synchronized (this) {
1295 mService = m;
1296 notifyAll();
1297 }
1298
1299 synchronized (this) {
1300 while (!mReady) {
1301 try {
1302 wait();
1303 } catch (InterruptedException e) {
1304 }
1305 }
1306 }
1307
1308 Looper.loop();
1309 }
1310 }
1311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 static class MemBinder extends Binder {
1313 ActivityManagerService mActivityManagerService;
1314 MemBinder(ActivityManagerService activityManagerService) {
1315 mActivityManagerService = activityManagerService;
1316 }
1317
1318 @Override
1319 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1320 ActivityManagerService service = mActivityManagerService;
1321 ArrayList<ProcessRecord> procs;
1322 synchronized (mActivityManagerService) {
1323 if (args != null && args.length > 0
1324 && args[0].charAt(0) != '-') {
1325 procs = new ArrayList<ProcessRecord>();
1326 int pid = -1;
1327 try {
1328 pid = Integer.parseInt(args[0]);
1329 } catch (NumberFormatException e) {
1330
1331 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001332 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1333 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 if (proc.pid == pid) {
1335 procs.add(proc);
1336 } else if (proc.processName.equals(args[0])) {
1337 procs.add(proc);
1338 }
1339 }
1340 if (procs.size() <= 0) {
1341 pw.println("No process found for: " + args[0]);
1342 return;
1343 }
1344 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001345 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 }
1347 }
1348 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1349 }
1350 }
1351
1352 static class CpuBinder extends Binder {
1353 ActivityManagerService mActivityManagerService;
1354 CpuBinder(ActivityManagerService activityManagerService) {
1355 mActivityManagerService = activityManagerService;
1356 }
1357
1358 @Override
1359 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1360 synchronized (mActivityManagerService.mProcessStatsThread) {
1361 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1362 }
1363 }
1364 }
1365
1366 private ActivityManagerService() {
1367 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1368 if (v != null && Integer.getInteger(v) != 0) {
1369 mSimpleProcessManagement = true;
1370 }
1371 v = System.getenv("ANDROID_DEBUG_APP");
1372 if (v != null) {
1373 mSimpleProcessManagement = true;
1374 }
1375
Joe Onorato8a9b2202010-02-26 18:56:32 -08001376 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 File dataDir = Environment.getDataDirectory();
1379 File systemDir = new File(dataDir, "system");
1380 systemDir.mkdirs();
1381 mBatteryStatsService = new BatteryStatsService(new File(
1382 systemDir, "batterystats.bin").toString());
1383 mBatteryStatsService.getActiveStatistics().readLocked();
1384 mBatteryStatsService.getActiveStatistics().writeLocked();
1385
1386 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001387 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388
Jack Palevichb90d28c2009-07-22 15:35:24 -07001389 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1390 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1391
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001392 mConfiguration.setToDefaults();
1393 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 mProcessStats.init();
1395
1396 // Add ourself to the Watchdog monitors.
1397 Watchdog.getInstance().addMonitor(this);
1398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 mProcessStatsThread = new Thread("ProcessStats") {
1400 public void run() {
1401 while (true) {
1402 try {
1403 try {
1404 synchronized(this) {
1405 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001406 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001408 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 // + ", write delay=" + nextWriteDelay);
1410 if (nextWriteDelay < nextCpuDelay) {
1411 nextCpuDelay = nextWriteDelay;
1412 }
1413 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001414 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 this.wait(nextCpuDelay);
1416 }
1417 }
1418 } catch (InterruptedException e) {
1419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 updateCpuStatsNow();
1421 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001422 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425 }
1426 };
1427 mProcessStatsThread.start();
1428 }
1429
1430 @Override
1431 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1432 throws RemoteException {
1433 try {
1434 return super.onTransact(code, data, reply, flags);
1435 } catch (RuntimeException e) {
1436 // The activity manager only throws security exceptions, so let's
1437 // log all others.
1438 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001439 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 }
1441 throw e;
1442 }
1443 }
1444
1445 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001446 final long now = SystemClock.uptimeMillis();
1447 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1448 return;
1449 }
1450 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1451 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 mProcessStatsThread.notify();
1453 }
1454 }
1455 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 void updateCpuStatsNow() {
1458 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001459 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 final long now = SystemClock.uptimeMillis();
1461 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001464 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1465 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 haveNewCpuStats = true;
1467 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001468 //Slog.i(TAG, mProcessStats.printCurrentState());
1469 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 // + mProcessStats.getTotalCpuPercent() + "%");
1471
Joe Onorato8a9b2202010-02-26 18:56:32 -08001472 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 if ("true".equals(SystemProperties.get("events.cpu"))) {
1474 int user = mProcessStats.getLastUserTime();
1475 int system = mProcessStats.getLastSystemTime();
1476 int iowait = mProcessStats.getLastIoWaitTime();
1477 int irq = mProcessStats.getLastIrqTime();
1478 int softIrq = mProcessStats.getLastSoftIrqTime();
1479 int idle = mProcessStats.getLastIdleTime();
1480
1481 int total = user + system + iowait + irq + softIrq + idle;
1482 if (total == 0) total = 1;
1483
Doug Zongker2bec3d42009-12-04 12:52:44 -08001484 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 ((user+system+iowait+irq+softIrq) * 100) / total,
1486 (user * 100) / total,
1487 (system * 100) / total,
1488 (iowait * 100) / total,
1489 (irq * 100) / total,
1490 (softIrq * 100) / total);
1491 }
1492 }
1493
Amith Yamasanie43530a2009-08-21 13:11:37 -07001494 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001495 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001496 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 synchronized(mPidsSelfLocked) {
1498 if (haveNewCpuStats) {
1499 if (mBatteryStatsService.isOnBattery()) {
1500 final int N = mProcessStats.countWorkingStats();
1501 for (int i=0; i<N; i++) {
1502 ProcessStats.Stats st
1503 = mProcessStats.getWorkingStats(i);
1504 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1505 if (pr != null) {
1506 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1507 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001508 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001509 } else {
1510 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001511 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001512 if (ps != null) {
1513 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001514 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 }
1517 }
1518 }
1519 }
1520 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1523 mLastWriteTime = now;
1524 mBatteryStatsService.getActiveStatistics().writeLocked();
1525 }
1526 }
1527 }
1528 }
1529
1530 /**
1531 * Initialize the application bind args. These are passed to each
1532 * process when the bindApplication() IPC is sent to the process. They're
1533 * lazily setup to make sure the services are running when they're asked for.
1534 */
1535 private HashMap<String, IBinder> getCommonServicesLocked() {
1536 if (mAppBindArgs == null) {
1537 mAppBindArgs = new HashMap<String, IBinder>();
1538
1539 // Setup the application init args
1540 mAppBindArgs.put("package", ServiceManager.getService("package"));
1541 mAppBindArgs.put("window", ServiceManager.getService("window"));
1542 mAppBindArgs.put(Context.ALARM_SERVICE,
1543 ServiceManager.getService(Context.ALARM_SERVICE));
1544 }
1545 return mAppBindArgs;
1546 }
1547
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001548 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 if (mFocusedActivity != r) {
1550 mFocusedActivity = r;
1551 mWindowManager.setFocusedApp(r, true);
1552 }
1553 }
1554
Dianne Hackborn906497c2010-05-10 15:57:38 -07001555 private final void updateLruProcessInternalLocked(ProcessRecord app,
1556 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001558 int lrui = mLruProcesses.indexOf(app);
1559 if (lrui >= 0) mLruProcesses.remove(lrui);
1560
1561 int i = mLruProcesses.size()-1;
1562 int skipTop = 0;
1563
Dianne Hackborn906497c2010-05-10 15:57:38 -07001564 app.lruSeq = mLruSeq;
1565
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001566 // compute the new weight for this process.
1567 if (updateActivityTime) {
1568 app.lastActivityTime = SystemClock.uptimeMillis();
1569 }
1570 if (app.activities.size() > 0) {
1571 // If this process has activities, we more strongly want to keep
1572 // it around.
1573 app.lruWeight = app.lastActivityTime;
1574 } else if (app.pubProviders.size() > 0) {
1575 // If this process contains content providers, we want to keep
1576 // it a little more strongly.
1577 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1578 // Also don't let it kick out the first few "real" hidden processes.
1579 skipTop = MIN_HIDDEN_APPS;
1580 } else {
1581 // If this process doesn't have activities, we less strongly
1582 // want to keep it around, and generally want to avoid getting
1583 // in front of any very recently used activities.
1584 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1585 // Also don't let it kick out the first few "real" hidden processes.
1586 skipTop = MIN_HIDDEN_APPS;
1587 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001588
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001589 while (i >= 0) {
1590 ProcessRecord p = mLruProcesses.get(i);
1591 // If this app shouldn't be in front of the first N background
1592 // apps, then skip over that many that are currently hidden.
1593 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1594 skipTop--;
1595 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001596 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001597 mLruProcesses.add(i+1, app);
1598 break;
1599 }
1600 i--;
1601 }
1602 if (i < 0) {
1603 mLruProcesses.add(0, app);
1604 }
1605
Dianne Hackborn906497c2010-05-10 15:57:38 -07001606 // If the app is currently using a content provider or service,
1607 // bump those processes as well.
1608 if (app.connections.size() > 0) {
1609 for (ConnectionRecord cr : app.connections) {
1610 if (cr.binding != null && cr.binding.service != null
1611 && cr.binding.service.app != null
1612 && cr.binding.service.app.lruSeq != mLruSeq) {
1613 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1614 updateActivityTime, i+1);
1615 }
1616 }
1617 }
1618 if (app.conProviders.size() > 0) {
1619 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1620 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1621 updateLruProcessInternalLocked(cpr.app, oomAdj,
1622 updateActivityTime, i+1);
1623 }
1624 }
1625 }
1626
Joe Onorato8a9b2202010-02-26 18:56:32 -08001627 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 if (oomAdj) {
1629 updateOomAdjLocked();
1630 }
1631 }
1632
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001633 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001634 boolean oomAdj, boolean updateActivityTime) {
1635 mLruSeq++;
1636 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1637 }
1638
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001639 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 String processName, int uid) {
1641 if (uid == Process.SYSTEM_UID) {
1642 // The system gets to run in any process. If there are multiple
1643 // processes with the same uid, just pick the first (this
1644 // should never happen).
1645 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1646 processName);
1647 return procs != null ? procs.valueAt(0) : null;
1648 }
1649 ProcessRecord proc = mProcessNames.get(processName, uid);
1650 return proc;
1651 }
1652
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001653 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001654 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001655 try {
1656 if (pm.performDexOpt(packageName)) {
1657 mDidDexOpt = true;
1658 }
1659 } catch (RemoteException e) {
1660 }
1661 }
1662
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001663 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 int transit = mWindowManager.getPendingAppTransition();
1665 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1666 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1667 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1668 }
1669
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001670 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001672 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1674 // We don't have to do anything more if:
1675 // (1) There is an existing application record; and
1676 // (2) The caller doesn't think it is dead, OR there is no thread
1677 // object attached to it so we know it couldn't have crashed; and
1678 // (3) There is a pid assigned to it, so it is either starting or
1679 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001680 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 + " app=" + app + " knownToBeDead=" + knownToBeDead
1682 + " thread=" + (app != null ? app.thread : null)
1683 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001684 if (app != null && app.pid > 0) {
1685 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001686 // We already have the app running, or are waiting for it to
1687 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001688 return app;
1689 } else {
1690 // An application record is attached to a previous process,
1691 // clean it up now.
1692 handleAppDiedLocked(app, true);
1693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 String hostingNameStr = hostingName != null
1697 ? hostingName.flattenToShortString() : null;
1698
1699 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1700 // If we are in the background, then check to see if this process
1701 // is bad. If so, we will just silently fail.
1702 if (mBadProcesses.get(info.processName, info.uid) != null) {
1703 return null;
1704 }
1705 } else {
1706 // When the user is explicitly starting a process, then clear its
1707 // crash count so that we won't make it bad until they see at
1708 // least one crash dialog again, and make the process good again
1709 // if it had been bad.
1710 mProcessCrashTimes.remove(info.processName, info.uid);
1711 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001712 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 info.processName);
1714 mBadProcesses.remove(info.processName, info.uid);
1715 if (app != null) {
1716 app.bad = false;
1717 }
1718 }
1719 }
1720
1721 if (app == null) {
1722 app = newProcessRecordLocked(null, info, processName);
1723 mProcessNames.put(processName, info.uid, app);
1724 } else {
1725 // If this is a new package in the process, add the package to the list
1726 app.addPackage(info.packageName);
1727 }
1728
1729 // If the system is not ready yet, then hold off on starting this
1730 // process until it is.
1731 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001732 && !isAllowedWhileBooting(info)
1733 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 if (!mProcessesOnHold.contains(app)) {
1735 mProcessesOnHold.add(app);
1736 }
1737 return app;
1738 }
1739
1740 startProcessLocked(app, hostingType, hostingNameStr);
1741 return (app.pid != 0) ? app : null;
1742 }
1743
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001744 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1745 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1746 }
1747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 private final void startProcessLocked(ProcessRecord app,
1749 String hostingType, String hostingNameStr) {
1750 if (app.pid > 0 && app.pid != MY_PID) {
1751 synchronized (mPidsSelfLocked) {
1752 mPidsSelfLocked.remove(app.pid);
1753 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1754 }
1755 app.pid = 0;
1756 }
1757
1758 mProcessesOnHold.remove(app);
1759
1760 updateCpuStats();
1761
1762 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1763 mProcDeaths[0] = 0;
1764
1765 try {
1766 int uid = app.info.uid;
1767 int[] gids = null;
1768 try {
1769 gids = mContext.getPackageManager().getPackageGids(
1770 app.info.packageName);
1771 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001772 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 }
1774 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1775 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1776 && mTopComponent != null
1777 && app.processName.equals(mTopComponent.getPackageName())) {
1778 uid = 0;
1779 }
1780 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1781 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1782 uid = 0;
1783 }
1784 }
1785 int debugFlags = 0;
1786 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1787 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1788 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001789 // Run the app in safe mode if its manifest requests so or the
1790 // system is booted in safe mode.
1791 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1792 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001793 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1796 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1797 }
1798 if ("1".equals(SystemProperties.get("debug.assert"))) {
1799 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1800 }
1801 int pid = Process.start("android.app.ActivityThread",
1802 mSimpleProcessManagement ? app.processName : null, uid, uid,
1803 gids, debugFlags, null);
1804 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1805 synchronized (bs) {
1806 if (bs.isOnBattery()) {
1807 app.batteryStats.incStartsLocked();
1808 }
1809 }
1810
Doug Zongker2bec3d42009-12-04 12:52:44 -08001811 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 app.processName, hostingType,
1813 hostingNameStr != null ? hostingNameStr : "");
1814
1815 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001816 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 }
1818
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001819 StringBuilder buf = mStringBuilder;
1820 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 buf.append("Start proc ");
1822 buf.append(app.processName);
1823 buf.append(" for ");
1824 buf.append(hostingType);
1825 if (hostingNameStr != null) {
1826 buf.append(" ");
1827 buf.append(hostingNameStr);
1828 }
1829 buf.append(": pid=");
1830 buf.append(pid);
1831 buf.append(" uid=");
1832 buf.append(uid);
1833 buf.append(" gids={");
1834 if (gids != null) {
1835 for (int gi=0; gi<gids.length; gi++) {
1836 if (gi != 0) buf.append(", ");
1837 buf.append(gids[gi]);
1838
1839 }
1840 }
1841 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001842 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 if (pid == 0 || pid == MY_PID) {
1844 // Processes are being emulated with threads.
1845 app.pid = MY_PID;
1846 app.removed = false;
1847 mStartingProcesses.add(app);
1848 } else if (pid > 0) {
1849 app.pid = pid;
1850 app.removed = false;
1851 synchronized (mPidsSelfLocked) {
1852 this.mPidsSelfLocked.put(pid, app);
1853 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1854 msg.obj = app;
1855 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1856 }
1857 } else {
1858 app.pid = 0;
1859 RuntimeException e = new RuntimeException(
1860 "Failure starting process " + app.processName
1861 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001862 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 }
1864 } catch (RuntimeException e) {
1865 // XXX do better error recovery.
1866 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001867 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 }
1869 }
1870
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001871 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 if (resumed) {
1873 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1874 } else {
1875 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1876 }
1877 }
1878
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001879 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001880 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1881 && mTopAction == null) {
1882 // We are running in factory test mode, but unable to find
1883 // the factory test app, so just sit around displaying the
1884 // error message and don't try to start anything.
1885 return false;
1886 }
1887 Intent intent = new Intent(
1888 mTopAction,
1889 mTopData != null ? Uri.parse(mTopData) : null);
1890 intent.setComponent(mTopComponent);
1891 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1892 intent.addCategory(Intent.CATEGORY_HOME);
1893 }
1894 ActivityInfo aInfo =
1895 intent.resolveActivityInfo(mContext.getPackageManager(),
1896 STOCK_PM_FLAGS);
1897 if (aInfo != null) {
1898 intent.setComponent(new ComponentName(
1899 aInfo.applicationInfo.packageName, aInfo.name));
1900 // Don't do this if the home app is currently being
1901 // instrumented.
1902 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1903 aInfo.applicationInfo.uid);
1904 if (app == null || app.instrumentationClass == null) {
1905 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001906 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001907 null, null, 0, 0, 0, false, false);
1908 }
1909 }
1910
1911
1912 return true;
1913 }
1914
1915 /**
1916 * Starts the "new version setup screen" if appropriate.
1917 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001918 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001919 // Only do this once per boot.
1920 if (mCheckedForSetup) {
1921 return;
1922 }
1923
1924 // We will show this screen if the current one is a different
1925 // version than the last one shown, and we are not running in
1926 // low-level factory test mode.
1927 final ContentResolver resolver = mContext.getContentResolver();
1928 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1929 Settings.Secure.getInt(resolver,
1930 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1931 mCheckedForSetup = true;
1932
1933 // See if we should be showing the platform update setup UI.
1934 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1935 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1936 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1937
1938 // We don't allow third party apps to replace this.
1939 ResolveInfo ri = null;
1940 for (int i=0; ris != null && i<ris.size(); i++) {
1941 if ((ris.get(i).activityInfo.applicationInfo.flags
1942 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1943 ri = ris.get(i);
1944 break;
1945 }
1946 }
1947
1948 if (ri != null) {
1949 String vers = ri.activityInfo.metaData != null
1950 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1951 : null;
1952 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1953 vers = ri.activityInfo.applicationInfo.metaData.getString(
1954 Intent.METADATA_SETUP_VERSION);
1955 }
1956 String lastVers = Settings.Secure.getString(
1957 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1958 if (vers != null && !vers.equals(lastVers)) {
1959 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1960 intent.setComponent(new ComponentName(
1961 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001962 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001963 null, null, 0, 0, 0, false, false);
1964 }
1965 }
1966 }
1967 }
1968
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001969 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001970 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001971
1972 final int identHash = System.identityHashCode(r);
1973 updateUsageStats(r, true);
1974
1975 int i = mWatchers.beginBroadcast();
1976 while (i > 0) {
1977 i--;
1978 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1979 if (w != null) {
1980 try {
1981 w.activityResuming(identHash);
1982 } catch (RemoteException e) {
1983 }
1984 }
1985 }
1986 mWatchers.finishBroadcast();
1987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001989 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001990 final int N = mPendingActivityLaunches.size();
1991 if (N <= 0) {
1992 return;
1993 }
1994 for (int i=0; i<N; i++) {
1995 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001996 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001997 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1998 doResume && i == (N-1));
1999 }
2000 mPendingActivityLaunches.clear();
2001 }
2002
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002003 public final int startActivity(IApplicationThread caller,
2004 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2005 int grantedMode, IBinder resultTo,
2006 String resultWho, int requestCode, boolean onlyIfNeeded,
2007 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002008 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002009 grantedUriPermissions, grantedMode, resultTo, resultWho,
2010 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002011 }
2012
2013 public final WaitResult startActivityAndWait(IApplicationThread caller,
2014 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2015 int grantedMode, IBinder resultTo,
2016 String resultWho, int requestCode, boolean onlyIfNeeded,
2017 boolean debug) {
2018 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002019 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002020 grantedUriPermissions, grantedMode, resultTo, resultWho,
2021 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002022 return res;
2023 }
2024
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002025 public final int startActivityWithConfig(IApplicationThread caller,
2026 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2027 int grantedMode, IBinder resultTo,
2028 String resultWho, int requestCode, boolean onlyIfNeeded,
2029 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002030 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002031 grantedUriPermissions, grantedMode, resultTo, resultWho,
2032 requestCode, onlyIfNeeded, debug, null, config);
2033 }
2034
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002035 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002036 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002037 IBinder resultTo, String resultWho, int requestCode,
2038 int flagsMask, int flagsValues) {
2039 // Refuse possible leaked file descriptors
2040 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2041 throw new IllegalArgumentException("File descriptors passed in Intent");
2042 }
2043
2044 IIntentSender sender = intent.getTarget();
2045 if (!(sender instanceof PendingIntentRecord)) {
2046 throw new IllegalArgumentException("Bad PendingIntent object");
2047 }
2048
2049 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002050
2051 synchronized (this) {
2052 // If this is coming from the currently resumed activity, it is
2053 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002054 if (mMainStack.mResumedActivity != null
2055 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002056 Binder.getCallingUid()) {
2057 mAppSwitchesAllowedTime = 0;
2058 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002059 }
2060
2061 return pir.sendInner(0, fillInIntent, resolvedType,
2062 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2063 }
2064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 public boolean startNextMatchingActivity(IBinder callingActivity,
2066 Intent intent) {
2067 // Refuse possible leaked file descriptors
2068 if (intent != null && intent.hasFileDescriptors() == true) {
2069 throw new IllegalArgumentException("File descriptors passed in Intent");
2070 }
2071
2072 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002073 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 if (index < 0) {
2075 return false;
2076 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002077 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 if (r.app == null || r.app.thread == null) {
2079 // The caller is not running... d'oh!
2080 return false;
2081 }
2082 intent = new Intent(intent);
2083 // The caller is not allowed to change the data.
2084 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2085 // And we are resetting to find the next component...
2086 intent.setComponent(null);
2087
2088 ActivityInfo aInfo = null;
2089 try {
2090 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002091 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002093 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094
2095 // Look for the original activity in the list...
2096 final int N = resolves != null ? resolves.size() : 0;
2097 for (int i=0; i<N; i++) {
2098 ResolveInfo rInfo = resolves.get(i);
2099 if (rInfo.activityInfo.packageName.equals(r.packageName)
2100 && rInfo.activityInfo.name.equals(r.info.name)) {
2101 // We found the current one... the next matching is
2102 // after it.
2103 i++;
2104 if (i<N) {
2105 aInfo = resolves.get(i).activityInfo;
2106 }
2107 break;
2108 }
2109 }
2110 } catch (RemoteException e) {
2111 }
2112
2113 if (aInfo == null) {
2114 // Nobody who is next!
2115 return false;
2116 }
2117
2118 intent.setComponent(new ComponentName(
2119 aInfo.applicationInfo.packageName, aInfo.name));
2120 intent.setFlags(intent.getFlags()&~(
2121 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2122 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2123 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2124 Intent.FLAG_ACTIVITY_NEW_TASK));
2125
2126 // Okay now we need to start the new activity, replacing the
2127 // currently running activity. This is a little tricky because
2128 // we want to start the new one as if the current one is finished,
2129 // but not finish the current one first so that there is no flicker.
2130 // And thus...
2131 final boolean wasFinishing = r.finishing;
2132 r.finishing = true;
2133
2134 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002135 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 final String resultWho = r.resultWho;
2137 final int requestCode = r.requestCode;
2138 r.resultTo = null;
2139 if (resultTo != null) {
2140 resultTo.removeResultsLocked(r, resultWho, requestCode);
2141 }
2142
2143 final long origId = Binder.clearCallingIdentity();
2144 // XXX we are not dealing with propagating grantedUriPermissions...
2145 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002146 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002148 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 Binder.restoreCallingIdentity(origId);
2150
2151 r.finishing = wasFinishing;
2152 if (res != START_SUCCESS) {
2153 return false;
2154 }
2155 return true;
2156 }
2157 }
2158
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002159 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 Intent intent, String resolvedType, IBinder resultTo,
2161 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002162
2163 // This is so super not safe, that only the system (or okay root)
2164 // can do it.
2165 final int callingUid = Binder.getCallingUid();
2166 if (callingUid != 0 && callingUid != Process.myUid()) {
2167 throw new SecurityException(
2168 "startActivityInPackage only available to the system");
2169 }
2170
The Android Open Source Project4df24232009-03-05 14:34:35 -08002171 final boolean componentSpecified = intent.getComponent() != null;
2172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 // Don't modify the client's object!
2174 intent = new Intent(intent);
2175
2176 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 ActivityInfo aInfo;
2178 try {
2179 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002180 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002182 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 aInfo = rInfo != null ? rInfo.activityInfo : null;
2184 } catch (RemoteException e) {
2185 aInfo = null;
2186 }
2187
2188 if (aInfo != null) {
2189 // Store the found target back into the intent, because now that
2190 // we have it we never want to do this again. For example, if the
2191 // user navigates back to this point in the history, we should
2192 // always restart the exact same activity.
2193 intent.setComponent(new ComponentName(
2194 aInfo.applicationInfo.packageName, aInfo.name));
2195 }
2196
2197 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002198 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002200 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 }
2202 }
2203
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002204 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 // Remove any existing entries that are the same kind of task.
2206 int N = mRecentTasks.size();
2207 for (int i=0; i<N; i++) {
2208 TaskRecord tr = mRecentTasks.get(i);
2209 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2210 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2211 mRecentTasks.remove(i);
2212 i--;
2213 N--;
2214 if (task.intent == null) {
2215 // If the new recent task we are adding is not fully
2216 // specified, then replace it with the existing recent task.
2217 task = tr;
2218 }
2219 }
2220 }
2221 if (N >= MAX_RECENT_TASKS) {
2222 mRecentTasks.remove(N-1);
2223 }
2224 mRecentTasks.add(0, task);
2225 }
2226
2227 public void setRequestedOrientation(IBinder token,
2228 int requestedOrientation) {
2229 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002230 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 if (index < 0) {
2232 return;
2233 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002234 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 final long origId = Binder.clearCallingIdentity();
2236 mWindowManager.setAppOrientation(r, requestedOrientation);
2237 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002238 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 r.mayFreezeScreenLocked(r.app) ? r : null);
2240 if (config != null) {
2241 r.frozenBeforeDestroy = true;
2242 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002243 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 }
2245 }
2246 Binder.restoreCallingIdentity(origId);
2247 }
2248 }
2249
2250 public int getRequestedOrientation(IBinder token) {
2251 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002252 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 if (index < 0) {
2254 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2255 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002256 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 return mWindowManager.getAppOrientation(r);
2258 }
2259 }
2260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 /**
2262 * This is the internal entry point for handling Activity.finish().
2263 *
2264 * @param token The Binder token referencing the Activity we want to finish.
2265 * @param resultCode Result code, if any, from this Activity.
2266 * @param resultData Result data (Intent), if any, from this Activity.
2267 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002268 * @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 -08002269 */
2270 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2271 // Refuse possible leaked file descriptors
2272 if (resultData != null && resultData.hasFileDescriptors() == true) {
2273 throw new IllegalArgumentException("File descriptors passed in Intent");
2274 }
2275
2276 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002277 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002279 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 if (next != null) {
2281 // ask watcher if this is allowed
2282 boolean resumeOK = true;
2283 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002284 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002286 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 }
2288
2289 if (!resumeOK) {
2290 return false;
2291 }
2292 }
2293 }
2294 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002295 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 resultData, "app-request");
2297 Binder.restoreCallingIdentity(origId);
2298 return res;
2299 }
2300 }
2301
Dianne Hackborn860755f2010-06-03 18:47:52 -07002302 public final void finishHeavyWeightApp() {
2303 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2304 != PackageManager.PERMISSION_GRANTED) {
2305 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2306 + Binder.getCallingPid()
2307 + ", uid=" + Binder.getCallingUid()
2308 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2309 Slog.w(TAG, msg);
2310 throw new SecurityException(msg);
2311 }
2312
2313 synchronized(this) {
2314 if (mHeavyWeightProcess == null) {
2315 return;
2316 }
2317
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002318 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002319 mHeavyWeightProcess.activities);
2320 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002321 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002322 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002323 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002324 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002325 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002326 null, "finish-heavy");
2327 }
2328 }
2329 }
2330
2331 mHeavyWeightProcess = null;
2332 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2333 }
2334 }
2335
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002336 public void crashApplication(int uid, int initialPid, String packageName,
2337 String message) {
2338 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2339 != PackageManager.PERMISSION_GRANTED) {
2340 String msg = "Permission Denial: crashApplication() from pid="
2341 + Binder.getCallingPid()
2342 + ", uid=" + Binder.getCallingUid()
2343 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2344 Slog.w(TAG, msg);
2345 throw new SecurityException(msg);
2346 }
2347
2348 synchronized(this) {
2349 ProcessRecord proc = null;
2350
2351 // Figure out which process to kill. We don't trust that initialPid
2352 // still has any relation to current pids, so must scan through the
2353 // list.
2354 synchronized (mPidsSelfLocked) {
2355 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2356 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2357 if (p.info.uid != uid) {
2358 continue;
2359 }
2360 if (p.pid == initialPid) {
2361 proc = p;
2362 break;
2363 }
2364 for (String str : p.pkgList) {
2365 if (str.equals(packageName)) {
2366 proc = p;
2367 }
2368 }
2369 }
2370 }
2371
2372 if (proc == null) {
2373 Log.w(TAG, "crashApplication: nothing for uid=" + uid
2374 + " initialPid=" + initialPid
2375 + " packageName=" + packageName);
2376 return;
2377 }
2378
2379 if (proc.thread != null) {
2380 long ident = Binder.clearCallingIdentity();
2381 try {
2382 proc.thread.scheduleCrash(message);
2383 } catch (RemoteException e) {
2384 }
2385 Binder.restoreCallingIdentity(ident);
2386 }
2387 }
2388 }
2389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 public final void finishSubActivity(IBinder token, String resultWho,
2391 int requestCode) {
2392 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002393 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 if (index < 0) {
2395 return;
2396 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002397 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398
2399 final long origId = Binder.clearCallingIdentity();
2400
2401 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002402 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2403 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 if (r.resultTo == self && r.requestCode == requestCode) {
2405 if ((r.resultWho == null && resultWho == null) ||
2406 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002407 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 Activity.RESULT_CANCELED, null, "request-sub");
2409 }
2410 }
2411 }
2412
2413 Binder.restoreCallingIdentity(origId);
2414 }
2415 }
2416
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002417 public boolean willActivityBeVisible(IBinder token) {
2418 synchronized(this) {
2419 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002420 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2421 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002422 if (r == token) {
2423 return true;
2424 }
2425 if (r.fullscreen && !r.finishing) {
2426 return false;
2427 }
2428 }
2429 return true;
2430 }
2431 }
2432
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002433 public void overridePendingTransition(IBinder token, String packageName,
2434 int enterAnim, int exitAnim) {
2435 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002436 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002437 if (index < 0) {
2438 return;
2439 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002440 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002441
2442 final long origId = Binder.clearCallingIdentity();
2443
2444 if (self.state == ActivityState.RESUMED
2445 || self.state == ActivityState.PAUSING) {
2446 mWindowManager.overridePendingAppTransition(packageName,
2447 enterAnim, exitAnim);
2448 }
2449
2450 Binder.restoreCallingIdentity(origId);
2451 }
2452 }
2453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 * Main function for removing an existing process from the activity manager
2456 * as a result of that process going away. Clears out all connections
2457 * to the process.
2458 */
2459 private final void handleAppDiedLocked(ProcessRecord app,
2460 boolean restarting) {
2461 cleanUpApplicationRecordLocked(app, restarting, -1);
2462 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002463 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 }
2465
2466 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002467 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2468 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2469 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2472 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 }
2474
2475 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002476 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477
2478 boolean atTop = true;
2479 boolean hasVisibleActivities = false;
2480
2481 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002482 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002483 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 TAG, "Removing app " + app + " from history with " + i + " entries");
2485 while (i > 0) {
2486 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002487 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002488 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2490 if (r.app == app) {
2491 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002492 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 TAG, "Removing this entry! frozen=" + r.haveState
2494 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002495 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496
2497 r.inHistory = false;
2498 mWindowManager.removeAppToken(r);
2499 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002500 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002502 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503
2504 } else {
2505 // We have the current state for this activity, so
2506 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002507 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 TAG, "Keeping entry, setting app to null");
2509 if (r.visible) {
2510 hasVisibleActivities = true;
2511 }
2512 r.app = null;
2513 r.nowVisible = false;
2514 if (!r.haveState) {
2515 r.icicle = null;
2516 }
2517 }
2518
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002519 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 r.state = ActivityState.STOPPED;
2521 }
2522 atTop = false;
2523 }
2524
2525 app.activities.clear();
2526
2527 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002528 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 + " running instrumentation " + app.instrumentationClass);
2530 Bundle info = new Bundle();
2531 info.putString("shortMsg", "Process crashed.");
2532 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2533 }
2534
2535 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002536 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 // If there was nothing to resume, and we are not already
2538 // restarting this process, but there is a visible activity that
2539 // is hosted by the process... then make sure all visible
2540 // activities are running, taking care of restarting this
2541 // process.
2542 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002543 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 }
2545 }
2546 }
2547 }
2548
2549 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2550 IBinder threadBinder = thread.asBinder();
2551
2552 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002553 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2554 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2556 return i;
2557 }
2558 }
2559 return -1;
2560 }
2561
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002562 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 IApplicationThread thread) {
2564 if (thread == null) {
2565 return null;
2566 }
2567
2568 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002569 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 }
2571
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002572 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 IApplicationThread thread) {
2574
2575 mProcDeaths[0]++;
2576
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002577 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2578 synchronized (stats) {
2579 stats.noteProcessDiedLocked(app.info.uid, pid);
2580 }
2581
Magnus Edlund7bb25812010-02-24 15:45:06 +01002582 // Clean up already done if the process has been re-started.
2583 if (app.pid == pid && app.thread != null &&
2584 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002585 if (!app.killedBackground) {
2586 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2587 + ") has died.");
2588 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002589 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002590 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 TAG, "Dying app: " + app + ", pid: " + pid
2592 + ", thread: " + thread.asBinder());
2593 boolean doLowMem = app.instrumentationClass == null;
2594 handleAppDiedLocked(app, false);
2595
2596 if (doLowMem) {
2597 // If there are no longer any background processes running,
2598 // and the app that died was not running instrumentation,
2599 // then tell everyone we are now low on memory.
2600 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002601 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2602 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2604 haveBg = true;
2605 break;
2606 }
2607 }
2608
2609 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002610 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002611 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002612 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002613 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2614 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002615 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002616 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2617 // The low memory report is overriding any current
2618 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002619 // heavy/important/visible/foreground processes first.
2620 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002621 rec.lastRequestedGc = 0;
2622 } else {
2623 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002625 rec.reportLowMemory = true;
2626 rec.lastLowMemory = now;
2627 mProcessesToGc.remove(rec);
2628 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 }
2630 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002631 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 }
2633 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002634 } else if (app.pid != pid) {
2635 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002636 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002637 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002638 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002639 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002640 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 + thread.asBinder());
2642 }
2643 }
2644
Dan Egnor42471dd2010-01-07 17:25:22 -08002645 /**
2646 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002647 * @param clearTraces causes the dump file to be erased prior to the new
2648 * traces being written, if true; when false, the new traces will be
2649 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002650 * @param pids of dalvik VM processes to dump stack traces for
2651 * @return file containing stack traces, or null if no dump file is configured
2652 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002653 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002654 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2655 if (tracesPath == null || tracesPath.length() == 0) {
2656 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002658
2659 File tracesFile = new File(tracesPath);
2660 try {
2661 File tracesDir = tracesFile.getParentFile();
2662 if (!tracesDir.exists()) tracesFile.mkdirs();
2663 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2664
Christopher Tate6ee412d2010-05-28 12:01:56 -07002665 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002666 tracesFile.createNewFile();
2667 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2668 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002669 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002670 return null;
2671 }
2672
2673 // Use a FileObserver to detect when traces finish writing.
2674 // The order of traces is considered important to maintain for legibility.
2675 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2676 public synchronized void onEvent(int event, String path) { notify(); }
2677 };
2678
2679 try {
2680 observer.startWatching();
2681 int num = pids.size();
2682 for (int i = 0; i < num; i++) {
2683 synchronized (observer) {
2684 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2685 observer.wait(200); // Wait for write-close, give up after 200msec
2686 }
2687 }
2688 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002689 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002690 } finally {
2691 observer.stopWatching();
2692 }
2693
2694 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 }
2696
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002697 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2698 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002699 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002700
2701 synchronized (this) {
2702 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2703 if (mShuttingDown) {
2704 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2705 return;
2706 } else if (app.notResponding) {
2707 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2708 return;
2709 } else if (app.crashing) {
2710 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2711 return;
2712 }
2713
2714 // In case we come through here for the same app before completing
2715 // this one, mark as anring now so we will bail out.
2716 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002717
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002718 // Log the ANR to the event log.
2719 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2720 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002721
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002722 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2723 pids.add(app.pid);
2724
2725 int parentPid = app.pid;
2726 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2727 if (parentPid != app.pid) pids.add(parentPid);
2728
2729 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002730
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002731 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2732 ProcessRecord r = mLruProcesses.get(i);
2733 if (r != null && r.thread != null) {
2734 int pid = r.pid;
2735 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 }
2738 }
2739
Christopher Tate6ee412d2010-05-28 12:01:56 -07002740 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002741
2742 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002743 StringBuilder info = mStringBuilder;
2744 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002745 info.append("ANR in ").append(app.processName);
2746 if (activity != null && activity.shortComponentName != null) {
2747 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002748 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002749 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002751 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002753 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002754 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756
Dan Egnor42471dd2010-01-07 17:25:22 -08002757 String cpuInfo = null;
2758 if (MONITOR_CPU_USAGE) {
2759 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002760 synchronized (mProcessStatsThread) {
2761 cpuInfo = mProcessStats.printCurrentState();
2762 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002763 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 }
2765
Joe Onorato8a9b2202010-02-26 18:56:32 -08002766 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002767 if (tracesFile == null) {
2768 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2769 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2770 }
2771
2772 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2773
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002774 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002776 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2777 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002779 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2780 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 }
2782 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002783 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002784 }
2785 }
2786
Dan Egnor42471dd2010-01-07 17:25:22 -08002787 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2788 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2789 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002790
2791 synchronized (this) {
2792 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2793 Process.killProcess(app.pid);
2794 return;
2795 }
2796
2797 // Set the app's notResponding state, and look up the errorReportReceiver
2798 makeAppNotRespondingLocked(app,
2799 activity != null ? activity.shortComponentName : null,
2800 annotation != null ? "ANR " + annotation : "ANR",
2801 info.toString());
2802
2803 // Bring up the infamous App Not Responding dialog
2804 Message msg = Message.obtain();
2805 HashMap map = new HashMap();
2806 msg.what = SHOW_NOT_RESPONDING_MSG;
2807 msg.obj = map;
2808 map.put("app", app);
2809 if (activity != null) {
2810 map.put("activity", activity);
2811 }
2812
2813 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 }
2816
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002817 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 app.persistentActivities--;
2819 if (app.persistentActivities > 0) {
2820 // Still more of 'em...
2821 return;
2822 }
2823 if (app.persistent) {
2824 // Ah, but the application itself is persistent. Whatever!
2825 return;
2826 }
2827
2828 // App is no longer persistent... make sure it and the ones
2829 // following it in the LRU list have the correc oom_adj.
2830 updateOomAdjLocked();
2831 }
2832
2833 public void setPersistent(IBinder token, boolean isPersistent) {
2834 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2835 != PackageManager.PERMISSION_GRANTED) {
2836 String msg = "Permission Denial: setPersistent() from pid="
2837 + Binder.getCallingPid()
2838 + ", uid=" + Binder.getCallingUid()
2839 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002840 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 throw new SecurityException(msg);
2842 }
2843
2844 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002845 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 if (index < 0) {
2847 return;
2848 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002849 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 ProcessRecord app = r.app;
2851
Joe Onorato8a9b2202010-02-26 18:56:32 -08002852 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 TAG, "Setting persistence " + isPersistent + ": " + r);
2854
2855 if (isPersistent) {
2856 if (r.persistent) {
2857 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002858 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 return;
2860 }
2861 r.persistent = true;
2862 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002863 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 if (app.persistentActivities > 1) {
2865 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002866 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 return;
2868 }
2869 if (app.persistent) {
2870 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002871 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 return;
2873 }
2874
2875 // App is now persistent... make sure it and the ones
2876 // following it now have the correct oom_adj.
2877 final long origId = Binder.clearCallingIdentity();
2878 updateOomAdjLocked();
2879 Binder.restoreCallingIdentity(origId);
2880
2881 } else {
2882 if (!r.persistent) {
2883 // Okay okay, I heard you already!
2884 return;
2885 }
2886 r.persistent = false;
2887 final long origId = Binder.clearCallingIdentity();
2888 decPersistentCountLocked(app);
2889 Binder.restoreCallingIdentity(origId);
2890
2891 }
2892 }
2893 }
2894
2895 public boolean clearApplicationUserData(final String packageName,
2896 final IPackageDataObserver observer) {
2897 int uid = Binder.getCallingUid();
2898 int pid = Binder.getCallingPid();
2899 long callingId = Binder.clearCallingIdentity();
2900 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002901 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 int pkgUid = -1;
2903 synchronized(this) {
2904 try {
2905 pkgUid = pm.getPackageUid(packageName);
2906 } catch (RemoteException e) {
2907 }
2908 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002909 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002910 return false;
2911 }
2912 if (uid == pkgUid || checkComponentPermission(
2913 android.Manifest.permission.CLEAR_APP_USER_DATA,
2914 pid, uid, -1)
2915 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002916 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 } else {
2918 throw new SecurityException(pid+" does not have permission:"+
2919 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2920 "for process:"+packageName);
2921 }
2922 }
2923
2924 try {
2925 //clear application user data
2926 pm.clearApplicationUserData(packageName, observer);
2927 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2928 Uri.fromParts("package", packageName, null));
2929 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002930 synchronized (this) {
2931 broadcastIntentLocked(null, null, intent,
2932 null, null, 0, null, null, null,
2933 false, false, MY_PID, Process.SYSTEM_UID);
2934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 } catch (RemoteException e) {
2936 }
2937 } finally {
2938 Binder.restoreCallingIdentity(callingId);
2939 }
2940 return true;
2941 }
2942
Dianne Hackborn03abb812010-01-04 18:43:19 -08002943 public void killBackgroundProcesses(final String packageName) {
2944 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2945 != PackageManager.PERMISSION_GRANTED &&
2946 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2947 != PackageManager.PERMISSION_GRANTED) {
2948 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 + Binder.getCallingPid()
2950 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002951 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002952 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 throw new SecurityException(msg);
2954 }
2955
2956 long callingId = Binder.clearCallingIdentity();
2957 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002958 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 int pkgUid = -1;
2960 synchronized(this) {
2961 try {
2962 pkgUid = pm.getPackageUid(packageName);
2963 } catch (RemoteException e) {
2964 }
2965 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002966 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002967 return;
2968 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002969 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002970 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002971 }
2972 } finally {
2973 Binder.restoreCallingIdentity(callingId);
2974 }
2975 }
2976
2977 public void forceStopPackage(final String packageName) {
2978 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2979 != PackageManager.PERMISSION_GRANTED) {
2980 String msg = "Permission Denial: forceStopPackage() from pid="
2981 + Binder.getCallingPid()
2982 + ", uid=" + Binder.getCallingUid()
2983 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002984 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002985 throw new SecurityException(msg);
2986 }
2987
2988 long callingId = Binder.clearCallingIdentity();
2989 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002990 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002991 int pkgUid = -1;
2992 synchronized(this) {
2993 try {
2994 pkgUid = pm.getPackageUid(packageName);
2995 } catch (RemoteException e) {
2996 }
2997 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002998 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002999 return;
3000 }
3001 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 }
3003 } finally {
3004 Binder.restoreCallingIdentity(callingId);
3005 }
3006 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003007
3008 /*
3009 * The pkg name and uid have to be specified.
3010 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3011 */
3012 public void killApplicationWithUid(String pkg, int uid) {
3013 if (pkg == null) {
3014 return;
3015 }
3016 // Make sure the uid is valid.
3017 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003018 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003019 return;
3020 }
3021 int callerUid = Binder.getCallingUid();
3022 // Only the system server can kill an application
3023 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003024 // Post an aysnc message to kill the application
3025 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3026 msg.arg1 = uid;
3027 msg.arg2 = 0;
3028 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003029 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003030 } else {
3031 throw new SecurityException(callerUid + " cannot kill pkg: " +
3032 pkg);
3033 }
3034 }
3035
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003036 public void closeSystemDialogs(String reason) {
3037 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3038 if (reason != null) {
3039 intent.putExtra("reason", reason);
3040 }
3041
3042 final int uid = Binder.getCallingUid();
3043 final long origId = Binder.clearCallingIdentity();
3044 synchronized (this) {
3045 int i = mWatchers.beginBroadcast();
3046 while (i > 0) {
3047 i--;
3048 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3049 if (w != null) {
3050 try {
3051 w.closingSystemDialogs(reason);
3052 } catch (RemoteException e) {
3053 }
3054 }
3055 }
3056 mWatchers.finishBroadcast();
3057
Dianne Hackbornffa42482009-09-23 22:20:11 -07003058 mWindowManager.closeSystemDialogs(reason);
3059
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003060 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3061 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003062 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003063 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003064 Activity.RESULT_CANCELED, null, "close-sys");
3065 }
3066 }
3067
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003068 broadcastIntentLocked(null, null, intent, null,
3069 null, 0, null, null, null, false, false, -1, uid);
3070 }
3071 Binder.restoreCallingIdentity(origId);
3072 }
3073
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003074 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003075 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003076 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3077 for (int i=pids.length-1; i>=0; i--) {
3078 infos[i] = new Debug.MemoryInfo();
3079 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003080 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003081 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003082 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003083
3084 public void killApplicationProcess(String processName, int uid) {
3085 if (processName == null) {
3086 return;
3087 }
3088
3089 int callerUid = Binder.getCallingUid();
3090 // Only the system server can kill an application
3091 if (callerUid == Process.SYSTEM_UID) {
3092 synchronized (this) {
3093 ProcessRecord app = getProcessRecordLocked(processName, uid);
3094 if (app != null) {
3095 try {
3096 app.thread.scheduleSuicide();
3097 } catch (RemoteException e) {
3098 // If the other end already died, then our work here is done.
3099 }
3100 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003101 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003102 + processName + " / " + uid);
3103 }
3104 }
3105 } else {
3106 throw new SecurityException(callerUid + " cannot kill app process: " +
3107 processName);
3108 }
3109 }
3110
Dianne Hackborn03abb812010-01-04 18:43:19 -08003111 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003112 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3114 Uri.fromParts("package", packageName, null));
3115 intent.putExtra(Intent.EXTRA_UID, uid);
3116 broadcastIntentLocked(null, null, intent,
3117 null, null, 0, null, null, null,
3118 false, false, MY_PID, Process.SYSTEM_UID);
3119 }
3120
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003121 private final boolean killPackageProcessesLocked(String packageName, int uid,
3122 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003123 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124
Dianne Hackborn03abb812010-01-04 18:43:19 -08003125 // Remove all processes this package may have touched: all with the
3126 // same UID (except for the system or root user), and all whose name
3127 // matches the package name.
3128 final String procNamePrefix = packageName + ":";
3129 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3130 final int NA = apps.size();
3131 for (int ia=0; ia<NA; ia++) {
3132 ProcessRecord app = apps.valueAt(ia);
3133 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003134 if (doit) {
3135 procs.add(app);
3136 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003137 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3138 || app.processName.equals(packageName)
3139 || app.processName.startsWith(procNamePrefix)) {
3140 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003141 if (!doit) {
3142 return true;
3143 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003144 app.removed = true;
3145 procs.add(app);
3146 }
3147 }
3148 }
3149 }
3150
3151 int N = procs.size();
3152 for (int i=0; i<N; i++) {
3153 removeProcessLocked(procs.get(i), callerWillRestart);
3154 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003155 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003156 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003157
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003158 private final boolean forceStopPackageLocked(String name, int uid,
3159 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 int i, N;
3161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 if (uid < 0) {
3163 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003164 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 } catch (RemoteException e) {
3166 }
3167 }
3168
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003169 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003170 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003171
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003172 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3173 while (badApps.hasNext()) {
3174 SparseArray<Long> ba = badApps.next();
3175 if (ba.get(uid) != null) {
3176 badApps.remove();
3177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 }
3179 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003180
3181 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3182 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003184 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3185 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003187 if (!doit) {
3188 return true;
3189 }
3190 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003191 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 if (r.app != null) {
3193 r.app.removed = true;
3194 }
3195 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003196 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 }
3198 }
3199
3200 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3201 for (ServiceRecord service : mServices.values()) {
3202 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003203 if (!doit) {
3204 return true;
3205 }
3206 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003207 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 if (service.app != null) {
3209 service.app.removed = true;
3210 }
3211 service.app = null;
3212 services.add(service);
3213 }
3214 }
3215
3216 N = services.size();
3217 for (i=0; i<N; i++) {
3218 bringDownServiceLocked(services.get(i), true);
3219 }
3220
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003221 if (doit) {
3222 if (purgeCache) {
3223 AttributeCache ac = AttributeCache.instance();
3224 if (ac != null) {
3225 ac.removePackage(name);
3226 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003227 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003228 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003229 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003230
3231 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 }
3233
3234 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3235 final String name = app.processName;
3236 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003237 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 TAG, "Force removing process " + app + " (" + name
3239 + "/" + uid + ")");
3240
3241 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003242 if (mHeavyWeightProcess == app) {
3243 mHeavyWeightProcess = null;
3244 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 boolean needRestart = false;
3247 if (app.pid > 0 && app.pid != MY_PID) {
3248 int pid = app.pid;
3249 synchronized (mPidsSelfLocked) {
3250 mPidsSelfLocked.remove(pid);
3251 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3252 }
3253 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003254 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 Process.killProcess(pid);
3256
3257 if (app.persistent) {
3258 if (!callerWillRestart) {
3259 addAppLocked(app.info);
3260 } else {
3261 needRestart = true;
3262 }
3263 }
3264 } else {
3265 mRemovedProcesses.add(app);
3266 }
3267
3268 return needRestart;
3269 }
3270
3271 private final void processStartTimedOutLocked(ProcessRecord app) {
3272 final int pid = app.pid;
3273 boolean gone = false;
3274 synchronized (mPidsSelfLocked) {
3275 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3276 if (knownApp != null && knownApp.thread == null) {
3277 mPidsSelfLocked.remove(pid);
3278 gone = true;
3279 }
3280 }
3281
3282 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003283 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003284 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003285 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003287 if (mHeavyWeightProcess == app) {
3288 mHeavyWeightProcess = null;
3289 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3290 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003291 // Take care of any launching providers waiting for this process.
3292 checkAppInLaunchingProvidersLocked(app, true);
3293 // Take care of any services that are waiting for the process.
3294 for (int i=0; i<mPendingServices.size(); i++) {
3295 ServiceRecord sr = mPendingServices.get(i);
3296 if (app.info.uid == sr.appInfo.uid
3297 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003298 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003299 mPendingServices.remove(i);
3300 i--;
3301 bringDownServiceLocked(sr, true);
3302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003304 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003305 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003306 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003307 try {
3308 IBackupManager bm = IBackupManager.Stub.asInterface(
3309 ServiceManager.getService(Context.BACKUP_SERVICE));
3310 bm.agentDisconnected(app.info.packageName);
3311 } catch (RemoteException e) {
3312 // Can't happen; the backup manager is local
3313 }
3314 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003315 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003316 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003317 mPendingBroadcast = null;
3318 scheduleBroadcastsLocked();
3319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003321 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 }
3323 }
3324
3325 private final boolean attachApplicationLocked(IApplicationThread thread,
3326 int pid) {
3327
3328 // Find the application record that is being attached... either via
3329 // the pid if we are running in multiple processes, or just pull the
3330 // next app record if we are emulating process with anonymous threads.
3331 ProcessRecord app;
3332 if (pid != MY_PID && pid >= 0) {
3333 synchronized (mPidsSelfLocked) {
3334 app = mPidsSelfLocked.get(pid);
3335 }
3336 } else if (mStartingProcesses.size() > 0) {
3337 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003338 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 } else {
3340 app = null;
3341 }
3342
3343 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003344 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003346 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 if (pid > 0 && pid != MY_PID) {
3348 Process.killProcess(pid);
3349 } else {
3350 try {
3351 thread.scheduleExit();
3352 } catch (Exception e) {
3353 // Ignore exceptions.
3354 }
3355 }
3356 return false;
3357 }
3358
3359 // If this application record is still attached to a previous
3360 // process, clean it up now.
3361 if (app.thread != null) {
3362 handleAppDiedLocked(app, true);
3363 }
3364
3365 // Tell the process all about itself.
3366
Joe Onorato8a9b2202010-02-26 18:56:32 -08003367 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 TAG, "Binding process pid " + pid + " to record " + app);
3369
3370 String processName = app.processName;
3371 try {
3372 thread.asBinder().linkToDeath(new AppDeathRecipient(
3373 app, pid, thread), 0);
3374 } catch (RemoteException e) {
3375 app.resetPackageList();
3376 startProcessLocked(app, "link fail", processName);
3377 return false;
3378 }
3379
Doug Zongker2bec3d42009-12-04 12:52:44 -08003380 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381
3382 app.thread = thread;
3383 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003384 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3385 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 app.forcingToForeground = null;
3387 app.foregroundServices = false;
3388 app.debugging = false;
3389
3390 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3391
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003392 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3393 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003395 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003396 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003397 }
3398
Joe Onorato8a9b2202010-02-26 18:56:32 -08003399 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 TAG, "New app record " + app
3401 + " thread=" + thread.asBinder() + " pid=" + pid);
3402 try {
3403 int testMode = IApplicationThread.DEBUG_OFF;
3404 if (mDebugApp != null && mDebugApp.equals(processName)) {
3405 testMode = mWaitForDebugger
3406 ? IApplicationThread.DEBUG_WAIT
3407 : IApplicationThread.DEBUG_ON;
3408 app.debugging = true;
3409 if (mDebugTransient) {
3410 mDebugApp = mOrigDebugApp;
3411 mWaitForDebugger = mOrigWaitForDebugger;
3412 }
3413 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003414
Christopher Tate181fafa2009-05-14 11:12:14 -07003415 // If the app is being launched for restore or full backup, set it up specially
3416 boolean isRestrictedBackupMode = false;
3417 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3418 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3419 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3420 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003421
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003422 ensurePackageDexOpt(app.instrumentationInfo != null
3423 ? app.instrumentationInfo.packageName
3424 : app.info.packageName);
3425 if (app.instrumentationClass != null) {
3426 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003427 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003428 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003429 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003430 thread.bindApplication(processName, app.instrumentationInfo != null
3431 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 app.instrumentationClass, app.instrumentationProfileFile,
3433 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003434 isRestrictedBackupMode || !normalMode,
3435 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003436 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003437 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 } catch (Exception e) {
3439 // todo: Yikes! What should we do? For now we will try to
3440 // start another process, but that could easily get us in
3441 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003442 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443
3444 app.resetPackageList();
3445 startProcessLocked(app, "bind fail", processName);
3446 return false;
3447 }
3448
3449 // Remove this record from the list of starting applications.
3450 mPersistentStartingProcesses.remove(app);
3451 mProcessesOnHold.remove(app);
3452
3453 boolean badApp = false;
3454 boolean didSomething = false;
3455
3456 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003457 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003458 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3460 && processName.equals(hr.processName)) {
3461 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003462 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463 didSomething = true;
3464 }
3465 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003466 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 + hr.intent.getComponent().flattenToShortString(), e);
3468 badApp = true;
3469 }
3470 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003471 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 }
3473 }
3474
3475 // Find any services that should be running in this process...
3476 if (!badApp && mPendingServices.size() > 0) {
3477 ServiceRecord sr = null;
3478 try {
3479 for (int i=0; i<mPendingServices.size(); i++) {
3480 sr = mPendingServices.get(i);
3481 if (app.info.uid != sr.appInfo.uid
3482 || !processName.equals(sr.processName)) {
3483 continue;
3484 }
3485
3486 mPendingServices.remove(i);
3487 i--;
3488 realStartServiceLocked(sr, app);
3489 didSomething = true;
3490 }
3491 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003492 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 + sr.shortName, e);
3494 badApp = true;
3495 }
3496 }
3497
3498 // Check if the next broadcast receiver is in this process...
3499 BroadcastRecord br = mPendingBroadcast;
3500 if (!badApp && br != null && br.curApp == app) {
3501 try {
3502 mPendingBroadcast = null;
3503 processCurBroadcastLocked(br, app);
3504 didSomething = true;
3505 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003506 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 + br.curComponent.flattenToShortString(), e);
3508 badApp = true;
3509 logBroadcastReceiverDiscard(br);
3510 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3511 br.resultExtras, br.resultAbort, true);
3512 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003513 // We need to reset the state if we fails to start the receiver.
3514 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 }
3516 }
3517
Christopher Tate181fafa2009-05-14 11:12:14 -07003518 // Check whether the next backup agent is in this process...
3519 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003520 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003521 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003522 try {
3523 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3524 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003525 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003526 e.printStackTrace();
3527 }
3528 }
3529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 if (badApp) {
3531 // todo: Also need to kill application to deal with all
3532 // kinds of exceptions.
3533 handleAppDiedLocked(app, false);
3534 return false;
3535 }
3536
3537 if (!didSomething) {
3538 updateOomAdjLocked();
3539 }
3540
3541 return true;
3542 }
3543
3544 public final void attachApplication(IApplicationThread thread) {
3545 synchronized (this) {
3546 int callingPid = Binder.getCallingPid();
3547 final long origId = Binder.clearCallingIdentity();
3548 attachApplicationLocked(thread, callingPid);
3549 Binder.restoreCallingIdentity(origId);
3550 }
3551 }
3552
Dianne Hackborne88846e2009-09-30 21:34:25 -07003553 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003555 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 Binder.restoreCallingIdentity(origId);
3557 }
3558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003560 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003561 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 mWindowManager.enableScreenAfterBoot();
3563 }
3564
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003565 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003566 IntentFilter pkgFilter = new IntentFilter();
3567 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3568 pkgFilter.addDataScheme("package");
3569 mContext.registerReceiver(new BroadcastReceiver() {
3570 @Override
3571 public void onReceive(Context context, Intent intent) {
3572 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3573 if (pkgs != null) {
3574 for (String pkg : pkgs) {
3575 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3576 setResultCode(Activity.RESULT_OK);
3577 return;
3578 }
3579 }
3580 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003581 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003582 }, pkgFilter);
3583
3584 synchronized (this) {
3585 // Ensure that any processes we had put on hold are now started
3586 // up.
3587 final int NP = mProcessesOnHold.size();
3588 if (NP > 0) {
3589 ArrayList<ProcessRecord> procs =
3590 new ArrayList<ProcessRecord>(mProcessesOnHold);
3591 for (int ip=0; ip<NP; ip++) {
3592 this.startProcessLocked(procs.get(ip), "on-hold", null);
3593 }
3594 }
3595
3596 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003597 // Start looking for apps that are abusing wake locks.
3598 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3599 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003600 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003601 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003602 broadcastIntentLocked(null, null,
3603 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3604 null, null, 0, null, null,
3605 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3606 false, false, MY_PID, Process.SYSTEM_UID);
3607 }
3608 }
3609 }
3610
3611 final void ensureBootCompleted() {
3612 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003613 boolean enableScreen;
3614 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003615 booting = mBooting;
3616 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003617 enableScreen = !mBooted;
3618 mBooted = true;
3619 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003620
3621 if (booting) {
3622 finishBooting();
3623 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003624
3625 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003626 enableScreenAfterBoot();
3627 }
3628 }
3629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 public final void activityPaused(IBinder token, Bundle icicle) {
3631 // Refuse possible leaked file descriptors
3632 if (icicle != null && icicle.hasFileDescriptors()) {
3633 throw new IllegalArgumentException("File descriptors passed in Bundle");
3634 }
3635
3636 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003637 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 Binder.restoreCallingIdentity(origId);
3639 }
3640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 public final void activityStopped(IBinder token, Bitmap thumbnail,
3642 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003643 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 TAG, "Activity stopped: token=" + token);
3645
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003646 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647
3648 final long origId = Binder.clearCallingIdentity();
3649
3650 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003651 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003653 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 r.thumbnail = thumbnail;
3655 r.description = description;
3656 r.stopped = true;
3657 r.state = ActivityState.STOPPED;
3658 if (!r.finishing) {
3659 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003660 r.stack.destroyActivityLocked(r, true);
3661 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 }
3663 }
3664 }
3665 }
3666
3667 if (r != null) {
3668 sendPendingThumbnail(r, null, null, null, false);
3669 }
3670
3671 trimApplications();
3672
3673 Binder.restoreCallingIdentity(origId);
3674 }
3675
3676 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003677 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003678 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 }
3680
3681 public String getCallingPackage(IBinder token) {
3682 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003683 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003684 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 }
3686 }
3687
3688 public ComponentName getCallingActivity(IBinder token) {
3689 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003690 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 return r != null ? r.intent.getComponent() : null;
3692 }
3693 }
3694
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003695 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003696 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003698 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 if (r != null) {
3700 return r.resultTo;
3701 }
3702 }
3703 return null;
3704 }
3705
3706 public ComponentName getActivityClassForToken(IBinder token) {
3707 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003708 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003710 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 return r.intent.getComponent();
3712 }
3713 return null;
3714 }
3715 }
3716
3717 public String getPackageForToken(IBinder token) {
3718 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003719 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003721 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 return r.packageName;
3723 }
3724 return null;
3725 }
3726 }
3727
3728 public IIntentSender getIntentSender(int type,
3729 String packageName, IBinder token, String resultWho,
3730 int requestCode, Intent intent, String resolvedType, int flags) {
3731 // Refuse possible leaked file descriptors
3732 if (intent != null && intent.hasFileDescriptors() == true) {
3733 throw new IllegalArgumentException("File descriptors passed in Intent");
3734 }
3735
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003736 if (type == INTENT_SENDER_BROADCAST) {
3737 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3738 throw new IllegalArgumentException(
3739 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3740 }
3741 }
3742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 synchronized(this) {
3744 int callingUid = Binder.getCallingUid();
3745 try {
3746 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3747 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003748 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 .getPackageUid(packageName);
3750 if (uid != Binder.getCallingUid()) {
3751 String msg = "Permission Denial: getIntentSender() from pid="
3752 + Binder.getCallingPid()
3753 + ", uid=" + Binder.getCallingUid()
3754 + ", (need uid=" + uid + ")"
3755 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003756 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 throw new SecurityException(msg);
3758 }
3759 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003760
3761 return getIntentSenderLocked(type, packageName, callingUid,
3762 token, resultWho, requestCode, intent, resolvedType, flags);
3763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 } catch (RemoteException e) {
3765 throw new SecurityException(e);
3766 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003767 }
3768 }
3769
3770 IIntentSender getIntentSenderLocked(int type,
3771 String packageName, int callingUid, IBinder token, String resultWho,
3772 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003773 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003774 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003775 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003776 if (index < 0) {
3777 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003779 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003780 if (activity.finishing) {
3781 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003783 }
3784
3785 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3786 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3787 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3788 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3789 |PendingIntent.FLAG_UPDATE_CURRENT);
3790
3791 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3792 type, packageName, activity, resultWho,
3793 requestCode, intent, resolvedType, flags);
3794 WeakReference<PendingIntentRecord> ref;
3795 ref = mIntentSenderRecords.get(key);
3796 PendingIntentRecord rec = ref != null ? ref.get() : null;
3797 if (rec != null) {
3798 if (!cancelCurrent) {
3799 if (updateCurrent) {
3800 rec.key.requestIntent.replaceExtras(intent);
3801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 return rec;
3803 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003804 rec.canceled = true;
3805 mIntentSenderRecords.remove(key);
3806 }
3807 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 return rec;
3809 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003810 rec = new PendingIntentRecord(this, key, callingUid);
3811 mIntentSenderRecords.put(key, rec.ref);
3812 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3813 if (activity.pendingResults == null) {
3814 activity.pendingResults
3815 = new HashSet<WeakReference<PendingIntentRecord>>();
3816 }
3817 activity.pendingResults.add(rec.ref);
3818 }
3819 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 }
3821
3822 public void cancelIntentSender(IIntentSender sender) {
3823 if (!(sender instanceof PendingIntentRecord)) {
3824 return;
3825 }
3826 synchronized(this) {
3827 PendingIntentRecord rec = (PendingIntentRecord)sender;
3828 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003829 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 .getPackageUid(rec.key.packageName);
3831 if (uid != Binder.getCallingUid()) {
3832 String msg = "Permission Denial: cancelIntentSender() from pid="
3833 + Binder.getCallingPid()
3834 + ", uid=" + Binder.getCallingUid()
3835 + " is not allowed to cancel packges "
3836 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003837 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 throw new SecurityException(msg);
3839 }
3840 } catch (RemoteException e) {
3841 throw new SecurityException(e);
3842 }
3843 cancelIntentSenderLocked(rec, true);
3844 }
3845 }
3846
3847 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3848 rec.canceled = true;
3849 mIntentSenderRecords.remove(rec.key);
3850 if (cleanActivity && rec.key.activity != null) {
3851 rec.key.activity.pendingResults.remove(rec.ref);
3852 }
3853 }
3854
3855 public String getPackageForIntentSender(IIntentSender pendingResult) {
3856 if (!(pendingResult instanceof PendingIntentRecord)) {
3857 return null;
3858 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003859 try {
3860 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3861 return res.key.packageName;
3862 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 }
3864 return null;
3865 }
3866
3867 public void setProcessLimit(int max) {
3868 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3869 "setProcessLimit()");
3870 mProcessLimit = max;
3871 }
3872
3873 public int getProcessLimit() {
3874 return mProcessLimit;
3875 }
3876
3877 void foregroundTokenDied(ForegroundToken token) {
3878 synchronized (ActivityManagerService.this) {
3879 synchronized (mPidsSelfLocked) {
3880 ForegroundToken cur
3881 = mForegroundProcesses.get(token.pid);
3882 if (cur != token) {
3883 return;
3884 }
3885 mForegroundProcesses.remove(token.pid);
3886 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3887 if (pr == null) {
3888 return;
3889 }
3890 pr.forcingToForeground = null;
3891 pr.foregroundServices = false;
3892 }
3893 updateOomAdjLocked();
3894 }
3895 }
3896
3897 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3898 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3899 "setProcessForeground()");
3900 synchronized(this) {
3901 boolean changed = false;
3902
3903 synchronized (mPidsSelfLocked) {
3904 ProcessRecord pr = mPidsSelfLocked.get(pid);
3905 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003906 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003907 return;
3908 }
3909 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3910 if (oldToken != null) {
3911 oldToken.token.unlinkToDeath(oldToken, 0);
3912 mForegroundProcesses.remove(pid);
3913 pr.forcingToForeground = null;
3914 changed = true;
3915 }
3916 if (isForeground && token != null) {
3917 ForegroundToken newToken = new ForegroundToken() {
3918 public void binderDied() {
3919 foregroundTokenDied(this);
3920 }
3921 };
3922 newToken.pid = pid;
3923 newToken.token = token;
3924 try {
3925 token.linkToDeath(newToken, 0);
3926 mForegroundProcesses.put(pid, newToken);
3927 pr.forcingToForeground = token;
3928 changed = true;
3929 } catch (RemoteException e) {
3930 // If the process died while doing this, we will later
3931 // do the cleanup with the process death link.
3932 }
3933 }
3934 }
3935
3936 if (changed) {
3937 updateOomAdjLocked();
3938 }
3939 }
3940 }
3941
3942 // =========================================================
3943 // PERMISSIONS
3944 // =========================================================
3945
3946 static class PermissionController extends IPermissionController.Stub {
3947 ActivityManagerService mActivityManagerService;
3948 PermissionController(ActivityManagerService activityManagerService) {
3949 mActivityManagerService = activityManagerService;
3950 }
3951
3952 public boolean checkPermission(String permission, int pid, int uid) {
3953 return mActivityManagerService.checkPermission(permission, pid,
3954 uid) == PackageManager.PERMISSION_GRANTED;
3955 }
3956 }
3957
3958 /**
3959 * This can be called with or without the global lock held.
3960 */
3961 int checkComponentPermission(String permission, int pid, int uid,
3962 int reqUid) {
3963 // We might be performing an operation on behalf of an indirect binder
3964 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3965 // client identity accordingly before proceeding.
3966 Identity tlsIdentity = sCallerIdentity.get();
3967 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003968 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3970 uid = tlsIdentity.uid;
3971 pid = tlsIdentity.pid;
3972 }
3973
3974 // Root, system server and our own process get to do everything.
3975 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3976 !Process.supportsProcesses()) {
3977 return PackageManager.PERMISSION_GRANTED;
3978 }
3979 // If the target requires a specific UID, always fail for others.
3980 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003981 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 return PackageManager.PERMISSION_DENIED;
3983 }
3984 if (permission == null) {
3985 return PackageManager.PERMISSION_GRANTED;
3986 }
3987 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003988 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 .checkUidPermission(permission, uid);
3990 } catch (RemoteException e) {
3991 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003992 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 }
3994 return PackageManager.PERMISSION_DENIED;
3995 }
3996
3997 /**
3998 * As the only public entry point for permissions checking, this method
3999 * can enforce the semantic that requesting a check on a null global
4000 * permission is automatically denied. (Internally a null permission
4001 * string is used when calling {@link #checkComponentPermission} in cases
4002 * when only uid-based security is needed.)
4003 *
4004 * This can be called with or without the global lock held.
4005 */
4006 public int checkPermission(String permission, int pid, int uid) {
4007 if (permission == null) {
4008 return PackageManager.PERMISSION_DENIED;
4009 }
4010 return checkComponentPermission(permission, pid, uid, -1);
4011 }
4012
4013 /**
4014 * Binder IPC calls go through the public entry point.
4015 * This can be called with or without the global lock held.
4016 */
4017 int checkCallingPermission(String permission) {
4018 return checkPermission(permission,
4019 Binder.getCallingPid(),
4020 Binder.getCallingUid());
4021 }
4022
4023 /**
4024 * This can be called with or without the global lock held.
4025 */
4026 void enforceCallingPermission(String permission, String func) {
4027 if (checkCallingPermission(permission)
4028 == PackageManager.PERMISSION_GRANTED) {
4029 return;
4030 }
4031
4032 String msg = "Permission Denial: " + func + " from pid="
4033 + Binder.getCallingPid()
4034 + ", uid=" + Binder.getCallingUid()
4035 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004036 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 throw new SecurityException(msg);
4038 }
4039
4040 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4041 ProviderInfo pi, int uid, int modeFlags) {
4042 try {
4043 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4044 if ((pi.readPermission != null) &&
4045 (pm.checkUidPermission(pi.readPermission, uid)
4046 != PackageManager.PERMISSION_GRANTED)) {
4047 return false;
4048 }
4049 }
4050 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4051 if ((pi.writePermission != null) &&
4052 (pm.checkUidPermission(pi.writePermission, uid)
4053 != PackageManager.PERMISSION_GRANTED)) {
4054 return false;
4055 }
4056 }
4057 return true;
4058 } catch (RemoteException e) {
4059 return false;
4060 }
4061 }
4062
4063 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4064 int modeFlags) {
4065 // Root gets to do everything.
4066 if (uid == 0 || !Process.supportsProcesses()) {
4067 return true;
4068 }
4069 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4070 if (perms == null) return false;
4071 UriPermission perm = perms.get(uri);
4072 if (perm == null) return false;
4073 return (modeFlags&perm.modeFlags) == modeFlags;
4074 }
4075
4076 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4077 // Another redirected-binder-call permissions check as in
4078 // {@link checkComponentPermission}.
4079 Identity tlsIdentity = sCallerIdentity.get();
4080 if (tlsIdentity != null) {
4081 uid = tlsIdentity.uid;
4082 pid = tlsIdentity.pid;
4083 }
4084
4085 // Our own process gets to do everything.
4086 if (pid == MY_PID) {
4087 return PackageManager.PERMISSION_GRANTED;
4088 }
4089 synchronized(this) {
4090 return checkUriPermissionLocked(uri, uid, modeFlags)
4091 ? PackageManager.PERMISSION_GRANTED
4092 : PackageManager.PERMISSION_DENIED;
4093 }
4094 }
4095
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004096 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004097 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4099 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4100 if (modeFlags == 0) {
4101 return;
4102 }
4103
Joe Onorato8a9b2202010-02-26 18:56:32 -08004104 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004105 "Requested grant " + targetPkg + " permission to " + uri);
4106
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004107 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108
4109 // If this is not a content: uri, we can't do anything with it.
4110 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004112 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 return;
4114 }
4115
4116 String name = uri.getAuthority();
4117 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004118 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004119 if (cpr != null) {
4120 pi = cpr.info;
4121 } else {
4122 try {
4123 pi = pm.resolveContentProvider(name,
4124 PackageManager.GET_URI_PERMISSION_PATTERNS);
4125 } catch (RemoteException ex) {
4126 }
4127 }
4128 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004129 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 return;
4131 }
4132
4133 int targetUid;
4134 try {
4135 targetUid = pm.getPackageUid(targetPkg);
4136 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004137 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004138 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139 return;
4140 }
4141 } catch (RemoteException ex) {
4142 return;
4143 }
4144
4145 // First... does the target actually need this permission?
4146 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4147 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004148 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004149 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 return;
4151 }
4152
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004153 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 if (!pi.grantUriPermissions) {
4155 throw new SecurityException("Provider " + pi.packageName
4156 + "/" + pi.name
4157 + " does not allow granting of Uri permissions (uri "
4158 + uri + ")");
4159 }
4160 if (pi.uriPermissionPatterns != null) {
4161 final int N = pi.uriPermissionPatterns.length;
4162 boolean allowed = false;
4163 for (int i=0; i<N; i++) {
4164 if (pi.uriPermissionPatterns[i] != null
4165 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4166 allowed = true;
4167 break;
4168 }
4169 }
4170 if (!allowed) {
4171 throw new SecurityException("Provider " + pi.packageName
4172 + "/" + pi.name
4173 + " does not allow granting of permission to path of Uri "
4174 + uri);
4175 }
4176 }
4177
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004178 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 // this uri?
4180 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4181 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4182 throw new SecurityException("Uid " + callingUid
4183 + " does not have permission to uri " + uri);
4184 }
4185 }
4186
4187 // Okay! So here we are: the caller has the assumed permission
4188 // to the uri, and the target doesn't. Let's now give this to
4189 // the target.
4190
Joe Onorato8a9b2202010-02-26 18:56:32 -08004191 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004192 "Granting " + targetPkg + " permission to " + uri);
4193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 HashMap<Uri, UriPermission> targetUris
4195 = mGrantedUriPermissions.get(targetUid);
4196 if (targetUris == null) {
4197 targetUris = new HashMap<Uri, UriPermission>();
4198 mGrantedUriPermissions.put(targetUid, targetUris);
4199 }
4200
4201 UriPermission perm = targetUris.get(uri);
4202 if (perm == null) {
4203 perm = new UriPermission(targetUid, uri);
4204 targetUris.put(uri, perm);
4205
4206 }
4207 perm.modeFlags |= modeFlags;
4208 if (activity == null) {
4209 perm.globalModeFlags |= modeFlags;
4210 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4211 perm.readActivities.add(activity);
4212 if (activity.readUriPermissions == null) {
4213 activity.readUriPermissions = new HashSet<UriPermission>();
4214 }
4215 activity.readUriPermissions.add(perm);
4216 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4217 perm.writeActivities.add(activity);
4218 if (activity.writeUriPermissions == null) {
4219 activity.writeUriPermissions = new HashSet<UriPermission>();
4220 }
4221 activity.writeUriPermissions.add(perm);
4222 }
4223 }
4224
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004225 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004226 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 if (intent == null) {
4228 return;
4229 }
4230 Uri data = intent.getData();
4231 if (data == null) {
4232 return;
4233 }
4234 grantUriPermissionLocked(callingUid, targetPkg, data,
4235 intent.getFlags(), activity);
4236 }
4237
4238 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4239 Uri uri, int modeFlags) {
4240 synchronized(this) {
4241 final ProcessRecord r = getRecordForAppLocked(caller);
4242 if (r == null) {
4243 throw new SecurityException("Unable to find app for caller "
4244 + caller
4245 + " when granting permission to uri " + uri);
4246 }
4247 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004248 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 return;
4250 }
4251 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004252 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 return;
4254 }
4255
4256 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4257 null);
4258 }
4259 }
4260
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004261 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4263 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4264 HashMap<Uri, UriPermission> perms
4265 = mGrantedUriPermissions.get(perm.uid);
4266 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004267 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004268 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 perms.remove(perm.uri);
4270 if (perms.size() == 0) {
4271 mGrantedUriPermissions.remove(perm.uid);
4272 }
4273 }
4274 }
4275 }
4276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4278 int modeFlags) {
4279 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4280 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4281 if (modeFlags == 0) {
4282 return;
4283 }
4284
Joe Onorato8a9b2202010-02-26 18:56:32 -08004285 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004286 "Revoking all granted permissions to " + uri);
4287
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004288 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289
4290 final String authority = uri.getAuthority();
4291 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004292 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 if (cpr != null) {
4294 pi = cpr.info;
4295 } else {
4296 try {
4297 pi = pm.resolveContentProvider(authority,
4298 PackageManager.GET_URI_PERMISSION_PATTERNS);
4299 } catch (RemoteException ex) {
4300 }
4301 }
4302 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004303 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 return;
4305 }
4306
4307 // Does the caller have this permission on the URI?
4308 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4309 // Right now, if you are not the original owner of the permission,
4310 // you are not allowed to revoke it.
4311 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4312 throw new SecurityException("Uid " + callingUid
4313 + " does not have permission to uri " + uri);
4314 //}
4315 }
4316
4317 // Go through all of the permissions and remove any that match.
4318 final List<String> SEGMENTS = uri.getPathSegments();
4319 if (SEGMENTS != null) {
4320 final int NS = SEGMENTS.size();
4321 int N = mGrantedUriPermissions.size();
4322 for (int i=0; i<N; i++) {
4323 HashMap<Uri, UriPermission> perms
4324 = mGrantedUriPermissions.valueAt(i);
4325 Iterator<UriPermission> it = perms.values().iterator();
4326 toploop:
4327 while (it.hasNext()) {
4328 UriPermission perm = it.next();
4329 Uri targetUri = perm.uri;
4330 if (!authority.equals(targetUri.getAuthority())) {
4331 continue;
4332 }
4333 List<String> targetSegments = targetUri.getPathSegments();
4334 if (targetSegments == null) {
4335 continue;
4336 }
4337 if (targetSegments.size() < NS) {
4338 continue;
4339 }
4340 for (int j=0; j<NS; j++) {
4341 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4342 continue toploop;
4343 }
4344 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004345 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004346 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 perm.clearModes(modeFlags);
4348 if (perm.modeFlags == 0) {
4349 it.remove();
4350 }
4351 }
4352 if (perms.size() == 0) {
4353 mGrantedUriPermissions.remove(
4354 mGrantedUriPermissions.keyAt(i));
4355 N--;
4356 i--;
4357 }
4358 }
4359 }
4360 }
4361
4362 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4363 int modeFlags) {
4364 synchronized(this) {
4365 final ProcessRecord r = getRecordForAppLocked(caller);
4366 if (r == null) {
4367 throw new SecurityException("Unable to find app for caller "
4368 + caller
4369 + " when revoking permission to uri " + uri);
4370 }
4371 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004372 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 return;
4374 }
4375
4376 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4377 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4378 if (modeFlags == 0) {
4379 return;
4380 }
4381
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004382 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383
4384 final String authority = uri.getAuthority();
4385 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004386 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 if (cpr != null) {
4388 pi = cpr.info;
4389 } else {
4390 try {
4391 pi = pm.resolveContentProvider(authority,
4392 PackageManager.GET_URI_PERMISSION_PATTERNS);
4393 } catch (RemoteException ex) {
4394 }
4395 }
4396 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004397 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 return;
4399 }
4400
4401 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4402 }
4403 }
4404
4405 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4406 synchronized (this) {
4407 ProcessRecord app =
4408 who != null ? getRecordForAppLocked(who) : null;
4409 if (app == null) return;
4410
4411 Message msg = Message.obtain();
4412 msg.what = WAIT_FOR_DEBUGGER_MSG;
4413 msg.obj = app;
4414 msg.arg1 = waiting ? 1 : 0;
4415 mHandler.sendMessage(msg);
4416 }
4417 }
4418
4419 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4420 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004421 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004423 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 }
4425
4426 // =========================================================
4427 // TASK MANAGEMENT
4428 // =========================================================
4429
4430 public List getTasks(int maxNum, int flags,
4431 IThumbnailReceiver receiver) {
4432 ArrayList list = new ArrayList();
4433
4434 PendingThumbnailsRecord pending = null;
4435 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004436 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437
4438 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004439 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4441 + ", receiver=" + receiver);
4442
4443 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4444 != PackageManager.PERMISSION_GRANTED) {
4445 if (receiver != null) {
4446 // If the caller wants to wait for pending thumbnails,
4447 // it ain't gonna get them.
4448 try {
4449 receiver.finished();
4450 } catch (RemoteException ex) {
4451 }
4452 }
4453 String msg = "Permission Denial: getTasks() from pid="
4454 + Binder.getCallingPid()
4455 + ", uid=" + Binder.getCallingUid()
4456 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004457 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 throw new SecurityException(msg);
4459 }
4460
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004461 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004462 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004463 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004464 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 CharSequence topDescription = null;
4466 TaskRecord curTask = null;
4467 int numActivities = 0;
4468 int numRunning = 0;
4469 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004470 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004472 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473
4474 // Initialize state for next task if needed.
4475 if (top == null ||
4476 (top.state == ActivityState.INITIALIZING
4477 && top.task == r.task)) {
4478 top = r;
4479 topDescription = r.description;
4480 curTask = r.task;
4481 numActivities = numRunning = 0;
4482 }
4483
4484 // Add 'r' into the current task.
4485 numActivities++;
4486 if (r.app != null && r.app.thread != null) {
4487 numRunning++;
4488 }
4489 if (topDescription == null) {
4490 topDescription = r.description;
4491 }
4492
Joe Onorato8a9b2202010-02-26 18:56:32 -08004493 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 TAG, r.intent.getComponent().flattenToShortString()
4495 + ": task=" + r.task);
4496
4497 // If the next one is a different task, generate a new
4498 // TaskInfo entry for what we have.
4499 if (next == null || next.task != curTask) {
4500 ActivityManager.RunningTaskInfo ci
4501 = new ActivityManager.RunningTaskInfo();
4502 ci.id = curTask.taskId;
4503 ci.baseActivity = r.intent.getComponent();
4504 ci.topActivity = top.intent.getComponent();
4505 ci.thumbnail = top.thumbnail;
4506 ci.description = topDescription;
4507 ci.numActivities = numActivities;
4508 ci.numRunning = numRunning;
4509 //System.out.println(
4510 // "#" + maxNum + ": " + " descr=" + ci.description);
4511 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004512 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 TAG, "State=" + top.state + "Idle=" + top.idle
4514 + " app=" + top.app
4515 + " thr=" + (top.app != null ? top.app.thread : null));
4516 if (top.state == ActivityState.RESUMED
4517 || top.state == ActivityState.PAUSING) {
4518 if (top.idle && top.app != null
4519 && top.app.thread != null) {
4520 topRecord = top;
4521 topThumbnail = top.app.thread;
4522 } else {
4523 top.thumbnailNeeded = true;
4524 }
4525 }
4526 if (pending == null) {
4527 pending = new PendingThumbnailsRecord(receiver);
4528 }
4529 pending.pendingRecords.add(top);
4530 }
4531 list.add(ci);
4532 maxNum--;
4533 top = null;
4534 }
4535 }
4536
4537 if (pending != null) {
4538 mPendingThumbnails.add(pending);
4539 }
4540 }
4541
Joe Onorato8a9b2202010-02-26 18:56:32 -08004542 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004543
4544 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004545 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 try {
4547 topThumbnail.requestThumbnail(topRecord);
4548 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004549 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 sendPendingThumbnail(null, topRecord, null, null, true);
4551 }
4552 }
4553
4554 if (pending == null && receiver != null) {
4555 // In this case all thumbnails were available and the client
4556 // is being asked to be told when the remaining ones come in...
4557 // which is unusually, since the top-most currently running
4558 // activity should never have a canned thumbnail! Oh well.
4559 try {
4560 receiver.finished();
4561 } catch (RemoteException ex) {
4562 }
4563 }
4564
4565 return list;
4566 }
4567
4568 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4569 int flags) {
4570 synchronized (this) {
4571 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4572 "getRecentTasks()");
4573
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004574 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 final int N = mRecentTasks.size();
4577 ArrayList<ActivityManager.RecentTaskInfo> res
4578 = new ArrayList<ActivityManager.RecentTaskInfo>(
4579 maxNum < N ? maxNum : N);
4580 for (int i=0; i<N && maxNum > 0; i++) {
4581 TaskRecord tr = mRecentTasks.get(i);
4582 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4583 || (tr.intent == null)
4584 || ((tr.intent.getFlags()
4585 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4586 ActivityManager.RecentTaskInfo rti
4587 = new ActivityManager.RecentTaskInfo();
4588 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4589 rti.baseIntent = new Intent(
4590 tr.intent != null ? tr.intent : tr.affinityIntent);
4591 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004592
4593 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4594 // Check whether this activity is currently available.
4595 try {
4596 if (rti.origActivity != null) {
4597 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4598 continue;
4599 }
4600 } else if (rti.baseIntent != null) {
4601 if (pm.queryIntentActivities(rti.baseIntent,
4602 null, 0) == null) {
4603 continue;
4604 }
4605 }
4606 } catch (RemoteException e) {
4607 // Will never happen.
4608 }
4609 }
4610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 res.add(rti);
4612 maxNum--;
4613 }
4614 }
4615 return res;
4616 }
4617 }
4618
4619 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4620 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004621 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 TaskRecord jt = startTask;
4623
4624 // First look backwards
4625 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004626 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 if (r.task != jt) {
4628 jt = r.task;
4629 if (affinity.equals(jt.affinity)) {
4630 return j;
4631 }
4632 }
4633 }
4634
4635 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004636 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 jt = startTask;
4638 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004639 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 if (r.task != jt) {
4641 if (affinity.equals(jt.affinity)) {
4642 return j;
4643 }
4644 jt = r.task;
4645 }
4646 }
4647
4648 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004649 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 return N-1;
4651 }
4652
4653 return -1;
4654 }
4655
4656 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004657 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 */
4659 public void moveTaskToFront(int task) {
4660 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4661 "moveTaskToFront()");
4662
4663 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004664 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4665 Binder.getCallingUid(), "Task to front")) {
4666 return;
4667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 final long origId = Binder.clearCallingIdentity();
4669 try {
4670 int N = mRecentTasks.size();
4671 for (int i=0; i<N; i++) {
4672 TaskRecord tr = mRecentTasks.get(i);
4673 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004674 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 return;
4676 }
4677 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004678 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4679 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004681 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 return;
4683 }
4684 }
4685 } finally {
4686 Binder.restoreCallingIdentity(origId);
4687 }
4688 }
4689 }
4690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 public void moveTaskToBack(int task) {
4692 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4693 "moveTaskToBack()");
4694
4695 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004696 if (mMainStack.mResumedActivity != null
4697 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004698 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4699 Binder.getCallingUid(), "Task to back")) {
4700 return;
4701 }
4702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004704 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 Binder.restoreCallingIdentity(origId);
4706 }
4707 }
4708
4709 /**
4710 * Moves an activity, and all of the other activities within the same task, to the bottom
4711 * of the history stack. The activity's order within the task is unchanged.
4712 *
4713 * @param token A reference to the activity we wish to move
4714 * @param nonRoot If false then this only works if the activity is the root
4715 * of a task; if true it will work for any activity in a task.
4716 * @return Returns true if the move completed, false if not.
4717 */
4718 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4719 synchronized(this) {
4720 final long origId = Binder.clearCallingIdentity();
4721 int taskId = getTaskForActivityLocked(token, !nonRoot);
4722 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004723 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 }
4725 Binder.restoreCallingIdentity(origId);
4726 }
4727 return false;
4728 }
4729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 public void moveTaskBackwards(int task) {
4731 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4732 "moveTaskBackwards()");
4733
4734 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004735 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4736 Binder.getCallingUid(), "Task backwards")) {
4737 return;
4738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 final long origId = Binder.clearCallingIdentity();
4740 moveTaskBackwardsLocked(task);
4741 Binder.restoreCallingIdentity(origId);
4742 }
4743 }
4744
4745 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004746 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 }
4748
4749 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4750 synchronized(this) {
4751 return getTaskForActivityLocked(token, onlyRoot);
4752 }
4753 }
4754
4755 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004756 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 TaskRecord lastTask = null;
4758 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004759 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 if (r == token) {
4761 if (!onlyRoot || lastTask != r.task) {
4762 return r.task.taskId;
4763 }
4764 return -1;
4765 }
4766 lastTask = r.task;
4767 }
4768
4769 return -1;
4770 }
4771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004772 public void finishOtherInstances(IBinder token, ComponentName className) {
4773 synchronized(this) {
4774 final long origId = Binder.clearCallingIdentity();
4775
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004776 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 TaskRecord lastTask = null;
4778 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004779 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 if (r.realActivity.equals(className)
4781 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004782 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 null, "others")) {
4784 i--;
4785 N--;
4786 }
4787 }
4788 lastTask = r.task;
4789 }
4790
4791 Binder.restoreCallingIdentity(origId);
4792 }
4793 }
4794
4795 // =========================================================
4796 // THUMBNAILS
4797 // =========================================================
4798
4799 public void reportThumbnail(IBinder token,
4800 Bitmap thumbnail, CharSequence description) {
4801 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4802 final long origId = Binder.clearCallingIdentity();
4803 sendPendingThumbnail(null, token, thumbnail, description, true);
4804 Binder.restoreCallingIdentity(origId);
4805 }
4806
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004807 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 Bitmap thumbnail, CharSequence description, boolean always) {
4809 TaskRecord task = null;
4810 ArrayList receivers = null;
4811
4812 //System.out.println("Send pending thumbnail: " + r);
4813
4814 synchronized(this) {
4815 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004816 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 if (index < 0) {
4818 return;
4819 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004820 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 }
4822 if (thumbnail == null) {
4823 thumbnail = r.thumbnail;
4824 description = r.description;
4825 }
4826 if (thumbnail == null && !always) {
4827 // If there is no thumbnail, and this entry is not actually
4828 // going away, then abort for now and pick up the next
4829 // thumbnail we get.
4830 return;
4831 }
4832 task = r.task;
4833
4834 int N = mPendingThumbnails.size();
4835 int i=0;
4836 while (i<N) {
4837 PendingThumbnailsRecord pr =
4838 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4839 //System.out.println("Looking in " + pr.pendingRecords);
4840 if (pr.pendingRecords.remove(r)) {
4841 if (receivers == null) {
4842 receivers = new ArrayList();
4843 }
4844 receivers.add(pr);
4845 if (pr.pendingRecords.size() == 0) {
4846 pr.finished = true;
4847 mPendingThumbnails.remove(i);
4848 N--;
4849 continue;
4850 }
4851 }
4852 i++;
4853 }
4854 }
4855
4856 if (receivers != null) {
4857 final int N = receivers.size();
4858 for (int i=0; i<N; i++) {
4859 try {
4860 PendingThumbnailsRecord pr =
4861 (PendingThumbnailsRecord)receivers.get(i);
4862 pr.receiver.newThumbnail(
4863 task != null ? task.taskId : -1, thumbnail, description);
4864 if (pr.finished) {
4865 pr.receiver.finished();
4866 }
4867 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004868 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 }
4870 }
4871 }
4872 }
4873
4874 // =========================================================
4875 // CONTENT PROVIDERS
4876 // =========================================================
4877
4878 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4879 List providers = null;
4880 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004881 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004883 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 } catch (RemoteException ex) {
4885 }
4886 if (providers != null) {
4887 final int N = providers.size();
4888 for (int i=0; i<N; i++) {
4889 ProviderInfo cpi =
4890 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004891 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 if (cpr == null) {
4893 cpr = new ContentProviderRecord(cpi, app.info);
4894 mProvidersByClass.put(cpi.name, cpr);
4895 }
4896 app.pubProviders.put(cpi.name, cpr);
4897 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004898 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 }
4900 }
4901 return providers;
4902 }
4903
4904 private final String checkContentProviderPermissionLocked(
4905 ProviderInfo cpi, ProcessRecord r, int mode) {
4906 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4907 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4908 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4909 cpi.exported ? -1 : cpi.applicationInfo.uid)
4910 == PackageManager.PERMISSION_GRANTED
4911 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4912 return null;
4913 }
4914 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4915 cpi.exported ? -1 : cpi.applicationInfo.uid)
4916 == PackageManager.PERMISSION_GRANTED) {
4917 return null;
4918 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004919
4920 PathPermission[] pps = cpi.pathPermissions;
4921 if (pps != null) {
4922 int i = pps.length;
4923 while (i > 0) {
4924 i--;
4925 PathPermission pp = pps[i];
4926 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4927 cpi.exported ? -1 : cpi.applicationInfo.uid)
4928 == PackageManager.PERMISSION_GRANTED
4929 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4930 return null;
4931 }
4932 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4933 cpi.exported ? -1 : cpi.applicationInfo.uid)
4934 == PackageManager.PERMISSION_GRANTED) {
4935 return null;
4936 }
4937 }
4938 }
4939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 String msg = "Permission Denial: opening provider " + cpi.name
4941 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4942 + ", uid=" + callingUid + ") requires "
4943 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 return msg;
4946 }
4947
4948 private final ContentProviderHolder getContentProviderImpl(
4949 IApplicationThread caller, String name) {
4950 ContentProviderRecord cpr;
4951 ProviderInfo cpi = null;
4952
4953 synchronized(this) {
4954 ProcessRecord r = null;
4955 if (caller != null) {
4956 r = getRecordForAppLocked(caller);
4957 if (r == null) {
4958 throw new SecurityException(
4959 "Unable to find app for caller " + caller
4960 + " (pid=" + Binder.getCallingPid()
4961 + ") when getting content provider " + name);
4962 }
4963 }
4964
4965 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004966 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 if (cpr != null) {
4968 cpi = cpr.info;
4969 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4970 return new ContentProviderHolder(cpi,
4971 cpi.readPermission != null
4972 ? cpi.readPermission : cpi.writePermission);
4973 }
4974
4975 if (r != null && cpr.canRunHere(r)) {
4976 // This provider has been published or is in the process
4977 // of being published... but it is also allowed to run
4978 // in the caller's process, so don't make a connection
4979 // and just let the caller instantiate its own instance.
4980 if (cpr.provider != null) {
4981 // don't give caller the provider object, it needs
4982 // to make its own.
4983 cpr = new ContentProviderRecord(cpr);
4984 }
4985 return cpr;
4986 }
4987
4988 final long origId = Binder.clearCallingIdentity();
4989
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004990 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004991 // return it right away.
4992 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004993 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004994 "Adding provider requested by "
4995 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004996 + cpr.info.processName);
4997 Integer cnt = r.conProviders.get(cpr);
4998 if (cnt == null) {
4999 r.conProviders.put(cpr, new Integer(1));
5000 } else {
5001 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005004 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5005 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005006 // make sure to count it as being accessed and thus
5007 // back up on the LRU list. This is good because
5008 // content providers are often expensive to start.
5009 updateLruProcessLocked(cpr.app, false, true);
5010 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005011 } else {
5012 cpr.externals++;
5013 }
5014
5015 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 updateOomAdjLocked(cpr.app);
5017 }
5018
5019 Binder.restoreCallingIdentity(origId);
5020
5021 } else {
5022 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005023 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005024 resolveContentProvider(name,
5025 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 } catch (RemoteException ex) {
5027 }
5028 if (cpi == null) {
5029 return null;
5030 }
5031
5032 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
5033 return new ContentProviderHolder(cpi,
5034 cpi.readPermission != null
5035 ? cpi.readPermission : cpi.writePermission);
5036 }
5037
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005038 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5039 && !cpi.processName.equals("system")) {
5040 // If this content provider does not run in the system
5041 // process, and the system is not yet ready to run other
5042 // processes, then fail fast instead of hanging.
5043 throw new IllegalArgumentException(
5044 "Attempt to launch content provider before system ready");
5045 }
5046
Dianne Hackborn860755f2010-06-03 18:47:52 -07005047 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 final boolean firstClass = cpr == null;
5049 if (firstClass) {
5050 try {
5051 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005052 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 getApplicationInfo(
5054 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005055 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005057 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 + cpi.name);
5059 return null;
5060 }
5061 cpr = new ContentProviderRecord(cpi, ai);
5062 } catch (RemoteException ex) {
5063 // pm is in same process, this will never happen.
5064 }
5065 }
5066
5067 if (r != null && cpr.canRunHere(r)) {
5068 // If this is a multiprocess provider, then just return its
5069 // info and allow the caller to instantiate it. Only do
5070 // this if the provider is the same user as the caller's
5071 // process, or can run as root (so can be in any process).
5072 return cpr;
5073 }
5074
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005075 if (DEBUG_PROVIDER) {
5076 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005077 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005078 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 }
5080
5081 // This is single process, and our app is now connecting to it.
5082 // See if we are already in the process of launching this
5083 // provider.
5084 final int N = mLaunchingProviders.size();
5085 int i;
5086 for (i=0; i<N; i++) {
5087 if (mLaunchingProviders.get(i) == cpr) {
5088 break;
5089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 }
5091
5092 // If the provider is not already being launched, then get it
5093 // started.
5094 if (i >= N) {
5095 final long origId = Binder.clearCallingIdentity();
5096 ProcessRecord proc = startProcessLocked(cpi.processName,
5097 cpr.appInfo, false, 0, "content provider",
5098 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005099 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005101 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 + cpi.applicationInfo.packageName + "/"
5103 + cpi.applicationInfo.uid + " for provider "
5104 + name + ": process is bad");
5105 return null;
5106 }
5107 cpr.launchingApp = proc;
5108 mLaunchingProviders.add(cpr);
5109 Binder.restoreCallingIdentity(origId);
5110 }
5111
5112 // Make sure the provider is published (the same provider class
5113 // may be published under multiple names).
5114 if (firstClass) {
5115 mProvidersByClass.put(cpi.name, cpr);
5116 }
5117 mProvidersByName.put(name, cpr);
5118
5119 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005120 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005121 "Adding provider requested by "
5122 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005123 + cpr.info.processName);
5124 Integer cnt = r.conProviders.get(cpr);
5125 if (cnt == null) {
5126 r.conProviders.put(cpr, new Integer(1));
5127 } else {
5128 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 cpr.clients.add(r);
5131 } else {
5132 cpr.externals++;
5133 }
5134 }
5135 }
5136
5137 // Wait for the provider to be published...
5138 synchronized (cpr) {
5139 while (cpr.provider == null) {
5140 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005141 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 + cpi.applicationInfo.packageName + "/"
5143 + cpi.applicationInfo.uid + " for provider "
5144 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005145 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 cpi.applicationInfo.packageName,
5147 cpi.applicationInfo.uid, name);
5148 return null;
5149 }
5150 try {
5151 cpr.wait();
5152 } catch (InterruptedException ex) {
5153 }
5154 }
5155 }
5156 return cpr;
5157 }
5158
5159 public final ContentProviderHolder getContentProvider(
5160 IApplicationThread caller, String name) {
5161 if (caller == null) {
5162 String msg = "null IApplicationThread when getting content provider "
5163 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 throw new SecurityException(msg);
5166 }
5167
5168 return getContentProviderImpl(caller, name);
5169 }
5170
5171 private ContentProviderHolder getContentProviderExternal(String name) {
5172 return getContentProviderImpl(null, name);
5173 }
5174
5175 /**
5176 * Drop a content provider from a ProcessRecord's bookkeeping
5177 * @param cpr
5178 */
5179 public void removeContentProvider(IApplicationThread caller, String name) {
5180 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005181 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005183 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005184 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005185 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 return;
5187 }
5188 final ProcessRecord r = getRecordForAppLocked(caller);
5189 if (r == null) {
5190 throw new SecurityException(
5191 "Unable to find app for caller " + caller +
5192 " when removing content provider " + name);
5193 }
5194 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005195 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005196 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005197 + r.info.processName + " from process "
5198 + localCpr.appInfo.processName);
5199 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005201 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005202 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 return;
5204 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005205 Integer cnt = r.conProviders.get(localCpr);
5206 if (cnt == null || cnt.intValue() <= 1) {
5207 localCpr.clients.remove(r);
5208 r.conProviders.remove(localCpr);
5209 } else {
5210 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 }
5213 updateOomAdjLocked();
5214 }
5215 }
5216
5217 private void removeContentProviderExternal(String name) {
5218 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005219 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 if(cpr == null) {
5221 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005222 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 return;
5224 }
5225
5226 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005227 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 localCpr.externals--;
5229 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005230 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 }
5232 updateOomAdjLocked();
5233 }
5234 }
5235
5236 public final void publishContentProviders(IApplicationThread caller,
5237 List<ContentProviderHolder> providers) {
5238 if (providers == null) {
5239 return;
5240 }
5241
5242 synchronized(this) {
5243 final ProcessRecord r = getRecordForAppLocked(caller);
5244 if (r == null) {
5245 throw new SecurityException(
5246 "Unable to find app for caller " + caller
5247 + " (pid=" + Binder.getCallingPid()
5248 + ") when publishing content providers");
5249 }
5250
5251 final long origId = Binder.clearCallingIdentity();
5252
5253 final int N = providers.size();
5254 for (int i=0; i<N; i++) {
5255 ContentProviderHolder src = providers.get(i);
5256 if (src == null || src.info == null || src.provider == null) {
5257 continue;
5258 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005259 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 if (dst != null) {
5261 mProvidersByClass.put(dst.info.name, dst);
5262 String names[] = dst.info.authority.split(";");
5263 for (int j = 0; j < names.length; j++) {
5264 mProvidersByName.put(names[j], dst);
5265 }
5266
5267 int NL = mLaunchingProviders.size();
5268 int j;
5269 for (j=0; j<NL; j++) {
5270 if (mLaunchingProviders.get(j) == dst) {
5271 mLaunchingProviders.remove(j);
5272 j--;
5273 NL--;
5274 }
5275 }
5276 synchronized (dst) {
5277 dst.provider = src.provider;
5278 dst.app = r;
5279 dst.notifyAll();
5280 }
5281 updateOomAdjLocked(r);
5282 }
5283 }
5284
5285 Binder.restoreCallingIdentity(origId);
5286 }
5287 }
5288
5289 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005290 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005291 synchronized (mSelf) {
5292 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5293 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005294 if (providers != null) {
5295 for (int i=providers.size()-1; i>=0; i--) {
5296 ProviderInfo pi = (ProviderInfo)providers.get(i);
5297 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5298 Slog.w(TAG, "Not installing system proc provider " + pi.name
5299 + ": not system .apk");
5300 providers.remove(i);
5301 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005302 }
5303 }
5304 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005305 if (providers != null) {
5306 mSystemThread.installSystemProviders(providers);
5307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 }
5309
5310 // =========================================================
5311 // GLOBAL MANAGEMENT
5312 // =========================================================
5313
5314 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5315 ApplicationInfo info, String customProcess) {
5316 String proc = customProcess != null ? customProcess : info.processName;
5317 BatteryStatsImpl.Uid.Proc ps = null;
5318 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5319 synchronized (stats) {
5320 ps = stats.getProcessStatsLocked(info.uid, proc);
5321 }
5322 return new ProcessRecord(ps, thread, info, proc);
5323 }
5324
5325 final ProcessRecord addAppLocked(ApplicationInfo info) {
5326 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5327
5328 if (app == null) {
5329 app = newProcessRecordLocked(null, info, null);
5330 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005331 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 }
5333
5334 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5335 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5336 app.persistent = true;
5337 app.maxAdj = CORE_SERVER_ADJ;
5338 }
5339 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5340 mPersistentStartingProcesses.add(app);
5341 startProcessLocked(app, "added application", app.processName);
5342 }
5343
5344 return app;
5345 }
5346
5347 public void unhandledBack() {
5348 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5349 "unhandledBack()");
5350
5351 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005352 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005353 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 TAG, "Performing unhandledBack(): stack size = " + count);
5355 if (count > 1) {
5356 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005357 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5359 Binder.restoreCallingIdentity(origId);
5360 }
5361 }
5362 }
5363
5364 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5365 String name = uri.getAuthority();
5366 ContentProviderHolder cph = getContentProviderExternal(name);
5367 ParcelFileDescriptor pfd = null;
5368 if (cph != null) {
5369 // We record the binder invoker's uid in thread-local storage before
5370 // going to the content provider to open the file. Later, in the code
5371 // that handles all permissions checks, we look for this uid and use
5372 // that rather than the Activity Manager's own uid. The effect is that
5373 // we do the check against the caller's permissions even though it looks
5374 // to the content provider like the Activity Manager itself is making
5375 // the request.
5376 sCallerIdentity.set(new Identity(
5377 Binder.getCallingPid(), Binder.getCallingUid()));
5378 try {
5379 pfd = cph.provider.openFile(uri, "r");
5380 } catch (FileNotFoundException e) {
5381 // do nothing; pfd will be returned null
5382 } finally {
5383 // Ensure that whatever happens, we clean up the identity state
5384 sCallerIdentity.remove();
5385 }
5386
5387 // We've got the fd now, so we're done with the provider.
5388 removeContentProviderExternal(name);
5389 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005390 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 }
5392 return pfd;
5393 }
5394
5395 public void goingToSleep() {
5396 synchronized(this) {
5397 mSleeping = true;
5398 mWindowManager.setEventDispatching(false);
5399
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005400 if (mMainStack.mResumedActivity != null) {
5401 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005403 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005405
5406 // Initialize the wake times of all processes.
5407 checkExcessiveWakeLocksLocked(false);
5408 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5409 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5410 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 }
5412 }
5413
Dianne Hackborn55280a92009-05-07 15:53:46 -07005414 public boolean shutdown(int timeout) {
5415 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5416 != PackageManager.PERMISSION_GRANTED) {
5417 throw new SecurityException("Requires permission "
5418 + android.Manifest.permission.SHUTDOWN);
5419 }
5420
5421 boolean timedout = false;
5422
5423 synchronized(this) {
5424 mShuttingDown = true;
5425 mWindowManager.setEventDispatching(false);
5426
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005427 if (mMainStack.mResumedActivity != null) {
5428 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005429 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005430 while (mMainStack.mResumedActivity != null
5431 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005432 long delay = endTime - System.currentTimeMillis();
5433 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005434 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005435 timedout = true;
5436 break;
5437 }
5438 try {
5439 this.wait();
5440 } catch (InterruptedException e) {
5441 }
5442 }
5443 }
5444 }
5445
5446 mUsageStatsService.shutdown();
5447 mBatteryStatsService.shutdown();
5448
5449 return timedout;
5450 }
5451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005452 public void wakingUp() {
5453 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005454 if (mMainStack.mGoingToSleep.isHeld()) {
5455 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 }
5457 mWindowManager.setEventDispatching(true);
5458 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005459 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005460 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005461 }
5462 }
5463
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005464 public void stopAppSwitches() {
5465 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5466 != PackageManager.PERMISSION_GRANTED) {
5467 throw new SecurityException("Requires permission "
5468 + android.Manifest.permission.STOP_APP_SWITCHES);
5469 }
5470
5471 synchronized(this) {
5472 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5473 + APP_SWITCH_DELAY_TIME;
5474 mDidAppSwitch = false;
5475 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5476 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5477 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5478 }
5479 }
5480
5481 public void resumeAppSwitches() {
5482 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5483 != PackageManager.PERMISSION_GRANTED) {
5484 throw new SecurityException("Requires permission "
5485 + android.Manifest.permission.STOP_APP_SWITCHES);
5486 }
5487
5488 synchronized(this) {
5489 // Note that we don't execute any pending app switches... we will
5490 // let those wait until either the timeout, or the next start
5491 // activity request.
5492 mAppSwitchesAllowedTime = 0;
5493 }
5494 }
5495
5496 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5497 String name) {
5498 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5499 return true;
5500 }
5501
5502 final int perm = checkComponentPermission(
5503 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5504 callingUid, -1);
5505 if (perm == PackageManager.PERMISSION_GRANTED) {
5506 return true;
5507 }
5508
Joe Onorato8a9b2202010-02-26 18:56:32 -08005509 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005510 return false;
5511 }
5512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 public void setDebugApp(String packageName, boolean waitForDebugger,
5514 boolean persistent) {
5515 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5516 "setDebugApp()");
5517
5518 // Note that this is not really thread safe if there are multiple
5519 // callers into it at the same time, but that's not a situation we
5520 // care about.
5521 if (persistent) {
5522 final ContentResolver resolver = mContext.getContentResolver();
5523 Settings.System.putString(
5524 resolver, Settings.System.DEBUG_APP,
5525 packageName);
5526 Settings.System.putInt(
5527 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5528 waitForDebugger ? 1 : 0);
5529 }
5530
5531 synchronized (this) {
5532 if (!persistent) {
5533 mOrigDebugApp = mDebugApp;
5534 mOrigWaitForDebugger = mWaitForDebugger;
5535 }
5536 mDebugApp = packageName;
5537 mWaitForDebugger = waitForDebugger;
5538 mDebugTransient = !persistent;
5539 if (packageName != null) {
5540 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005541 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 Binder.restoreCallingIdentity(origId);
5543 }
5544 }
5545 }
5546
5547 public void setAlwaysFinish(boolean enabled) {
5548 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5549 "setAlwaysFinish()");
5550
5551 Settings.System.putInt(
5552 mContext.getContentResolver(),
5553 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5554
5555 synchronized (this) {
5556 mAlwaysFinishActivities = enabled;
5557 }
5558 }
5559
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005560 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005562 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005564 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 }
5566 }
5567
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005568 public boolean isUserAMonkey() {
5569 // For now the fact that there is a controller implies
5570 // we have a monkey.
5571 synchronized (this) {
5572 return mController != null;
5573 }
5574 }
5575
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005576 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005577 synchronized (this) {
5578 mWatchers.register(watcher);
5579 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005580 }
5581
5582 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005583 synchronized (this) {
5584 mWatchers.unregister(watcher);
5585 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005586 }
5587
Daniel Sandler69a48172010-06-23 16:29:36 -04005588 public void setImmersive(IBinder token, boolean immersive) {
5589 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005590 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005591 if (index < 0) {
5592 throw new IllegalArgumentException();
5593 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005594 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005595 r.immersive = immersive;
5596 }
5597 }
5598
5599 public boolean isImmersive(IBinder token) {
5600 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005601 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005602 if (index < 0) {
5603 throw new IllegalArgumentException();
5604 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005605 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005606 return r.immersive;
5607 }
5608 }
5609
5610 public boolean isTopActivityImmersive() {
5611 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005612 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005613 return (r != null) ? r.immersive : false;
5614 }
5615 }
5616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 public final void enterSafeMode() {
5618 synchronized(this) {
5619 // It only makes sense to do this before the system is ready
5620 // and started launching other packages.
5621 if (!mSystemReady) {
5622 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005623 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 } catch (RemoteException e) {
5625 }
5626
5627 View v = LayoutInflater.from(mContext).inflate(
5628 com.android.internal.R.layout.safe_mode, null);
5629 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5630 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5631 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5632 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5633 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5634 lp.format = v.getBackground().getOpacity();
5635 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5636 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5637 ((WindowManager)mContext.getSystemService(
5638 Context.WINDOW_SERVICE)).addView(v, lp);
5639 }
5640 }
5641 }
5642
5643 public void noteWakeupAlarm(IIntentSender sender) {
5644 if (!(sender instanceof PendingIntentRecord)) {
5645 return;
5646 }
5647 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5648 synchronized (stats) {
5649 if (mBatteryStatsService.isOnBattery()) {
5650 mBatteryStatsService.enforceCallingPermission();
5651 PendingIntentRecord rec = (PendingIntentRecord)sender;
5652 int MY_UID = Binder.getCallingUid();
5653 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5654 BatteryStatsImpl.Uid.Pkg pkg =
5655 stats.getPackageStatsLocked(uid, rec.key.packageName);
5656 pkg.incWakeupsLocked();
5657 }
5658 }
5659 }
5660
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005661 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005663 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005664 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005665 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 // XXX Note: don't acquire main activity lock here, because the window
5667 // manager calls in with its locks held.
5668
5669 boolean killed = false;
5670 synchronized (mPidsSelfLocked) {
5671 int[] types = new int[pids.length];
5672 int worstType = 0;
5673 for (int i=0; i<pids.length; i++) {
5674 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5675 if (proc != null) {
5676 int type = proc.setAdj;
5677 types[i] = type;
5678 if (type > worstType) {
5679 worstType = type;
5680 }
5681 }
5682 }
5683
5684 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5685 // then constrain it so we will kill all hidden procs.
5686 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5687 worstType = HIDDEN_APP_MIN_ADJ;
5688 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005689 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 for (int i=0; i<pids.length; i++) {
5691 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5692 if (proc == null) {
5693 continue;
5694 }
5695 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005696 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005697 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005698 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5699 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005701 proc.killedBackground = true;
5702 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 }
5704 }
5705 }
5706 return killed;
5707 }
5708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 public final void startRunning(String pkg, String cls, String action,
5710 String data) {
5711 synchronized(this) {
5712 if (mStartRunning) {
5713 return;
5714 }
5715 mStartRunning = true;
5716 mTopComponent = pkg != null && cls != null
5717 ? new ComponentName(pkg, cls) : null;
5718 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5719 mTopData = data;
5720 if (!mSystemReady) {
5721 return;
5722 }
5723 }
5724
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005725 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 }
5727
5728 private void retrieveSettings() {
5729 final ContentResolver resolver = mContext.getContentResolver();
5730 String debugApp = Settings.System.getString(
5731 resolver, Settings.System.DEBUG_APP);
5732 boolean waitForDebugger = Settings.System.getInt(
5733 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5734 boolean alwaysFinishActivities = Settings.System.getInt(
5735 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5736
5737 Configuration configuration = new Configuration();
5738 Settings.System.getConfiguration(resolver, configuration);
5739
5740 synchronized (this) {
5741 mDebugApp = mOrigDebugApp = debugApp;
5742 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5743 mAlwaysFinishActivities = alwaysFinishActivities;
5744 // This happens before any activities are started, so we can
5745 // change mConfiguration in-place.
5746 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005747 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005748 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 }
5750 }
5751
5752 public boolean testIsSystemReady() {
5753 // no need to synchronize(this) just to read & return the value
5754 return mSystemReady;
5755 }
5756
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005757 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 // In the simulator, startRunning will never have been called, which
5759 // normally sets a few crucial variables. Do it here instead.
5760 if (!Process.supportsProcesses()) {
5761 mStartRunning = true;
5762 mTopAction = Intent.ACTION_MAIN;
5763 }
5764
5765 synchronized(this) {
5766 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005767 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768 return;
5769 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005770
5771 // Check to see if there are any update receivers to run.
5772 if (!mDidUpdate) {
5773 if (mWaitingUpdate) {
5774 return;
5775 }
5776 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5777 List<ResolveInfo> ris = null;
5778 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005779 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005780 intent, null, 0);
5781 } catch (RemoteException e) {
5782 }
5783 if (ris != null) {
5784 for (int i=ris.size()-1; i>=0; i--) {
5785 if ((ris.get(i).activityInfo.applicationInfo.flags
5786 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5787 ris.remove(i);
5788 }
5789 }
5790 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5791 for (int i=0; i<ris.size(); i++) {
5792 ActivityInfo ai = ris.get(i).activityInfo;
5793 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5794 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005795 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005796 finisher = new IIntentReceiver.Stub() {
5797 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005798 String data, Bundle extras, boolean ordered,
5799 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005800 throws RemoteException {
5801 synchronized (ActivityManagerService.this) {
5802 mDidUpdate = true;
5803 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005804 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005805 }
5806 };
5807 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005808 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005809 broadcastIntentLocked(null, null, intent, null, finisher,
5810 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005811 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005812 mWaitingUpdate = true;
5813 }
5814 }
5815 }
5816 if (mWaitingUpdate) {
5817 return;
5818 }
5819 mDidUpdate = true;
5820 }
5821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 mSystemReady = true;
5823 if (!mStartRunning) {
5824 return;
5825 }
5826 }
5827
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005828 ArrayList<ProcessRecord> procsToKill = null;
5829 synchronized(mPidsSelfLocked) {
5830 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5831 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5832 if (!isAllowedWhileBooting(proc.info)){
5833 if (procsToKill == null) {
5834 procsToKill = new ArrayList<ProcessRecord>();
5835 }
5836 procsToKill.add(proc);
5837 }
5838 }
5839 }
5840
5841 if (procsToKill != null) {
5842 synchronized(this) {
5843 for (int i=procsToKill.size()-1; i>=0; i--) {
5844 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005845 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005846 removeProcessLocked(proc, true);
5847 }
5848 }
5849 }
5850
Joe Onorato8a9b2202010-02-26 18:56:32 -08005851 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005852 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 SystemClock.uptimeMillis());
5854
5855 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005856 // Make sure we have no pre-ready processes sitting around.
5857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5859 ResolveInfo ri = mContext.getPackageManager()
5860 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005861 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 CharSequence errorMsg = null;
5863 if (ri != null) {
5864 ActivityInfo ai = ri.activityInfo;
5865 ApplicationInfo app = ai.applicationInfo;
5866 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5867 mTopAction = Intent.ACTION_FACTORY_TEST;
5868 mTopData = null;
5869 mTopComponent = new ComponentName(app.packageName,
5870 ai.name);
5871 } else {
5872 errorMsg = mContext.getResources().getText(
5873 com.android.internal.R.string.factorytest_not_system);
5874 }
5875 } else {
5876 errorMsg = mContext.getResources().getText(
5877 com.android.internal.R.string.factorytest_no_action);
5878 }
5879 if (errorMsg != null) {
5880 mTopAction = null;
5881 mTopData = null;
5882 mTopComponent = null;
5883 Message msg = Message.obtain();
5884 msg.what = SHOW_FACTORY_ERROR_MSG;
5885 msg.getData().putCharSequence("msg", errorMsg);
5886 mHandler.sendMessage(msg);
5887 }
5888 }
5889 }
5890
5891 retrieveSettings();
5892
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005893 if (goingCallback != null) goingCallback.run();
5894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 synchronized (this) {
5896 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5897 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005898 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005899 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 if (apps != null) {
5901 int N = apps.size();
5902 int i;
5903 for (i=0; i<N; i++) {
5904 ApplicationInfo info
5905 = (ApplicationInfo)apps.get(i);
5906 if (info != null &&
5907 !info.packageName.equals("android")) {
5908 addAppLocked(info);
5909 }
5910 }
5911 }
5912 } catch (RemoteException ex) {
5913 // pm is in same process, this will never happen.
5914 }
5915 }
5916
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005917 // Start up initial activity.
5918 mBooting = true;
5919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005921 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 Message msg = Message.obtain();
5923 msg.what = SHOW_UID_ERROR_MSG;
5924 mHandler.sendMessage(msg);
5925 }
5926 } catch (RemoteException e) {
5927 }
5928
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005929 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 }
5931 }
5932
Dan Egnorb7f03672009-12-09 16:22:32 -08005933 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005934 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005936 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005937 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 startAppProblemLocked(app);
5939 app.stopFreezingAllLocked();
5940 return handleAppCrashLocked(app);
5941 }
5942
Dan Egnorb7f03672009-12-09 16:22:32 -08005943 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005944 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005945 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005946 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005947 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5948 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 startAppProblemLocked(app);
5950 app.stopFreezingAllLocked();
5951 }
5952
5953 /**
5954 * Generate a process error record, suitable for attachment to a ProcessRecord.
5955 *
5956 * @param app The ProcessRecord in which the error occurred.
5957 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5958 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005959 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 * @param shortMsg Short message describing the crash.
5961 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005962 * @param stackTrace Full crash stack trace, may be null.
5963 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 * @return Returns a fully-formed AppErrorStateInfo record.
5965 */
5966 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005967 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 report.condition = condition;
5971 report.processName = app.processName;
5972 report.pid = app.pid;
5973 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005974 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 report.shortMsg = shortMsg;
5976 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005977 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978
5979 return report;
5980 }
5981
Dan Egnor42471dd2010-01-07 17:25:22 -08005982 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005983 synchronized (this) {
5984 app.crashing = false;
5985 app.crashingReport = null;
5986 app.notResponding = false;
5987 app.notRespondingReport = null;
5988 if (app.anrDialog == fromDialog) {
5989 app.anrDialog = null;
5990 }
5991 if (app.waitDialog == fromDialog) {
5992 app.waitDialog = null;
5993 }
5994 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005995 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07005996 Slog.i(ActivityManagerService.TAG, "Killing "
5997 + app.processName + " (pid=" + app.pid + "): user's request");
5998 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
5999 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 Process.killProcess(app.pid);
6001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 }
6003 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006004
Dan Egnorb7f03672009-12-09 16:22:32 -08006005 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006006 long now = SystemClock.uptimeMillis();
6007
6008 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6009 app.info.uid);
6010 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6011 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006012 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006014 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 app.info.processName, app.info.uid);
6016 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006017 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6018 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006020 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006021 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006022 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 }
6024 }
6025 if (!app.persistent) {
6026 // We don't want to start this process again until the user
6027 // explicitly does so... but for persistent process, we really
6028 // need to keep it running. If a persistent process is actually
6029 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006030 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 app.info.processName);
6032 mBadProcesses.put(app.info.processName, app.info.uid, now);
6033 app.bad = true;
6034 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6035 app.removed = true;
6036 removeProcessLocked(app, false);
6037 return false;
6038 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006039 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006040 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006041 if (r.app == app) {
6042 // If the top running activity is from this crashing
6043 // process, then terminate it to avoid getting in a loop.
6044 Slog.w(TAG, " Force finishing activity "
6045 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006046 int index = mMainStack.indexOfTokenLocked(r);
6047 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006048 Activity.RESULT_CANCELED, null, "crashed");
6049 // Also terminate an activities below it that aren't yet
6050 // stopped, to avoid a situation where one will get
6051 // re-start our crashing activity once it gets resumed again.
6052 index--;
6053 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006054 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006055 if (r.state == ActivityState.RESUMED
6056 || r.state == ActivityState.PAUSING
6057 || r.state == ActivityState.PAUSED) {
6058 if (!r.isHomeActivity) {
6059 Slog.w(TAG, " Force finishing activity "
6060 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006061 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006062 Activity.RESULT_CANCELED, null, "crashed");
6063 }
6064 }
6065 }
6066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 }
6068
6069 // Bump up the crash count of any services currently running in the proc.
6070 if (app.services.size() != 0) {
6071 // Any services running in the application need to be placed
6072 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006073 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006074 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006075 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006076 sr.crashCount++;
6077 }
6078 }
6079
6080 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6081 return true;
6082 }
6083
6084 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006085 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6086 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 skipCurrentReceiverLocked(app);
6088 }
6089
6090 void skipCurrentReceiverLocked(ProcessRecord app) {
6091 boolean reschedule = false;
6092 BroadcastRecord r = app.curReceiver;
6093 if (r != null) {
6094 // The current broadcast is waiting for this app's receiver
6095 // to be finished. Looks like that's not going to happen, so
6096 // let the broadcast continue.
6097 logBroadcastReceiverDiscard(r);
6098 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6099 r.resultExtras, r.resultAbort, true);
6100 reschedule = true;
6101 }
6102 r = mPendingBroadcast;
6103 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006104 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006105 "skip & discard pending app " + r);
6106 logBroadcastReceiverDiscard(r);
6107 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6108 r.resultExtras, r.resultAbort, true);
6109 reschedule = true;
6110 }
6111 if (reschedule) {
6112 scheduleBroadcastsLocked();
6113 }
6114 }
6115
Dan Egnor60d87622009-12-16 16:32:58 -08006116 /**
6117 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6118 * The application process will exit immediately after this call returns.
6119 * @param app object of the crashing app, null for the system server
6120 * @param crashInfo describing the exception
6121 */
6122 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6123 ProcessRecord r = findAppProcess(app);
6124
6125 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6126 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006127 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006128 crashInfo.exceptionClassName,
6129 crashInfo.exceptionMessage,
6130 crashInfo.throwFileName,
6131 crashInfo.throwLineNumber);
6132
Dan Egnor42471dd2010-01-07 17:25:22 -08006133 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006134
6135 crashApplication(r, crashInfo);
6136 }
6137
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006138 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006139 IBinder app,
6140 int violationMask,
6141 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006142 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006143
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006144 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006145 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006146 boolean logIt = true;
6147 synchronized (mAlreadyLoggedViolatedStacks) {
6148 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6149 logIt = false;
6150 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006151 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006152 // the relative pain numbers, without logging all
6153 // the stack traces repeatedly. We'd want to do
6154 // likewise in the client code, which also does
6155 // dup suppression, before the Binder call.
6156 } else {
6157 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6158 mAlreadyLoggedViolatedStacks.clear();
6159 }
6160 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6161 }
6162 }
6163 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006164 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006165 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006166 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006167
6168 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6169 AppErrorResult result = new AppErrorResult();
6170 synchronized (this) {
6171 final long origId = Binder.clearCallingIdentity();
6172
6173 Message msg = Message.obtain();
6174 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6175 HashMap<String, Object> data = new HashMap<String, Object>();
6176 data.put("result", result);
6177 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006178 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006179 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006180 msg.obj = data;
6181 mHandler.sendMessage(msg);
6182
6183 Binder.restoreCallingIdentity(origId);
6184 }
6185 int res = result.get();
6186 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6187 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006188 }
6189
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006190 // Depending on the policy in effect, there could be a bunch of
6191 // these in quick succession so we try to batch these together to
6192 // minimize disk writes, number of dropbox entries, and maximize
6193 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006194 private void logStrictModeViolationToDropBox(
6195 ProcessRecord process,
6196 StrictMode.ViolationInfo info) {
6197 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006198 return;
6199 }
6200 final boolean isSystemApp = process == null ||
6201 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6202 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6203 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6204 final DropBoxManager dbox = (DropBoxManager)
6205 mContext.getSystemService(Context.DROPBOX_SERVICE);
6206
6207 // Exit early if the dropbox isn't configured to accept this report type.
6208 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6209
6210 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006211 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006212 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6213 synchronized (sb) {
6214 bufferWasEmpty = sb.length() == 0;
6215 appendDropBoxProcessHeaders(process, sb);
6216 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6217 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006218 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6219 if (info.violationNumThisLoop != 0) {
6220 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6221 }
6222 if (info != null && info.durationMillis != -1) {
6223 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006224 }
6225 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006226 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6227 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006228 }
6229 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006230
6231 // Only buffer up to ~64k. Various logging bits truncate
6232 // things at 128k.
6233 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006234 }
6235
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006236 // Flush immediately if the buffer's grown too large, or this
6237 // is a non-system app. Non-system apps are isolated with a
6238 // different tag & policy and not batched.
6239 //
6240 // Batching is useful during internal testing with
6241 // StrictMode settings turned up high. Without batching,
6242 // thousands of separate files could be created on boot.
6243 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006244 new Thread("Error dump: " + dropboxTag) {
6245 @Override
6246 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006247 String report;
6248 synchronized (sb) {
6249 report = sb.toString();
6250 sb.delete(0, sb.length());
6251 sb.trimToSize();
6252 }
6253 if (report.length() != 0) {
6254 dbox.addText(dropboxTag, report);
6255 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006256 }
6257 }.start();
6258 return;
6259 }
6260
6261 // System app batching:
6262 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006263 // An existing dropbox-writing thread is outstanding, so
6264 // we don't need to start it up. The existing thread will
6265 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006266 return;
6267 }
6268
6269 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6270 // (After this point, we shouldn't access AMS internal data structures.)
6271 new Thread("Error dump: " + dropboxTag) {
6272 @Override
6273 public void run() {
6274 // 5 second sleep to let stacks arrive and be batched together
6275 try {
6276 Thread.sleep(5000); // 5 seconds
6277 } catch (InterruptedException e) {}
6278
6279 String errorReport;
6280 synchronized (mStrictModeBuffer) {
6281 errorReport = mStrictModeBuffer.toString();
6282 if (errorReport.length() == 0) {
6283 return;
6284 }
6285 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6286 mStrictModeBuffer.trimToSize();
6287 }
6288 dbox.addText(dropboxTag, errorReport);
6289 }
6290 }.start();
6291 }
6292
Dan Egnor60d87622009-12-16 16:32:58 -08006293 /**
6294 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6295 * @param app object of the crashing app, null for the system server
6296 * @param tag reported by the caller
6297 * @param crashInfo describing the context of the error
6298 * @return true if the process should exit immediately (WTF is fatal)
6299 */
6300 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006301 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006302 ProcessRecord r = findAppProcess(app);
6303
6304 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6305 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006306 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006307 tag, crashInfo.exceptionMessage);
6308
Dan Egnor42471dd2010-01-07 17:25:22 -08006309 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006310
Doug Zongker43866e02010-01-07 12:09:54 -08006311 if (Settings.Secure.getInt(mContext.getContentResolver(),
6312 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006313 crashApplication(r, crashInfo);
6314 return true;
6315 } else {
6316 return false;
6317 }
6318 }
6319
6320 /**
6321 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6322 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6323 */
6324 private ProcessRecord findAppProcess(IBinder app) {
6325 if (app == null) {
6326 return null;
6327 }
6328
6329 synchronized (this) {
6330 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6331 final int NA = apps.size();
6332 for (int ia=0; ia<NA; ia++) {
6333 ProcessRecord p = apps.valueAt(ia);
6334 if (p.thread != null && p.thread.asBinder() == app) {
6335 return p;
6336 }
6337 }
6338 }
6339
Joe Onorato8a9b2202010-02-26 18:56:32 -08006340 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006341 return null;
6342 }
6343 }
6344
6345 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006346 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6347 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006348 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006349 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006350 if (process == null || process.pid == MY_PID) {
6351 sb.append("Process: system_server\n");
6352 } else {
6353 sb.append("Process: ").append(process.processName).append("\n");
6354 }
6355 if (process != null) {
6356 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006357 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006358 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6359 for (String pkg : process.pkgList) {
6360 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006361 try {
Dan Egnora455d192010-03-12 08:52:28 -08006362 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6363 if (pi != null) {
6364 sb.append(" v").append(pi.versionCode);
6365 if (pi.versionName != null) {
6366 sb.append(" (").append(pi.versionName).append(")");
6367 }
6368 }
6369 } catch (RemoteException e) {
6370 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006371 }
Dan Egnora455d192010-03-12 08:52:28 -08006372 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006373 }
Dan Egnora455d192010-03-12 08:52:28 -08006374 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006375 }
6376
6377 private static String processClass(ProcessRecord process) {
6378 if (process == null || process.pid == MY_PID) {
6379 return "system_server";
6380 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6381 return "system_app";
6382 } else {
6383 return "data_app";
6384 }
6385 }
6386
6387 /**
6388 * Write a description of an error (crash, WTF, ANR) to the drop box.
6389 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6390 * @param process which caused the error, null means the system server
6391 * @param activity which triggered the error, null if unknown
6392 * @param parent activity related to the error, null if unknown
6393 * @param subject line related to the error, null if absent
6394 * @param report in long form describing the error, null if absent
6395 * @param logFile to include in the report, null if none
6396 * @param crashInfo giving an application stack trace, null if absent
6397 */
6398 public void addErrorToDropBox(String eventType,
6399 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6400 final String report, final File logFile,
6401 final ApplicationErrorReport.CrashInfo crashInfo) {
6402 // NOTE -- this must never acquire the ActivityManagerService lock,
6403 // otherwise the watchdog may be prevented from resetting the system.
6404
6405 final String dropboxTag = processClass(process) + "_" + eventType;
6406 final DropBoxManager dbox = (DropBoxManager)
6407 mContext.getSystemService(Context.DROPBOX_SERVICE);
6408
6409 // Exit early if the dropbox isn't configured to accept this report type.
6410 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6411
6412 final StringBuilder sb = new StringBuilder(1024);
6413 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006414 if (activity != null) {
6415 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6416 }
6417 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6418 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6419 }
6420 if (parent != null && parent != activity) {
6421 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6422 }
6423 if (subject != null) {
6424 sb.append("Subject: ").append(subject).append("\n");
6425 }
6426 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6427 sb.append("\n");
6428
6429 // Do the rest in a worker thread to avoid blocking the caller on I/O
6430 // (After this point, we shouldn't access AMS internal data structures.)
6431 Thread worker = new Thread("Error dump: " + dropboxTag) {
6432 @Override
6433 public void run() {
6434 if (report != null) {
6435 sb.append(report);
6436 }
6437 if (logFile != null) {
6438 try {
6439 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6440 } catch (IOException e) {
6441 Slog.e(TAG, "Error reading " + logFile, e);
6442 }
6443 }
6444 if (crashInfo != null && crashInfo.stackTrace != null) {
6445 sb.append(crashInfo.stackTrace);
6446 }
6447
6448 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6449 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6450 if (lines > 0) {
6451 sb.append("\n");
6452
6453 // Merge several logcat streams, and take the last N lines
6454 InputStreamReader input = null;
6455 try {
6456 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6457 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6458 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6459
6460 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6461 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6462 input = new InputStreamReader(logcat.getInputStream());
6463
6464 int num;
6465 char[] buf = new char[8192];
6466 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6467 } catch (IOException e) {
6468 Slog.e(TAG, "Error running logcat", e);
6469 } finally {
6470 if (input != null) try { input.close(); } catch (IOException e) {}
6471 }
6472 }
6473
6474 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006475 }
Dan Egnora455d192010-03-12 08:52:28 -08006476 };
6477
6478 if (process == null || process.pid == MY_PID) {
6479 worker.run(); // We may be about to die -- need to run this synchronously
6480 } else {
6481 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006482 }
6483 }
6484
6485 /**
6486 * Bring up the "unexpected error" dialog box for a crashing app.
6487 * Deal with edge cases (intercepts from instrumented applications,
6488 * ActivityController, error intent receivers, that sort of thing).
6489 * @param r the application crashing
6490 * @param crashInfo describing the failure
6491 */
6492 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006493 long timeMillis = System.currentTimeMillis();
6494 String shortMsg = crashInfo.exceptionClassName;
6495 String longMsg = crashInfo.exceptionMessage;
6496 String stackTrace = crashInfo.stackTrace;
6497 if (shortMsg != null && longMsg != null) {
6498 longMsg = shortMsg + ": " + longMsg;
6499 } else if (shortMsg != null) {
6500 longMsg = shortMsg;
6501 }
6502
Dan Egnor60d87622009-12-16 16:32:58 -08006503 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006505 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 try {
6507 String name = r != null ? r.processName : null;
6508 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006509 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006510 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006511 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 + " at watcher's request");
6513 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006514 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 }
6516 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006517 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 }
6519 }
6520
6521 final long origId = Binder.clearCallingIdentity();
6522
6523 // If this process is running instrumentation, finish it.
6524 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006525 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006527 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6528 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529 Bundle info = new Bundle();
6530 info.putString("shortMsg", shortMsg);
6531 info.putString("longMsg", longMsg);
6532 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6533 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006534 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535 }
6536
Dan Egnor60d87622009-12-16 16:32:58 -08006537 // If we can't identify the process or it's already exceeded its crash quota,
6538 // quit right away without showing a crash dialog.
6539 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006541 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 }
6543
6544 Message msg = Message.obtain();
6545 msg.what = SHOW_ERROR_MSG;
6546 HashMap data = new HashMap();
6547 data.put("result", result);
6548 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006549 msg.obj = data;
6550 mHandler.sendMessage(msg);
6551
6552 Binder.restoreCallingIdentity(origId);
6553 }
6554
6555 int res = result.get();
6556
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006557 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 synchronized (this) {
6559 if (r != null) {
6560 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6561 SystemClock.uptimeMillis());
6562 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006563 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006564 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006565 }
6566 }
6567
6568 if (appErrorIntent != null) {
6569 try {
6570 mContext.startActivity(appErrorIntent);
6571 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006572 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006575 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006576
6577 Intent createAppErrorIntentLocked(ProcessRecord r,
6578 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6579 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006580 if (report == null) {
6581 return null;
6582 }
6583 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6584 result.setComponent(r.errorReportReceiver);
6585 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6586 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6587 return result;
6588 }
6589
Dan Egnorb7f03672009-12-09 16:22:32 -08006590 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6591 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006592 if (r.errorReportReceiver == null) {
6593 return null;
6594 }
6595
6596 if (!r.crashing && !r.notResponding) {
6597 return null;
6598 }
6599
Dan Egnorb7f03672009-12-09 16:22:32 -08006600 ApplicationErrorReport report = new ApplicationErrorReport();
6601 report.packageName = r.info.packageName;
6602 report.installerPackageName = r.errorReportReceiver.getPackageName();
6603 report.processName = r.processName;
6604 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006605 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006606
Dan Egnorb7f03672009-12-09 16:22:32 -08006607 if (r.crashing) {
6608 report.type = ApplicationErrorReport.TYPE_CRASH;
6609 report.crashInfo = crashInfo;
6610 } else if (r.notResponding) {
6611 report.type = ApplicationErrorReport.TYPE_ANR;
6612 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006613
Dan Egnorb7f03672009-12-09 16:22:32 -08006614 report.anrInfo.activity = r.notRespondingReport.tag;
6615 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6616 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006617 }
6618
Dan Egnorb7f03672009-12-09 16:22:32 -08006619 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006620 }
6621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006622 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6623 // assume our apps are happy - lazy create the list
6624 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6625
6626 synchronized (this) {
6627
6628 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006629 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6630 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6632 // This one's in trouble, so we'll generate a report for it
6633 // crashes are higher priority (in case there's a crash *and* an anr)
6634 ActivityManager.ProcessErrorStateInfo report = null;
6635 if (app.crashing) {
6636 report = app.crashingReport;
6637 } else if (app.notResponding) {
6638 report = app.notRespondingReport;
6639 }
6640
6641 if (report != null) {
6642 if (errList == null) {
6643 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6644 }
6645 errList.add(report);
6646 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006647 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006648 " crashing = " + app.crashing +
6649 " notResponding = " + app.notResponding);
6650 }
6651 }
6652 }
6653 }
6654
6655 return errList;
6656 }
6657
6658 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6659 // Lazy instantiation of list
6660 List<ActivityManager.RunningAppProcessInfo> runList = null;
6661 synchronized (this) {
6662 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006663 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6664 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6666 // Generate process state info for running application
6667 ActivityManager.RunningAppProcessInfo currApp =
6668 new ActivityManager.RunningAppProcessInfo(app.processName,
6669 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006670 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006671 if (mHeavyWeightProcess == app) {
6672 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6673 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006675 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006676 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6677 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6678 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006679 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6680 } else if (adj >= HOME_APP_ADJ) {
6681 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6682 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683 } else if (adj >= SECONDARY_SERVER_ADJ) {
6684 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006685 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6686 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6687 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6688 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006689 } else if (adj >= VISIBLE_APP_ADJ) {
6690 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6691 } else {
6692 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6693 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006694 currApp.importanceReasonCode = app.adjTypeCode;
6695 if (app.adjSource instanceof ProcessRecord) {
6696 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006697 } else if (app.adjSource instanceof ActivityRecord) {
6698 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006699 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6700 }
6701 if (app.adjTarget instanceof ComponentName) {
6702 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6703 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006704 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 // + " lru=" + currApp.lru);
6706 if (runList == null) {
6707 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6708 }
6709 runList.add(currApp);
6710 }
6711 }
6712 }
6713 return runList;
6714 }
6715
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006716 public List<ApplicationInfo> getRunningExternalApplications() {
6717 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6718 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6719 if (runningApps != null && runningApps.size() > 0) {
6720 Set<String> extList = new HashSet<String>();
6721 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6722 if (app.pkgList != null) {
6723 for (String pkg : app.pkgList) {
6724 extList.add(pkg);
6725 }
6726 }
6727 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006728 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006729 for (String pkg : extList) {
6730 try {
6731 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6732 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6733 retList.add(info);
6734 }
6735 } catch (RemoteException e) {
6736 }
6737 }
6738 }
6739 return retList;
6740 }
6741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 @Override
6743 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006744 if (checkCallingPermission(android.Manifest.permission.DUMP)
6745 != PackageManager.PERMISSION_GRANTED) {
6746 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6747 + Binder.getCallingPid()
6748 + ", uid=" + Binder.getCallingUid()
6749 + " without permission "
6750 + android.Manifest.permission.DUMP);
6751 return;
6752 }
6753
6754 boolean dumpAll = false;
6755
6756 int opti = 0;
6757 while (opti < args.length) {
6758 String opt = args[opti];
6759 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6760 break;
6761 }
6762 opti++;
6763 if ("-a".equals(opt)) {
6764 dumpAll = true;
6765 } else if ("-h".equals(opt)) {
6766 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006767 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006768 pw.println(" cmd may be one of:");
6769 pw.println(" activities: activity stack state");
6770 pw.println(" broadcasts: broadcast state");
6771 pw.println(" intents: pending intent state");
6772 pw.println(" processes: process state");
6773 pw.println(" providers: content provider state");
6774 pw.println(" services: service state");
6775 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006777 } else {
6778 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006780 }
6781
6782 // Is the caller requesting to dump a particular piece of data?
6783 if (opti < args.length) {
6784 String cmd = args[opti];
6785 opti++;
6786 if ("activities".equals(cmd) || "a".equals(cmd)) {
6787 synchronized (this) {
6788 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006790 return;
6791 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6792 synchronized (this) {
6793 dumpBroadcastsLocked(fd, pw, args, opti, true);
6794 }
6795 return;
6796 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6797 synchronized (this) {
6798 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6799 }
6800 return;
6801 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6802 synchronized (this) {
6803 dumpProcessesLocked(fd, pw, args, opti, true);
6804 }
6805 return;
6806 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6807 synchronized (this) {
6808 dumpProvidersLocked(fd, pw, args, opti, true);
6809 }
6810 return;
6811 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006812 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006813 return;
6814 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6815 synchronized (this) {
6816 dumpServicesLocked(fd, pw, args, opti, true);
6817 }
6818 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006819 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006820 }
6821
6822 // No piece of data specified, dump everything.
6823 synchronized (this) {
6824 boolean needSep;
6825 if (dumpAll) {
6826 pw.println("Providers in Current Activity Manager State:");
6827 }
6828 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6829 if (needSep) {
6830 pw.println(" ");
6831 }
6832 if (dumpAll) {
6833 pw.println("-------------------------------------------------------------------------------");
6834 pw.println("Broadcasts in Current Activity Manager State:");
6835 }
6836 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6837 if (needSep) {
6838 pw.println(" ");
6839 }
6840 if (dumpAll) {
6841 pw.println("-------------------------------------------------------------------------------");
6842 pw.println("Services in Current Activity Manager State:");
6843 }
6844 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6845 if (needSep) {
6846 pw.println(" ");
6847 }
6848 if (dumpAll) {
6849 pw.println("-------------------------------------------------------------------------------");
6850 pw.println("PendingIntents in Current Activity Manager State:");
6851 }
6852 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6853 if (needSep) {
6854 pw.println(" ");
6855 }
6856 if (dumpAll) {
6857 pw.println("-------------------------------------------------------------------------------");
6858 pw.println("Activities in Current Activity Manager State:");
6859 }
6860 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6861 if (needSep) {
6862 pw.println(" ");
6863 }
6864 if (dumpAll) {
6865 pw.println("-------------------------------------------------------------------------------");
6866 pw.println("Processes in Current Activity Manager State:");
6867 }
6868 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6869 }
6870 }
6871
6872 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6873 int opti, boolean dumpAll, boolean needHeader) {
6874 if (needHeader) {
6875 pw.println(" Activity stack:");
6876 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006877 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006878 pw.println(" ");
6879 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006880 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6881 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006883 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006884 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006885 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006886 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006887 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006888 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006889 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006890 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006891 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006892 pw.println(" ");
6893 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006894 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006896
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006897 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006898 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6899 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006900 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006901 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006903 if (dumpAll && mRecentTasks.size() > 0) {
6904 pw.println(" ");
6905 pw.println("Recent tasks in Current Activity Manager State:");
6906
6907 final int N = mRecentTasks.size();
6908 for (int i=0; i<N; i++) {
6909 TaskRecord tr = mRecentTasks.get(i);
6910 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6911 pw.println(tr);
6912 mRecentTasks.get(i).dump(pw, " ");
6913 }
6914 }
6915
6916 pw.println(" ");
6917 pw.println(" mCurTask: " + mCurTask);
6918
6919 return true;
6920 }
6921
6922 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6923 int opti, boolean dumpAll) {
6924 boolean needSep = false;
6925 int numPers = 0;
6926
6927 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6929 final int NA = procs.size();
6930 for (int ia=0; ia<NA; ia++) {
6931 if (!needSep) {
6932 pw.println(" All known processes:");
6933 needSep = true;
6934 }
6935 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006936 pw.print(r.persistent ? " *PERS*" : " *APP*");
6937 pw.print(" UID "); pw.print(procs.keyAt(ia));
6938 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006939 r.dump(pw, " ");
6940 if (r.persistent) {
6941 numPers++;
6942 }
6943 }
6944 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006945 }
6946
6947 if (mLruProcesses.size() > 0) {
6948 if (needSep) pw.println(" ");
6949 needSep = true;
6950 pw.println(" Running processes (most recent first):");
6951 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006952 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006953 needSep = true;
6954 }
6955
6956 synchronized (mPidsSelfLocked) {
6957 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 if (needSep) pw.println(" ");
6959 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006960 pw.println(" PID mappings:");
6961 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6962 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6963 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006964 }
6965 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006966 }
6967
6968 if (mForegroundProcesses.size() > 0) {
6969 if (needSep) pw.println(" ");
6970 needSep = true;
6971 pw.println(" Foreground Processes:");
6972 for (int i=0; i<mForegroundProcesses.size(); i++) {
6973 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6974 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006975 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006976 }
6977
6978 if (mPersistentStartingProcesses.size() > 0) {
6979 if (needSep) pw.println(" ");
6980 needSep = true;
6981 pw.println(" Persisent processes that are starting:");
6982 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6983 "Starting Norm", "Restarting PERS", false);
6984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006986 if (mStartingProcesses.size() > 0) {
6987 if (needSep) pw.println(" ");
6988 needSep = true;
6989 pw.println(" Processes that are starting:");
6990 dumpProcessList(pw, this, mStartingProcesses, " ",
6991 "Starting Norm", "Starting PERS", false);
6992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006994 if (mRemovedProcesses.size() > 0) {
6995 if (needSep) pw.println(" ");
6996 needSep = true;
6997 pw.println(" Processes that are being removed:");
6998 dumpProcessList(pw, this, mRemovedProcesses, " ",
6999 "Removed Norm", "Removed PERS", false);
7000 }
7001
7002 if (mProcessesOnHold.size() > 0) {
7003 if (needSep) pw.println(" ");
7004 needSep = true;
7005 pw.println(" Processes that are on old until the system is ready:");
7006 dumpProcessList(pw, this, mProcessesOnHold, " ",
7007 "OnHold Norm", "OnHold PERS", false);
7008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007009
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007010 if (mProcessesToGc.size() > 0) {
7011 if (needSep) pw.println(" ");
7012 needSep = true;
7013 pw.println(" Processes that are waiting to GC:");
7014 long now = SystemClock.uptimeMillis();
7015 for (int i=0; i<mProcessesToGc.size(); i++) {
7016 ProcessRecord proc = mProcessesToGc.get(i);
7017 pw.print(" Process "); pw.println(proc);
7018 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7019 pw.print(", last gced=");
7020 pw.print(now-proc.lastRequestedGc);
7021 pw.print(" ms ago, last lowMem=");
7022 pw.print(now-proc.lastLowMemory);
7023 pw.println(" ms ago");
7024
7025 }
7026 }
7027
7028 if (mProcessCrashTimes.getMap().size() > 0) {
7029 if (needSep) pw.println(" ");
7030 needSep = true;
7031 pw.println(" Time since processes crashed:");
7032 long now = SystemClock.uptimeMillis();
7033 for (Map.Entry<String, SparseArray<Long>> procs
7034 : mProcessCrashTimes.getMap().entrySet()) {
7035 SparseArray<Long> uids = procs.getValue();
7036 final int N = uids.size();
7037 for (int i=0; i<N; i++) {
7038 pw.print(" Process "); pw.print(procs.getKey());
7039 pw.print(" uid "); pw.print(uids.keyAt(i));
7040 pw.print(": last crashed ");
7041 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007042 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007043 }
7044 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007047 if (mBadProcesses.getMap().size() > 0) {
7048 if (needSep) pw.println(" ");
7049 needSep = true;
7050 pw.println(" Bad processes:");
7051 for (Map.Entry<String, SparseArray<Long>> procs
7052 : mBadProcesses.getMap().entrySet()) {
7053 SparseArray<Long> uids = procs.getValue();
7054 final int N = uids.size();
7055 for (int i=0; i<N; i++) {
7056 pw.print(" Bad process "); pw.print(procs.getKey());
7057 pw.print(" uid "); pw.print(uids.keyAt(i));
7058 pw.print(": crashed at time ");
7059 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 }
7061 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007064 pw.println(" ");
7065 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007066 if (mHeavyWeightProcess != null) {
7067 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7068 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007069 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007070 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007071 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7072 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7073 || mOrigWaitForDebugger) {
7074 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7075 + " mDebugTransient=" + mDebugTransient
7076 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7077 }
7078 if (mAlwaysFinishActivities || mController != null) {
7079 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7080 + " mController=" + mController);
7081 }
7082 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007084 pw.println(" mStartRunning=" + mStartRunning
7085 + " mSystemReady=" + mSystemReady
7086 + " mBooting=" + mBooting
7087 + " mBooted=" + mBooted
7088 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007089 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7090 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007091 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007093
7094 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007095 }
7096
7097 /**
7098 * There are three ways to call this:
7099 * - no service specified: dump all the services
7100 * - a flattened component name that matched an existing service was specified as the
7101 * first arg: dump that one service
7102 * - the first arg isn't the flattened component name of an existing service:
7103 * dump all services whose component contains the first arg as a substring
7104 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007105 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7106 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 String[] newArgs;
7108 String componentNameString;
7109 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007110 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007111 componentNameString = null;
7112 newArgs = EMPTY_STRING_ARRAY;
7113 r = null;
7114 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007115 componentNameString = args[opti];
7116 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007118 synchronized (this) {
7119 r = componentName != null ? mServices.get(componentName) : null;
7120 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007121 newArgs = new String[args.length - opti];
7122 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 }
7124
7125 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007126 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007128 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7129 synchronized (this) {
7130 for (ServiceRecord r1 : mServices.values()) {
7131 if (componentNameString == null
7132 || r1.name.flattenToString().contains(componentNameString)) {
7133 services.add(r1);
7134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 }
7136 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007137 for (int i=0; i<services.size(); i++) {
7138 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 }
7141 }
7142
7143 /**
7144 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7145 * there is a thread associated with the service.
7146 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007147 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7148 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007150 if (dumpAll) {
7151 synchronized (this) {
7152 pw.print(" * "); pw.println(r);
7153 r.dump(pw, " ");
7154 }
7155 pw.println("");
7156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 if (r.app != null && r.app.thread != null) {
7158 try {
7159 // flush anything that is already in the PrintWriter since the thread is going
7160 // to write to the file descriptor directly
7161 pw.flush();
7162 r.app.thread.dumpService(fd, r, args);
7163 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007164 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 } catch (RemoteException e) {
7166 pw.println("got a RemoteException while dumping the service");
7167 }
7168 }
7169 }
7170
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007171 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7172 int opti, boolean dumpAll) {
7173 boolean needSep = false;
7174
7175 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176 if (mRegisteredReceivers.size() > 0) {
7177 pw.println(" ");
7178 pw.println(" Registered Receivers:");
7179 Iterator it = mRegisteredReceivers.values().iterator();
7180 while (it.hasNext()) {
7181 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007182 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007183 r.dump(pw, " ");
7184 }
7185 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007187 pw.println(" ");
7188 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007189 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007190 needSep = true;
7191 }
7192
7193 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7194 || mPendingBroadcast != null) {
7195 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007197 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007199 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7200 pw.println(" Broadcast #" + i + ":");
7201 mParallelBroadcasts.get(i).dump(pw, " ");
7202 }
7203 if (mOrderedBroadcasts.size() > 0) {
7204 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007205 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007206 }
7207 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7208 pw.println(" Serialized Broadcast #" + i + ":");
7209 mOrderedBroadcasts.get(i).dump(pw, " ");
7210 }
7211 pw.println(" ");
7212 pw.println(" Pending broadcast:");
7213 if (mPendingBroadcast != null) {
7214 mPendingBroadcast.dump(pw, " ");
7215 } else {
7216 pw.println(" (null)");
7217 }
7218 needSep = true;
7219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007220
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007221 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007222 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007223 pw.println(" Historical broadcasts:");
7224 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7225 BroadcastRecord r = mBroadcastHistory[i];
7226 if (r == null) {
7227 break;
7228 }
7229 pw.println(" Historical Broadcast #" + i + ":");
7230 r.dump(pw, " ");
7231 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007232 needSep = true;
7233 }
7234
7235 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007236 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007237 pw.println(" Sticky broadcasts:");
7238 StringBuilder sb = new StringBuilder(128);
7239 for (Map.Entry<String, ArrayList<Intent>> ent
7240 : mStickyBroadcasts.entrySet()) {
7241 pw.print(" * Sticky action "); pw.print(ent.getKey());
7242 pw.println(":");
7243 ArrayList<Intent> intents = ent.getValue();
7244 final int N = intents.size();
7245 for (int i=0; i<N; i++) {
7246 sb.setLength(0);
7247 sb.append(" Intent: ");
7248 intents.get(i).toShortString(sb, true, false);
7249 pw.println(sb.toString());
7250 Bundle bundle = intents.get(i).getExtras();
7251 if (bundle != null) {
7252 pw.print(" ");
7253 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254 }
7255 }
7256 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007257 needSep = true;
7258 }
7259
7260 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007262 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007263 pw.println(" mHandler:");
7264 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007265 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007267
7268 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269 }
7270
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007271 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7272 int opti, boolean dumpAll) {
7273 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007274
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007275 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276 if (mServices.size() > 0) {
7277 pw.println(" Active services:");
7278 Iterator<ServiceRecord> it = mServices.values().iterator();
7279 while (it.hasNext()) {
7280 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007281 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007282 r.dump(pw, " ");
7283 }
7284 needSep = true;
7285 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007288 if (mPendingServices.size() > 0) {
7289 if (needSep) pw.println(" ");
7290 pw.println(" Pending services:");
7291 for (int i=0; i<mPendingServices.size(); i++) {
7292 ServiceRecord r = mPendingServices.get(i);
7293 pw.print(" * Pending "); pw.println(r);
7294 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 needSep = true;
7297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007299 if (mRestartingServices.size() > 0) {
7300 if (needSep) pw.println(" ");
7301 pw.println(" Restarting services:");
7302 for (int i=0; i<mRestartingServices.size(); i++) {
7303 ServiceRecord r = mRestartingServices.get(i);
7304 pw.print(" * Restarting "); pw.println(r);
7305 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007307 needSep = true;
7308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007310 if (mStoppingServices.size() > 0) {
7311 if (needSep) pw.println(" ");
7312 pw.println(" Stopping services:");
7313 for (int i=0; i<mStoppingServices.size(); i++) {
7314 ServiceRecord r = mStoppingServices.get(i);
7315 pw.print(" * Stopping "); pw.println(r);
7316 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007318 needSep = true;
7319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007321 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 if (mServiceConnections.size() > 0) {
7323 if (needSep) pw.println(" ");
7324 pw.println(" Connection bindings to services:");
7325 Iterator<ConnectionRecord> it
7326 = mServiceConnections.values().iterator();
7327 while (it.hasNext()) {
7328 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007329 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 r.dump(pw, " ");
7331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007332 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 }
7334 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007335
7336 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007337 }
7338
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007339 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7340 int opti, boolean dumpAll) {
7341 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007343 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 if (mProvidersByClass.size() > 0) {
7345 if (needSep) pw.println(" ");
7346 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007347 Iterator<Map.Entry<String, ContentProviderRecord>> it
7348 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007350 Map.Entry<String, ContentProviderRecord> e = it.next();
7351 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007352 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 r.dump(pw, " ");
7354 }
7355 needSep = true;
7356 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007357
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007358 if (mProvidersByName.size() > 0) {
7359 pw.println(" ");
7360 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007361 Iterator<Map.Entry<String, ContentProviderRecord>> it
7362 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007363 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007364 Map.Entry<String, ContentProviderRecord> e = it.next();
7365 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007366 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7367 pw.println(r);
7368 }
7369 needSep = true;
7370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007372
7373 if (mLaunchingProviders.size() > 0) {
7374 if (needSep) pw.println(" ");
7375 pw.println(" Launching content providers:");
7376 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7377 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7378 pw.println(mLaunchingProviders.get(i));
7379 }
7380 needSep = true;
7381 }
7382
7383 if (mGrantedUriPermissions.size() > 0) {
7384 pw.println();
7385 pw.println("Granted Uri Permissions:");
7386 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7387 int uid = mGrantedUriPermissions.keyAt(i);
7388 HashMap<Uri, UriPermission> perms
7389 = mGrantedUriPermissions.valueAt(i);
7390 pw.print(" * UID "); pw.print(uid);
7391 pw.println(" holds:");
7392 for (UriPermission perm : perms.values()) {
7393 pw.print(" "); pw.println(perm);
7394 perm.dump(pw, " ");
7395 }
7396 }
7397 needSep = true;
7398 }
7399
7400 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 }
7402
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007403 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7404 int opti, boolean dumpAll) {
7405 boolean needSep = false;
7406
7407 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408 if (this.mIntentSenderRecords.size() > 0) {
7409 Iterator<WeakReference<PendingIntentRecord>> it
7410 = mIntentSenderRecords.values().iterator();
7411 while (it.hasNext()) {
7412 WeakReference<PendingIntentRecord> ref = it.next();
7413 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007414 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007416 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 rec.dump(pw, " ");
7418 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007419 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 }
7421 }
7422 }
7423 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007424
7425 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 }
7427
7428 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007429 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 TaskRecord lastTask = null;
7431 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007432 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007433 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 if (lastTask != r.task) {
7435 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007436 pw.print(prefix);
7437 pw.print(full ? "* " : " ");
7438 pw.println(lastTask);
7439 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007440 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007443 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7444 pw.print(" #"); pw.print(i); pw.print(": ");
7445 pw.println(r);
7446 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007447 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449 }
7450 }
7451
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007452 private static String buildOomTag(String prefix, String space, int val, int base) {
7453 if (val == base) {
7454 if (space == null) return prefix;
7455 return prefix + " ";
7456 }
7457 return prefix + "+" + Integer.toString(val-base);
7458 }
7459
7460 private static final int dumpProcessList(PrintWriter pw,
7461 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 String prefix, String normalLabel, String persistentLabel,
7463 boolean inclOomAdj) {
7464 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007465 final int N = list.size()-1;
7466 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 ProcessRecord r = (ProcessRecord)list.get(i);
7468 if (false) {
7469 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7470 + " #" + i + ":");
7471 r.dump(pw, prefix + " ");
7472 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007473 String oomAdj;
7474 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007475 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007476 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007477 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7478 } else if (r.setAdj >= HOME_APP_ADJ) {
7479 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7480 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7481 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7482 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7483 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007484 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7485 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7486 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7487 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007488 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7489 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7490 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7491 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007492 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007493 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007494 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007495 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007496 } else {
7497 oomAdj = Integer.toString(r.setAdj);
7498 }
7499 String schedGroup;
7500 switch (r.setSchedGroup) {
7501 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7502 schedGroup = "B";
7503 break;
7504 case Process.THREAD_GROUP_DEFAULT:
7505 schedGroup = "F";
7506 break;
7507 default:
7508 schedGroup = Integer.toString(r.setSchedGroup);
7509 break;
7510 }
7511 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007513 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007514 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007515 pw.print(prefix);
7516 pw.print(" ");
7517 if (r.adjTarget instanceof ComponentName) {
7518 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7519 } else if (r.adjTarget != null) {
7520 pw.print(r.adjTarget.toString());
7521 } else {
7522 pw.print("{null}");
7523 }
7524 pw.print("<=");
7525 if (r.adjSource instanceof ProcessRecord) {
7526 pw.print("Proc{");
7527 pw.print(((ProcessRecord)r.adjSource).toShortString());
7528 pw.println("}");
7529 } else if (r.adjSource != null) {
7530 pw.println(r.adjSource.toString());
7531 } else {
7532 pw.println("{null}");
7533 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 } else {
7536 pw.println(String.format("%s%s #%2d: %s",
7537 prefix, (r.persistent ? persistentLabel : normalLabel),
7538 i, r.toString()));
7539 }
7540 if (r.persistent) {
7541 numPers++;
7542 }
7543 }
7544 return numPers;
7545 }
7546
Dianne Hackborn472ad872010-04-07 17:31:48 -07007547 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007549 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 long uptime = SystemClock.uptimeMillis();
7551 long realtime = SystemClock.elapsedRealtime();
7552
7553 if (isCheckinRequest) {
7554 // short checkin version
7555 pw.println(uptime + "," + realtime);
7556 pw.flush();
7557 } else {
7558 pw.println("Applications Memory Usage (kB):");
7559 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7560 }
7561 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7562 ProcessRecord r = (ProcessRecord)list.get(i);
7563 if (r.thread != null) {
7564 if (!isCheckinRequest) {
7565 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7566 pw.flush();
7567 }
7568 try {
7569 r.thread.asBinder().dump(fd, args);
7570 } catch (RemoteException e) {
7571 if (!isCheckinRequest) {
7572 pw.println("Got RemoteException!");
7573 pw.flush();
7574 }
7575 }
7576 }
7577 }
7578 }
7579
7580 /**
7581 * Searches array of arguments for the specified string
7582 * @param args array of argument strings
7583 * @param value value to search for
7584 * @return true if the value is contained in the array
7585 */
7586 private static boolean scanArgs(String[] args, String value) {
7587 if (args != null) {
7588 for (String arg : args) {
7589 if (value.equals(arg)) {
7590 return true;
7591 }
7592 }
7593 }
7594 return false;
7595 }
7596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007597 private final void killServicesLocked(ProcessRecord app,
7598 boolean allowRestart) {
7599 // Report disconnected services.
7600 if (false) {
7601 // XXX we are letting the client link to the service for
7602 // death notifications.
7603 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007604 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007606 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 if (r.connections.size() > 0) {
7608 Iterator<ConnectionRecord> jt
7609 = r.connections.values().iterator();
7610 while (jt.hasNext()) {
7611 ConnectionRecord c = jt.next();
7612 if (c.binding.client != app) {
7613 try {
7614 //c.conn.connected(r.className, null);
7615 } catch (Exception e) {
7616 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007617 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 + r.shortName
7619 + " from app " + app.processName, e);
7620 }
7621 }
7622 }
7623 }
7624 }
7625 }
7626 }
7627
7628 // Clean up any connections this application has to other services.
7629 if (app.connections.size() > 0) {
7630 Iterator<ConnectionRecord> it = app.connections.iterator();
7631 while (it.hasNext()) {
7632 ConnectionRecord r = it.next();
7633 removeConnectionLocked(r, app, null);
7634 }
7635 }
7636 app.connections.clear();
7637
7638 if (app.services.size() != 0) {
7639 // Any services running in the application need to be placed
7640 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007641 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007643 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 synchronized (sr.stats.getBatteryStats()) {
7645 sr.stats.stopLaunchedLocked();
7646 }
7647 sr.app = null;
7648 sr.executeNesting = 0;
7649 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007650
7651 boolean hasClients = sr.bindings.size() > 0;
7652 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 Iterator<IntentBindRecord> bindings
7654 = sr.bindings.values().iterator();
7655 while (bindings.hasNext()) {
7656 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007657 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007658 + ": shouldUnbind=" + b.hasBound);
7659 b.binder = null;
7660 b.requested = b.received = b.hasBound = false;
7661 }
7662 }
7663
7664 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007665 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007667 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 sr.crashCount, sr.shortName, app.pid);
7669 bringDownServiceLocked(sr, true);
7670 } else if (!allowRestart) {
7671 bringDownServiceLocked(sr, true);
7672 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007673 boolean canceled = scheduleServiceRestartLocked(sr, true);
7674
7675 // Should the service remain running? Note that in the
7676 // extreme case of so many attempts to deliver a command
7677 // that it failed, that we also will stop it here.
7678 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7679 if (sr.pendingStarts.size() == 0) {
7680 sr.startRequested = false;
7681 if (!hasClients) {
7682 // Whoops, no reason to restart!
7683 bringDownServiceLocked(sr, true);
7684 }
7685 }
7686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 }
7688 }
7689
7690 if (!allowRestart) {
7691 app.services.clear();
7692 }
7693 }
7694
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007695 // Make sure we have no more records on the stopping list.
7696 int i = mStoppingServices.size();
7697 while (i > 0) {
7698 i--;
7699 ServiceRecord sr = mStoppingServices.get(i);
7700 if (sr.app == app) {
7701 mStoppingServices.remove(i);
7702 }
7703 }
7704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 app.executingServices.clear();
7706 }
7707
7708 private final void removeDyingProviderLocked(ProcessRecord proc,
7709 ContentProviderRecord cpr) {
7710 synchronized (cpr) {
7711 cpr.launchingApp = null;
7712 cpr.notifyAll();
7713 }
7714
7715 mProvidersByClass.remove(cpr.info.name);
7716 String names[] = cpr.info.authority.split(";");
7717 for (int j = 0; j < names.length; j++) {
7718 mProvidersByName.remove(names[j]);
7719 }
7720
7721 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7722 while (cit.hasNext()) {
7723 ProcessRecord capp = cit.next();
7724 if (!capp.persistent && capp.thread != null
7725 && capp.pid != 0
7726 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007727 Slog.i(TAG, "Kill " + capp.processName
7728 + " (pid " + capp.pid + "): provider " + cpr.info.name
7729 + " in dying process " + proc.processName);
7730 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7731 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 Process.killProcess(capp.pid);
7733 }
7734 }
7735
7736 mLaunchingProviders.remove(cpr);
7737 }
7738
7739 /**
7740 * Main code for cleaning up a process when it has gone away. This is
7741 * called both as a result of the process dying, or directly when stopping
7742 * a process when running in single process mode.
7743 */
7744 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7745 boolean restarting, int index) {
7746 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007747 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 }
7749
Dianne Hackborn36124872009-10-08 16:22:03 -07007750 mProcessesToGc.remove(app);
7751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 // Dismiss any open dialogs.
7753 if (app.crashDialog != null) {
7754 app.crashDialog.dismiss();
7755 app.crashDialog = null;
7756 }
7757 if (app.anrDialog != null) {
7758 app.anrDialog.dismiss();
7759 app.anrDialog = null;
7760 }
7761 if (app.waitDialog != null) {
7762 app.waitDialog.dismiss();
7763 app.waitDialog = null;
7764 }
7765
7766 app.crashing = false;
7767 app.notResponding = false;
7768
7769 app.resetPackageList();
7770 app.thread = null;
7771 app.forcingToForeground = null;
7772 app.foregroundServices = false;
7773
7774 killServicesLocked(app, true);
7775
7776 boolean restart = false;
7777
7778 int NL = mLaunchingProviders.size();
7779
7780 // Remove published content providers.
7781 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007782 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007784 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 cpr.provider = null;
7786 cpr.app = null;
7787
7788 // See if someone is waiting for this provider... in which
7789 // case we don't remove it, but just let it restart.
7790 int i = 0;
7791 if (!app.bad) {
7792 for (; i<NL; i++) {
7793 if (mLaunchingProviders.get(i) == cpr) {
7794 restart = true;
7795 break;
7796 }
7797 }
7798 } else {
7799 i = NL;
7800 }
7801
7802 if (i >= NL) {
7803 removeDyingProviderLocked(app, cpr);
7804 NL = mLaunchingProviders.size();
7805 }
7806 }
7807 app.pubProviders.clear();
7808 }
7809
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007810 // Take care of any launching providers waiting for this process.
7811 if (checkAppInLaunchingProvidersLocked(app, false)) {
7812 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 // Unregister from connected content providers.
7816 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007817 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007818 while (it.hasNext()) {
7819 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7820 cpr.clients.remove(app);
7821 }
7822 app.conProviders.clear();
7823 }
7824
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007825 // At this point there may be remaining entries in mLaunchingProviders
7826 // where we were the only one waiting, so they are no longer of use.
7827 // Look for these and clean up if found.
7828 // XXX Commented out for now. Trying to figure out a way to reproduce
7829 // the actual situation to identify what is actually going on.
7830 if (false) {
7831 for (int i=0; i<NL; i++) {
7832 ContentProviderRecord cpr = (ContentProviderRecord)
7833 mLaunchingProviders.get(i);
7834 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7835 synchronized (cpr) {
7836 cpr.launchingApp = null;
7837 cpr.notifyAll();
7838 }
7839 }
7840 }
7841 }
7842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 skipCurrentReceiverLocked(app);
7844
7845 // Unregister any receivers.
7846 if (app.receivers.size() > 0) {
7847 Iterator<ReceiverList> it = app.receivers.iterator();
7848 while (it.hasNext()) {
7849 removeReceiverLocked(it.next());
7850 }
7851 app.receivers.clear();
7852 }
7853
Christopher Tate181fafa2009-05-14 11:12:14 -07007854 // If the app is undergoing backup, tell the backup manager about it
7855 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007856 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007857 try {
7858 IBackupManager bm = IBackupManager.Stub.asInterface(
7859 ServiceManager.getService(Context.BACKUP_SERVICE));
7860 bm.agentDisconnected(app.info.packageName);
7861 } catch (RemoteException e) {
7862 // can't happen; backup manager is local
7863 }
7864 }
7865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 // If the caller is restarting this app, then leave it in its
7867 // current lists and let the caller take care of it.
7868 if (restarting) {
7869 return;
7870 }
7871
7872 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007873 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 "Removing non-persistent process during cleanup: " + app);
7875 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007876 if (mHeavyWeightProcess == app) {
7877 mHeavyWeightProcess = null;
7878 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 } else if (!app.removed) {
7881 // This app is persistent, so we need to keep its record around.
7882 // If it is not already on the pending app list, add it there
7883 // and start a new process for it.
7884 app.thread = null;
7885 app.forcingToForeground = null;
7886 app.foregroundServices = false;
7887 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7888 mPersistentStartingProcesses.add(app);
7889 restart = true;
7890 }
7891 }
7892 mProcessesOnHold.remove(app);
7893
The Android Open Source Project4df24232009-03-05 14:34:35 -08007894 if (app == mHomeProcess) {
7895 mHomeProcess = null;
7896 }
7897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 if (restart) {
7899 // We have components that still need to be running in the
7900 // process, so re-launch it.
7901 mProcessNames.put(app.processName, app.info.uid, app);
7902 startProcessLocked(app, "restart", app.processName);
7903 } else if (app.pid > 0 && app.pid != MY_PID) {
7904 // Goodbye!
7905 synchronized (mPidsSelfLocked) {
7906 mPidsSelfLocked.remove(app.pid);
7907 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7908 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007909 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 }
7911 }
7912
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007913 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7914 // Look through the content providers we are waiting to have launched,
7915 // and if any run in this process then either schedule a restart of
7916 // the process or kill the client waiting for it if this process has
7917 // gone bad.
7918 int NL = mLaunchingProviders.size();
7919 boolean restart = false;
7920 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007921 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007922 if (cpr.launchingApp == app) {
7923 if (!alwaysBad && !app.bad) {
7924 restart = true;
7925 } else {
7926 removeDyingProviderLocked(app, cpr);
7927 NL = mLaunchingProviders.size();
7928 }
7929 }
7930 }
7931 return restart;
7932 }
7933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007934 // =========================================================
7935 // SERVICES
7936 // =========================================================
7937
7938 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7939 ActivityManager.RunningServiceInfo info =
7940 new ActivityManager.RunningServiceInfo();
7941 info.service = r.name;
7942 if (r.app != null) {
7943 info.pid = r.app.pid;
7944 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007945 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 info.process = r.processName;
7947 info.foreground = r.isForeground;
7948 info.activeSince = r.createTime;
7949 info.started = r.startRequested;
7950 info.clientCount = r.connections.size();
7951 info.crashCount = r.crashCount;
7952 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007953 if (r.isForeground) {
7954 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7955 }
7956 if (r.startRequested) {
7957 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7958 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007959 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007960 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7961 }
7962 if (r.app != null && r.app.persistent) {
7963 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7964 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007965 for (ConnectionRecord conn : r.connections.values()) {
7966 if (conn.clientLabel != 0) {
7967 info.clientPackage = conn.binding.client.info.packageName;
7968 info.clientLabel = conn.clientLabel;
7969 break;
7970 }
7971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007972 return info;
7973 }
7974
7975 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7976 int flags) {
7977 synchronized (this) {
7978 ArrayList<ActivityManager.RunningServiceInfo> res
7979 = new ArrayList<ActivityManager.RunningServiceInfo>();
7980
7981 if (mServices.size() > 0) {
7982 Iterator<ServiceRecord> it = mServices.values().iterator();
7983 while (it.hasNext() && res.size() < maxNum) {
7984 res.add(makeRunningServiceInfoLocked(it.next()));
7985 }
7986 }
7987
7988 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7989 ServiceRecord r = mRestartingServices.get(i);
7990 ActivityManager.RunningServiceInfo info =
7991 makeRunningServiceInfoLocked(r);
7992 info.restarting = r.nextRestartTime;
7993 res.add(info);
7994 }
7995
7996 return res;
7997 }
7998 }
7999
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008000 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8001 synchronized (this) {
8002 ServiceRecord r = mServices.get(name);
8003 if (r != null) {
8004 for (ConnectionRecord conn : r.connections.values()) {
8005 if (conn.clientIntent != null) {
8006 return conn.clientIntent;
8007 }
8008 }
8009 }
8010 }
8011 return null;
8012 }
8013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 private final ServiceRecord findServiceLocked(ComponentName name,
8015 IBinder token) {
8016 ServiceRecord r = mServices.get(name);
8017 return r == token ? r : null;
8018 }
8019
8020 private final class ServiceLookupResult {
8021 final ServiceRecord record;
8022 final String permission;
8023
8024 ServiceLookupResult(ServiceRecord _record, String _permission) {
8025 record = _record;
8026 permission = _permission;
8027 }
8028 };
8029
8030 private ServiceLookupResult findServiceLocked(Intent service,
8031 String resolvedType) {
8032 ServiceRecord r = null;
8033 if (service.getComponent() != null) {
8034 r = mServices.get(service.getComponent());
8035 }
8036 if (r == null) {
8037 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8038 r = mServicesByIntent.get(filter);
8039 }
8040
8041 if (r == null) {
8042 try {
8043 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008044 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 service, resolvedType, 0);
8046 ServiceInfo sInfo =
8047 rInfo != null ? rInfo.serviceInfo : null;
8048 if (sInfo == null) {
8049 return null;
8050 }
8051
8052 ComponentName name = new ComponentName(
8053 sInfo.applicationInfo.packageName, sInfo.name);
8054 r = mServices.get(name);
8055 } catch (RemoteException ex) {
8056 // pm is in same process, this will never happen.
8057 }
8058 }
8059 if (r != null) {
8060 int callingPid = Binder.getCallingPid();
8061 int callingUid = Binder.getCallingUid();
8062 if (checkComponentPermission(r.permission,
8063 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8064 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008065 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 + " from pid=" + callingPid
8067 + ", uid=" + callingUid
8068 + " requires " + r.permission);
8069 return new ServiceLookupResult(null, r.permission);
8070 }
8071 return new ServiceLookupResult(r, null);
8072 }
8073 return null;
8074 }
8075
8076 private class ServiceRestarter implements Runnable {
8077 private ServiceRecord mService;
8078
8079 void setService(ServiceRecord service) {
8080 mService = service;
8081 }
8082
8083 public void run() {
8084 synchronized(ActivityManagerService.this) {
8085 performServiceRestartLocked(mService);
8086 }
8087 }
8088 }
8089
8090 private ServiceLookupResult retrieveServiceLocked(Intent service,
8091 String resolvedType, int callingPid, int callingUid) {
8092 ServiceRecord r = null;
8093 if (service.getComponent() != null) {
8094 r = mServices.get(service.getComponent());
8095 }
8096 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8097 r = mServicesByIntent.get(filter);
8098 if (r == null) {
8099 try {
8100 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008101 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008102 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 ServiceInfo sInfo =
8104 rInfo != null ? rInfo.serviceInfo : null;
8105 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008106 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 ": not found");
8108 return null;
8109 }
8110
8111 ComponentName name = new ComponentName(
8112 sInfo.applicationInfo.packageName, sInfo.name);
8113 r = mServices.get(name);
8114 if (r == null) {
8115 filter = new Intent.FilterComparison(service.cloneFilter());
8116 ServiceRestarter res = new ServiceRestarter();
8117 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8118 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8119 synchronized (stats) {
8120 ss = stats.getServiceStatsLocked(
8121 sInfo.applicationInfo.uid, sInfo.packageName,
8122 sInfo.name);
8123 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008124 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008125 res.setService(r);
8126 mServices.put(name, r);
8127 mServicesByIntent.put(filter, r);
8128
8129 // Make sure this component isn't in the pending list.
8130 int N = mPendingServices.size();
8131 for (int i=0; i<N; i++) {
8132 ServiceRecord pr = mPendingServices.get(i);
8133 if (pr.name.equals(name)) {
8134 mPendingServices.remove(i);
8135 i--;
8136 N--;
8137 }
8138 }
8139 }
8140 } catch (RemoteException ex) {
8141 // pm is in same process, this will never happen.
8142 }
8143 }
8144 if (r != null) {
8145 if (checkComponentPermission(r.permission,
8146 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8147 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008148 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 + " from pid=" + Binder.getCallingPid()
8150 + ", uid=" + Binder.getCallingUid()
8151 + " requires " + r.permission);
8152 return new ServiceLookupResult(null, r.permission);
8153 }
8154 return new ServiceLookupResult(r, null);
8155 }
8156 return null;
8157 }
8158
8159 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8160 long now = SystemClock.uptimeMillis();
8161 if (r.executeNesting == 0 && r.app != null) {
8162 if (r.app.executingServices.size() == 0) {
8163 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8164 msg.obj = r.app;
8165 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8166 }
8167 r.app.executingServices.add(r);
8168 }
8169 r.executeNesting++;
8170 r.executingStart = now;
8171 }
8172
8173 private final void sendServiceArgsLocked(ServiceRecord r,
8174 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008175 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176 if (N == 0) {
8177 return;
8178 }
8179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 int i = 0;
8181 while (i < N) {
8182 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008183 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008184 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008185 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008186 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008187 // If somehow we got a dummy start at the front, then
8188 // just drop it here.
8189 i++;
8190 continue;
8191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008192 bumpServiceExecutingLocked(r);
8193 if (!oomAdjusted) {
8194 oomAdjusted = true;
8195 updateOomAdjLocked(r.app);
8196 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008197 int flags = 0;
8198 if (si.deliveryCount > 0) {
8199 flags |= Service.START_FLAG_RETRY;
8200 }
8201 if (si.doneExecutingCount > 0) {
8202 flags |= Service.START_FLAG_REDELIVERY;
8203 }
8204 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8205 si.deliveredTime = SystemClock.uptimeMillis();
8206 r.deliveredStarts.add(si);
8207 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008208 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008209 } catch (RemoteException e) {
8210 // Remote process gone... we'll let the normal cleanup take
8211 // care of this.
8212 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008213 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008214 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008215 break;
8216 }
8217 }
8218 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008219 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 } else {
8221 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008223 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 }
8225 }
8226 }
8227
8228 private final boolean requestServiceBindingLocked(ServiceRecord r,
8229 IntentBindRecord i, boolean rebind) {
8230 if (r.app == null || r.app.thread == null) {
8231 // If service is not currently running, can't yet bind.
8232 return false;
8233 }
8234 if ((!i.requested || rebind) && i.apps.size() > 0) {
8235 try {
8236 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008237 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008238 + ": shouldUnbind=" + i.hasBound);
8239 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8240 if (!rebind) {
8241 i.requested = true;
8242 }
8243 i.hasBound = true;
8244 i.doRebind = false;
8245 } catch (RemoteException e) {
8246 return false;
8247 }
8248 }
8249 return true;
8250 }
8251
8252 private final void requestServiceBindingsLocked(ServiceRecord r) {
8253 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8254 while (bindings.hasNext()) {
8255 IntentBindRecord i = bindings.next();
8256 if (!requestServiceBindingLocked(r, i, false)) {
8257 break;
8258 }
8259 }
8260 }
8261
8262 private final void realStartServiceLocked(ServiceRecord r,
8263 ProcessRecord app) throws RemoteException {
8264 if (app.thread == null) {
8265 throw new RemoteException();
8266 }
8267
8268 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008269 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270
8271 app.services.add(r);
8272 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008273 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008274
8275 boolean created = false;
8276 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008277 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008279 mStringBuilder.setLength(0);
8280 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008281 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008283 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 synchronized (r.stats.getBatteryStats()) {
8285 r.stats.startLaunchedLocked();
8286 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008287 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008288 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008289 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008290 created = true;
8291 } finally {
8292 if (!created) {
8293 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008294 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 }
8296 }
8297
8298 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008299
8300 // If the service is in the started state, and there are no
8301 // pending arguments, then fake up one so its onStartCommand() will
8302 // be called.
8303 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8304 r.lastStartId++;
8305 if (r.lastStartId < 1) {
8306 r.lastStartId = 1;
8307 }
8308 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8309 }
8310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 sendServiceArgsLocked(r, true);
8312 }
8313
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008314 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8315 boolean allowCancel) {
8316 boolean canceled = false;
8317
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008318 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008319 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008320 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008321
8322 // Any delivered but not yet finished starts should be put back
8323 // on the pending list.
8324 final int N = r.deliveredStarts.size();
8325 if (N > 0) {
8326 for (int i=N-1; i>=0; i--) {
8327 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8328 if (si.intent == null) {
8329 // We'll generate this again if needed.
8330 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8331 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8332 r.pendingStarts.add(0, si);
8333 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8334 dur *= 2;
8335 if (minDuration < dur) minDuration = dur;
8336 if (resetTime < dur) resetTime = dur;
8337 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008338 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008339 + r.name);
8340 canceled = true;
8341 }
8342 }
8343 r.deliveredStarts.clear();
8344 }
8345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 r.totalRestartCount++;
8347 if (r.restartDelay == 0) {
8348 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008349 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 } else {
8351 // If it has been a "reasonably long time" since the service
8352 // was started, then reset our restart duration back to
8353 // the beginning, so we don't infinitely increase the duration
8354 // on a service that just occasionally gets killed (which is
8355 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008356 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008358 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008360 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008361 if (r.restartDelay < minDuration) {
8362 r.restartDelay = minDuration;
8363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 }
8365 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008366
8367 r.nextRestartTime = now + r.restartDelay;
8368
8369 // Make sure that we don't end up restarting a bunch of services
8370 // all at the same time.
8371 boolean repeat;
8372 do {
8373 repeat = false;
8374 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8375 ServiceRecord r2 = mRestartingServices.get(i);
8376 if (r2 != r && r.nextRestartTime
8377 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8378 && r.nextRestartTime
8379 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8380 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8381 r.restartDelay = r.nextRestartTime - now;
8382 repeat = true;
8383 break;
8384 }
8385 }
8386 } while (repeat);
8387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 if (!mRestartingServices.contains(r)) {
8389 mRestartingServices.add(r);
8390 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008391
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008392 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008395 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008396 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008397 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008399 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008400 r.shortName, r.restartDelay);
8401
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008402 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008403 }
8404
8405 final void performServiceRestartLocked(ServiceRecord r) {
8406 if (!mRestartingServices.contains(r)) {
8407 return;
8408 }
8409 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8410 }
8411
8412 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8413 if (r.restartDelay == 0) {
8414 return false;
8415 }
8416 r.resetRestartCounter();
8417 mRestartingServices.remove(r);
8418 mHandler.removeCallbacks(r.restarter);
8419 return true;
8420 }
8421
8422 private final boolean bringUpServiceLocked(ServiceRecord r,
8423 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008424 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 //r.dump(" ");
8426
Dianne Hackborn36124872009-10-08 16:22:03 -07008427 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 sendServiceArgsLocked(r, false);
8429 return true;
8430 }
8431
8432 if (!whileRestarting && r.restartDelay > 0) {
8433 // If waiting for a restart, then do nothing.
8434 return true;
8435 }
8436
Joe Onorato8a9b2202010-02-26 18:56:32 -08008437 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008438 + " " + r.intent);
8439
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008440 // We are now bringing the service up, so no longer in the
8441 // restarting state.
8442 mRestartingServices.remove(r);
8443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008444 final String appName = r.processName;
8445 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8446 if (app != null && app.thread != null) {
8447 try {
8448 realStartServiceLocked(r, app);
8449 return true;
8450 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008451 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 }
8453
8454 // If a dead object exception was thrown -- fall through to
8455 // restart the application.
8456 }
8457
Dianne Hackborn36124872009-10-08 16:22:03 -07008458 // Not running -- get it started, and enqueue this service record
8459 // to be executed when the app comes up.
8460 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8461 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008462 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008463 + r.appInfo.packageName + "/"
8464 + r.appInfo.uid + " for service "
8465 + r.intent.getIntent() + ": process is bad");
8466 bringDownServiceLocked(r, true);
8467 return false;
8468 }
8469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 mPendingServices.add(r);
8472 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008474 return true;
8475 }
8476
8477 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008478 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 //r.dump(" ");
8480
8481 // Does it still need to run?
8482 if (!force && r.startRequested) {
8483 return;
8484 }
8485 if (r.connections.size() > 0) {
8486 if (!force) {
8487 // XXX should probably keep a count of the number of auto-create
8488 // connections directly in the service.
8489 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8490 while (it.hasNext()) {
8491 ConnectionRecord cr = it.next();
8492 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8493 return;
8494 }
8495 }
8496 }
8497
8498 // Report to all of the connections that the service is no longer
8499 // available.
8500 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8501 while (it.hasNext()) {
8502 ConnectionRecord c = it.next();
8503 try {
8504 // todo: shouldn't be a synchronous call!
8505 c.conn.connected(r.name, null);
8506 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008507 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 " to connection " + c.conn.asBinder() +
8509 " (in " + c.binding.client.processName + ")", e);
8510 }
8511 }
8512 }
8513
8514 // Tell the service that it has been unbound.
8515 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8516 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8517 while (it.hasNext()) {
8518 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008519 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 + ": hasBound=" + ibr.hasBound);
8521 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8522 try {
8523 bumpServiceExecutingLocked(r);
8524 updateOomAdjLocked(r.app);
8525 ibr.hasBound = false;
8526 r.app.thread.scheduleUnbindService(r,
8527 ibr.intent.getIntent());
8528 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008529 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 + r.shortName, e);
8531 serviceDoneExecutingLocked(r, true);
8532 }
8533 }
8534 }
8535 }
8536
Joe Onorato8a9b2202010-02-26 18:56:32 -08008537 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008539 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 System.identityHashCode(r), r.shortName,
8541 (r.app != null) ? r.app.pid : -1);
8542
8543 mServices.remove(r.name);
8544 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008545 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 r.totalRestartCount = 0;
8547 unscheduleServiceRestartLocked(r);
8548
8549 // Also make sure it is not on the pending list.
8550 int N = mPendingServices.size();
8551 for (int i=0; i<N; i++) {
8552 if (mPendingServices.get(i) == r) {
8553 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008554 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 TAG, "Removed pending service: " + r.shortName);
8556 i--;
8557 N--;
8558 }
8559 }
8560
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008561 r.cancelNotification();
8562 r.isForeground = false;
8563 r.foregroundId = 0;
8564 r.foregroundNoti = null;
8565
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008566 // Clear start entries.
8567 r.deliveredStarts.clear();
8568 r.pendingStarts.clear();
8569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 if (r.app != null) {
8571 synchronized (r.stats.getBatteryStats()) {
8572 r.stats.stopLaunchedLocked();
8573 }
8574 r.app.services.remove(r);
8575 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008577 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008578 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 bumpServiceExecutingLocked(r);
8580 mStoppingServices.add(r);
8581 updateOomAdjLocked(r.app);
8582 r.app.thread.scheduleStopService(r);
8583 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008584 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 + r.shortName, e);
8586 serviceDoneExecutingLocked(r, true);
8587 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008588 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008590 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008591 TAG, "Removed service that has no process: " + r.shortName);
8592 }
8593 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008594 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 TAG, "Removed service that is not running: " + r.shortName);
8596 }
8597 }
8598
8599 ComponentName startServiceLocked(IApplicationThread caller,
8600 Intent service, String resolvedType,
8601 int callingPid, int callingUid) {
8602 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008603 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008604 + " type=" + resolvedType + " args=" + service.getExtras());
8605
8606 if (caller != null) {
8607 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8608 if (callerApp == null) {
8609 throw new SecurityException(
8610 "Unable to find app for caller " + caller
8611 + " (pid=" + Binder.getCallingPid()
8612 + ") when starting service " + service);
8613 }
8614 }
8615
8616 ServiceLookupResult res =
8617 retrieveServiceLocked(service, resolvedType,
8618 callingPid, callingUid);
8619 if (res == null) {
8620 return null;
8621 }
8622 if (res.record == null) {
8623 return new ComponentName("!", res.permission != null
8624 ? res.permission : "private to package");
8625 }
8626 ServiceRecord r = res.record;
8627 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008628 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 + r.shortName);
8630 }
8631 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008632 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 r.lastStartId++;
8634 if (r.lastStartId < 1) {
8635 r.lastStartId = 1;
8636 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008637 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008638 r.lastActivity = SystemClock.uptimeMillis();
8639 synchronized (r.stats.getBatteryStats()) {
8640 r.stats.startRunningLocked();
8641 }
8642 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8643 return new ComponentName("!", "Service process is bad");
8644 }
8645 return r.name;
8646 }
8647 }
8648
8649 public ComponentName startService(IApplicationThread caller, Intent service,
8650 String resolvedType) {
8651 // Refuse possible leaked file descriptors
8652 if (service != null && service.hasFileDescriptors() == true) {
8653 throw new IllegalArgumentException("File descriptors passed in Intent");
8654 }
8655
8656 synchronized(this) {
8657 final int callingPid = Binder.getCallingPid();
8658 final int callingUid = Binder.getCallingUid();
8659 final long origId = Binder.clearCallingIdentity();
8660 ComponentName res = startServiceLocked(caller, service,
8661 resolvedType, callingPid, callingUid);
8662 Binder.restoreCallingIdentity(origId);
8663 return res;
8664 }
8665 }
8666
8667 ComponentName startServiceInPackage(int uid,
8668 Intent service, String resolvedType) {
8669 synchronized(this) {
8670 final long origId = Binder.clearCallingIdentity();
8671 ComponentName res = startServiceLocked(null, service,
8672 resolvedType, -1, uid);
8673 Binder.restoreCallingIdentity(origId);
8674 return res;
8675 }
8676 }
8677
8678 public int stopService(IApplicationThread caller, Intent service,
8679 String resolvedType) {
8680 // Refuse possible leaked file descriptors
8681 if (service != null && service.hasFileDescriptors() == true) {
8682 throw new IllegalArgumentException("File descriptors passed in Intent");
8683 }
8684
8685 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008686 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 + " type=" + resolvedType);
8688
8689 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8690 if (caller != null && callerApp == null) {
8691 throw new SecurityException(
8692 "Unable to find app for caller " + caller
8693 + " (pid=" + Binder.getCallingPid()
8694 + ") when stopping service " + service);
8695 }
8696
8697 // If this service is active, make sure it is stopped.
8698 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8699 if (r != null) {
8700 if (r.record != null) {
8701 synchronized (r.record.stats.getBatteryStats()) {
8702 r.record.stats.stopRunningLocked();
8703 }
8704 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008705 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 final long origId = Binder.clearCallingIdentity();
8707 bringDownServiceLocked(r.record, false);
8708 Binder.restoreCallingIdentity(origId);
8709 return 1;
8710 }
8711 return -1;
8712 }
8713 }
8714
8715 return 0;
8716 }
8717
8718 public IBinder peekService(Intent service, String resolvedType) {
8719 // Refuse possible leaked file descriptors
8720 if (service != null && service.hasFileDescriptors() == true) {
8721 throw new IllegalArgumentException("File descriptors passed in Intent");
8722 }
8723
8724 IBinder ret = null;
8725
8726 synchronized(this) {
8727 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8728
8729 if (r != null) {
8730 // r.record is null if findServiceLocked() failed the caller permission check
8731 if (r.record == null) {
8732 throw new SecurityException(
8733 "Permission Denial: Accessing service " + r.record.name
8734 + " from pid=" + Binder.getCallingPid()
8735 + ", uid=" + Binder.getCallingUid()
8736 + " requires " + r.permission);
8737 }
8738 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8739 if (ib != null) {
8740 ret = ib.binder;
8741 }
8742 }
8743 }
8744
8745 return ret;
8746 }
8747
8748 public boolean stopServiceToken(ComponentName className, IBinder token,
8749 int startId) {
8750 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008751 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008752 + " " + token + " startId=" + startId);
8753 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008754 if (r != null) {
8755 if (startId >= 0) {
8756 // Asked to only stop if done with all work. Note that
8757 // to avoid leaks, we will take this as dropping all
8758 // start items up to and including this one.
8759 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8760 if (si != null) {
8761 while (r.deliveredStarts.size() > 0) {
8762 if (r.deliveredStarts.remove(0) == si) {
8763 break;
8764 }
8765 }
8766 }
8767
8768 if (r.lastStartId != startId) {
8769 return false;
8770 }
8771
8772 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008773 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008774 + " is last, but have " + r.deliveredStarts.size()
8775 + " remaining args");
8776 }
8777 }
8778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 synchronized (r.stats.getBatteryStats()) {
8780 r.stats.stopRunningLocked();
8781 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008782 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008783 }
8784 final long origId = Binder.clearCallingIdentity();
8785 bringDownServiceLocked(r, false);
8786 Binder.restoreCallingIdentity(origId);
8787 return true;
8788 }
8789 }
8790 return false;
8791 }
8792
8793 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008794 int id, Notification notification, boolean removeNotification) {
8795 final long origId = Binder.clearCallingIdentity();
8796 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008797 synchronized(this) {
8798 ServiceRecord r = findServiceLocked(className, token);
8799 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008800 if (id != 0) {
8801 if (notification == null) {
8802 throw new IllegalArgumentException("null notification");
8803 }
8804 if (r.foregroundId != id) {
8805 r.cancelNotification();
8806 r.foregroundId = id;
8807 }
8808 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8809 r.foregroundNoti = notification;
8810 r.isForeground = true;
8811 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 if (r.app != null) {
8813 updateServiceForegroundLocked(r.app, true);
8814 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008815 } else {
8816 if (r.isForeground) {
8817 r.isForeground = false;
8818 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008819 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008820 updateServiceForegroundLocked(r.app, true);
8821 }
8822 }
8823 if (removeNotification) {
8824 r.cancelNotification();
8825 r.foregroundId = 0;
8826 r.foregroundNoti = null;
8827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008828 }
8829 }
8830 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008831 } finally {
8832 Binder.restoreCallingIdentity(origId);
8833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 }
8835
8836 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8837 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008838 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008839 if (sr.isForeground) {
8840 anyForeground = true;
8841 break;
8842 }
8843 }
8844 if (anyForeground != proc.foregroundServices) {
8845 proc.foregroundServices = anyForeground;
8846 if (oomAdj) {
8847 updateOomAdjLocked();
8848 }
8849 }
8850 }
8851
8852 public int bindService(IApplicationThread caller, IBinder token,
8853 Intent service, String resolvedType,
8854 IServiceConnection connection, int flags) {
8855 // Refuse possible leaked file descriptors
8856 if (service != null && service.hasFileDescriptors() == true) {
8857 throw new IllegalArgumentException("File descriptors passed in Intent");
8858 }
8859
8860 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008861 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 + " type=" + resolvedType + " conn=" + connection.asBinder()
8863 + " flags=0x" + Integer.toHexString(flags));
8864 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8865 if (callerApp == null) {
8866 throw new SecurityException(
8867 "Unable to find app for caller " + caller
8868 + " (pid=" + Binder.getCallingPid()
8869 + ") when binding service " + service);
8870 }
8871
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008872 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008873 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008874 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008875 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008876 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008877 return 0;
8878 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008879 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008880 }
8881
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008882 int clientLabel = 0;
8883 PendingIntent clientIntent = null;
8884
8885 if (callerApp.info.uid == Process.SYSTEM_UID) {
8886 // Hacky kind of thing -- allow system stuff to tell us
8887 // what they are, so we can report this elsewhere for
8888 // others to know why certain services are running.
8889 try {
8890 clientIntent = (PendingIntent)service.getParcelableExtra(
8891 Intent.EXTRA_CLIENT_INTENT);
8892 } catch (RuntimeException e) {
8893 }
8894 if (clientIntent != null) {
8895 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8896 if (clientLabel != 0) {
8897 // There are no useful extras in the intent, trash them.
8898 // System code calling with this stuff just needs to know
8899 // this will happen.
8900 service = service.cloneFilter();
8901 }
8902 }
8903 }
8904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 ServiceLookupResult res =
8906 retrieveServiceLocked(service, resolvedType,
8907 Binder.getCallingPid(), Binder.getCallingUid());
8908 if (res == null) {
8909 return 0;
8910 }
8911 if (res.record == null) {
8912 return -1;
8913 }
8914 ServiceRecord s = res.record;
8915
8916 final long origId = Binder.clearCallingIdentity();
8917
8918 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008919 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 + s.shortName);
8921 }
8922
8923 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8924 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008925 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926
8927 IBinder binder = connection.asBinder();
8928 s.connections.put(binder, c);
8929 b.connections.add(c);
8930 if (activity != null) {
8931 if (activity.connections == null) {
8932 activity.connections = new HashSet<ConnectionRecord>();
8933 }
8934 activity.connections.add(c);
8935 }
8936 b.client.connections.add(c);
8937 mServiceConnections.put(binder, c);
8938
8939 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8940 s.lastActivity = SystemClock.uptimeMillis();
8941 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8942 return 0;
8943 }
8944 }
8945
8946 if (s.app != null) {
8947 // This could have made the service more important.
8948 updateOomAdjLocked(s.app);
8949 }
8950
Joe Onorato8a9b2202010-02-26 18:56:32 -08008951 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008952 + ": received=" + b.intent.received
8953 + " apps=" + b.intent.apps.size()
8954 + " doRebind=" + b.intent.doRebind);
8955
8956 if (s.app != null && b.intent.received) {
8957 // Service is already running, so we can immediately
8958 // publish the connection.
8959 try {
8960 c.conn.connected(s.name, b.intent.binder);
8961 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008962 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008963 + " to connection " + c.conn.asBinder()
8964 + " (in " + c.binding.client.processName + ")", e);
8965 }
8966
8967 // If this is the first app connected back to this binding,
8968 // and the service had previously asked to be told when
8969 // rebound, then do so.
8970 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8971 requestServiceBindingLocked(s, b.intent, true);
8972 }
8973 } else if (!b.intent.requested) {
8974 requestServiceBindingLocked(s, b.intent, false);
8975 }
8976
8977 Binder.restoreCallingIdentity(origId);
8978 }
8979
8980 return 1;
8981 }
8982
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008983 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008984 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 IBinder binder = c.conn.asBinder();
8986 AppBindRecord b = c.binding;
8987 ServiceRecord s = b.service;
8988 s.connections.remove(binder);
8989 b.connections.remove(c);
8990 if (c.activity != null && c.activity != skipAct) {
8991 if (c.activity.connections != null) {
8992 c.activity.connections.remove(c);
8993 }
8994 }
8995 if (b.client != skipApp) {
8996 b.client.connections.remove(c);
8997 }
8998 mServiceConnections.remove(binder);
8999
9000 if (b.connections.size() == 0) {
9001 b.intent.apps.remove(b.client);
9002 }
9003
Joe Onorato8a9b2202010-02-26 18:56:32 -08009004 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 + ": shouldUnbind=" + b.intent.hasBound);
9006 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9007 && b.intent.hasBound) {
9008 try {
9009 bumpServiceExecutingLocked(s);
9010 updateOomAdjLocked(s.app);
9011 b.intent.hasBound = false;
9012 // Assume the client doesn't want to know about a rebind;
9013 // we will deal with that later if it asks for one.
9014 b.intent.doRebind = false;
9015 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9016 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009017 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009018 serviceDoneExecutingLocked(s, true);
9019 }
9020 }
9021
9022 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9023 bringDownServiceLocked(s, false);
9024 }
9025 }
9026
9027 public boolean unbindService(IServiceConnection connection) {
9028 synchronized (this) {
9029 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009030 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 ConnectionRecord r = mServiceConnections.get(binder);
9032 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009033 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 + connection.asBinder());
9035 return false;
9036 }
9037
9038 final long origId = Binder.clearCallingIdentity();
9039
9040 removeConnectionLocked(r, null, null);
9041
9042 if (r.binding.service.app != null) {
9043 // This could have made the service less important.
9044 updateOomAdjLocked(r.binding.service.app);
9045 }
9046
9047 Binder.restoreCallingIdentity(origId);
9048 }
9049
9050 return true;
9051 }
9052
9053 public void publishService(IBinder token, Intent intent, IBinder service) {
9054 // Refuse possible leaked file descriptors
9055 if (intent != null && intent.hasFileDescriptors() == true) {
9056 throw new IllegalArgumentException("File descriptors passed in Intent");
9057 }
9058
9059 synchronized(this) {
9060 if (!(token instanceof ServiceRecord)) {
9061 throw new IllegalArgumentException("Invalid service token");
9062 }
9063 ServiceRecord r = (ServiceRecord)token;
9064
9065 final long origId = Binder.clearCallingIdentity();
9066
Joe Onorato8a9b2202010-02-26 18:56:32 -08009067 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 + " " + intent + ": " + service);
9069 if (r != null) {
9070 Intent.FilterComparison filter
9071 = new Intent.FilterComparison(intent);
9072 IntentBindRecord b = r.bindings.get(filter);
9073 if (b != null && !b.received) {
9074 b.binder = service;
9075 b.requested = true;
9076 b.received = true;
9077 if (r.connections.size() > 0) {
9078 Iterator<ConnectionRecord> it
9079 = r.connections.values().iterator();
9080 while (it.hasNext()) {
9081 ConnectionRecord c = it.next();
9082 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009083 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009085 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009087 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 TAG, "Published intent: " + intent);
9089 continue;
9090 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009091 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 try {
9093 c.conn.connected(r.name, service);
9094 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009095 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 " to connection " + c.conn.asBinder() +
9097 " (in " + c.binding.client.processName + ")", e);
9098 }
9099 }
9100 }
9101 }
9102
9103 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9104
9105 Binder.restoreCallingIdentity(origId);
9106 }
9107 }
9108 }
9109
9110 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9111 // Refuse possible leaked file descriptors
9112 if (intent != null && intent.hasFileDescriptors() == true) {
9113 throw new IllegalArgumentException("File descriptors passed in Intent");
9114 }
9115
9116 synchronized(this) {
9117 if (!(token instanceof ServiceRecord)) {
9118 throw new IllegalArgumentException("Invalid service token");
9119 }
9120 ServiceRecord r = (ServiceRecord)token;
9121
9122 final long origId = Binder.clearCallingIdentity();
9123
9124 if (r != null) {
9125 Intent.FilterComparison filter
9126 = new Intent.FilterComparison(intent);
9127 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009128 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 + " at " + b + ": apps="
9130 + (b != null ? b.apps.size() : 0));
9131 if (b != null) {
9132 if (b.apps.size() > 0) {
9133 // Applications have already bound since the last
9134 // unbind, so just rebind right here.
9135 requestServiceBindingLocked(r, b, true);
9136 } else {
9137 // Note to tell the service the next time there is
9138 // a new client.
9139 b.doRebind = true;
9140 }
9141 }
9142
9143 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9144
9145 Binder.restoreCallingIdentity(origId);
9146 }
9147 }
9148 }
9149
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009150 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 synchronized(this) {
9152 if (!(token instanceof ServiceRecord)) {
9153 throw new IllegalArgumentException("Invalid service token");
9154 }
9155 ServiceRecord r = (ServiceRecord)token;
9156 boolean inStopping = mStoppingServices.contains(token);
9157 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009158 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009159 + ": nesting=" + r.executeNesting
9160 + ", inStopping=" + inStopping);
9161 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009162 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 + " with incorrect token: given " + token
9164 + ", expected " + r);
9165 return;
9166 }
9167
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009168 if (type == 1) {
9169 // This is a call from a service start... take care of
9170 // book-keeping.
9171 r.callStart = true;
9172 switch (res) {
9173 case Service.START_STICKY_COMPATIBILITY:
9174 case Service.START_STICKY: {
9175 // We are done with the associated start arguments.
9176 r.findDeliveredStart(startId, true);
9177 // Don't stop if killed.
9178 r.stopIfKilled = false;
9179 break;
9180 }
9181 case Service.START_NOT_STICKY: {
9182 // We are done with the associated start arguments.
9183 r.findDeliveredStart(startId, true);
9184 if (r.lastStartId == startId) {
9185 // There is no more work, and this service
9186 // doesn't want to hang around if killed.
9187 r.stopIfKilled = true;
9188 }
9189 break;
9190 }
9191 case Service.START_REDELIVER_INTENT: {
9192 // We'll keep this item until they explicitly
9193 // call stop for it, but keep track of the fact
9194 // that it was delivered.
9195 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9196 if (si != null) {
9197 si.deliveryCount = 0;
9198 si.doneExecutingCount++;
9199 // Don't stop if killed.
9200 r.stopIfKilled = true;
9201 }
9202 break;
9203 }
9204 default:
9205 throw new IllegalArgumentException(
9206 "Unknown service start result: " + res);
9207 }
9208 if (res == Service.START_STICKY_COMPATIBILITY) {
9209 r.callStart = false;
9210 }
9211 }
9212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 final long origId = Binder.clearCallingIdentity();
9214 serviceDoneExecutingLocked(r, inStopping);
9215 Binder.restoreCallingIdentity(origId);
9216 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009217 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 + " with token " + token);
9219 }
9220 }
9221 }
9222
9223 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9224 r.executeNesting--;
9225 if (r.executeNesting <= 0 && r.app != null) {
9226 r.app.executingServices.remove(r);
9227 if (r.app.executingServices.size() == 0) {
9228 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9229 }
9230 if (inStopping) {
9231 mStoppingServices.remove(r);
9232 }
9233 updateOomAdjLocked(r.app);
9234 }
9235 }
9236
9237 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009238 String anrMessage = null;
9239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 synchronized(this) {
9241 if (proc.executingServices.size() == 0 || proc.thread == null) {
9242 return;
9243 }
9244 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9245 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9246 ServiceRecord timeout = null;
9247 long nextTime = 0;
9248 while (it.hasNext()) {
9249 ServiceRecord sr = it.next();
9250 if (sr.executingStart < maxTime) {
9251 timeout = sr;
9252 break;
9253 }
9254 if (sr.executingStart > nextTime) {
9255 nextTime = sr.executingStart;
9256 }
9257 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009258 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009259 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009260 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 } else {
9262 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9263 msg.obj = proc;
9264 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9265 }
9266 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009267
9268 if (anrMessage != null) {
9269 appNotResponding(proc, null, null, anrMessage);
9270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 }
9272
9273 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009274 // BACKUP AND RESTORE
9275 // =========================================================
9276
9277 // Cause the target app to be launched if necessary and its backup agent
9278 // instantiated. The backup agent will invoke backupAgentCreated() on the
9279 // activity manager to announce its creation.
9280 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009281 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009282 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9283
9284 synchronized(this) {
9285 // !!! TODO: currently no check here that we're already bound
9286 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9287 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9288 synchronized (stats) {
9289 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9290 }
9291
9292 BackupRecord r = new BackupRecord(ss, app, backupMode);
9293 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9294 // startProcessLocked() returns existing proc's record if it's already running
9295 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009296 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009297 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009298 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009299 return false;
9300 }
9301
9302 r.app = proc;
9303 mBackupTarget = r;
9304 mBackupAppName = app.packageName;
9305
Christopher Tate6fa95972009-06-05 18:43:55 -07009306 // Try not to kill the process during backup
9307 updateOomAdjLocked(proc);
9308
Christopher Tate181fafa2009-05-14 11:12:14 -07009309 // If the process is already attached, schedule the creation of the backup agent now.
9310 // If it is not yet live, this will be done when it attaches to the framework.
9311 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009312 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009313 try {
9314 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9315 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009316 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009317 }
9318 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009319 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009320 }
9321 // Invariants: at this point, the target app process exists and the application
9322 // is either already running or in the process of coming up. mBackupTarget and
9323 // mBackupAppName describe the app, so that when it binds back to the AM we
9324 // know that it's scheduled for a backup-agent operation.
9325 }
9326
9327 return true;
9328 }
9329
9330 // A backup agent has just come up
9331 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009332 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009333 + " = " + agent);
9334
9335 synchronized(this) {
9336 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009337 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009338 return;
9339 }
9340
Christopher Tate043dadc2009-06-02 16:11:00 -07009341 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009342 try {
9343 IBackupManager bm = IBackupManager.Stub.asInterface(
9344 ServiceManager.getService(Context.BACKUP_SERVICE));
9345 bm.agentConnected(agentPackageName, agent);
9346 } catch (RemoteException e) {
9347 // can't happen; the backup manager service is local
9348 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009349 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009350 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009351 } finally {
9352 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009353 }
9354 }
9355 }
9356
9357 // done with this agent
9358 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009359 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009360 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009362 return;
9363 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009364
9365 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009366 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009367 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009368 return;
9369 }
9370
Christopher Tate181fafa2009-05-14 11:12:14 -07009371 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009372 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009373 return;
9374 }
9375
Christopher Tate6fa95972009-06-05 18:43:55 -07009376 ProcessRecord proc = mBackupTarget.app;
9377 mBackupTarget = null;
9378 mBackupAppName = null;
9379
9380 // Not backing this app up any more; reset its OOM adjustment
9381 updateOomAdjLocked(proc);
9382
Christopher Tatec7b31e32009-06-10 15:49:30 -07009383 // If the app crashed during backup, 'thread' will be null here
9384 if (proc.thread != null) {
9385 try {
9386 proc.thread.scheduleDestroyBackupAgent(appInfo);
9387 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009388 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009389 e.printStackTrace();
9390 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009391 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009392 }
9393 }
9394 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 // BROADCASTS
9396 // =========================================================
9397
Josh Bartel7f208742010-02-25 11:01:44 -06009398 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 List cur) {
9400 final ContentResolver resolver = mContext.getContentResolver();
9401 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9402 if (list == null) {
9403 return cur;
9404 }
9405 int N = list.size();
9406 for (int i=0; i<N; i++) {
9407 Intent intent = list.get(i);
9408 if (filter.match(resolver, intent, true, TAG) >= 0) {
9409 if (cur == null) {
9410 cur = new ArrayList<Intent>();
9411 }
9412 cur.add(intent);
9413 }
9414 }
9415 return cur;
9416 }
9417
9418 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009419 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 + mBroadcastsScheduled);
9421
9422 if (mBroadcastsScheduled) {
9423 return;
9424 }
9425 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9426 mBroadcastsScheduled = true;
9427 }
9428
9429 public Intent registerReceiver(IApplicationThread caller,
9430 IIntentReceiver receiver, IntentFilter filter, String permission) {
9431 synchronized(this) {
9432 ProcessRecord callerApp = null;
9433 if (caller != null) {
9434 callerApp = getRecordForAppLocked(caller);
9435 if (callerApp == null) {
9436 throw new SecurityException(
9437 "Unable to find app for caller " + caller
9438 + " (pid=" + Binder.getCallingPid()
9439 + ") when registering receiver " + receiver);
9440 }
9441 }
9442
9443 List allSticky = null;
9444
9445 // Look for any matching sticky broadcasts...
9446 Iterator actions = filter.actionsIterator();
9447 if (actions != null) {
9448 while (actions.hasNext()) {
9449 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009450 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009451 }
9452 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009453 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 }
9455
9456 // The first sticky in the list is returned directly back to
9457 // the client.
9458 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9459
Joe Onorato8a9b2202010-02-26 18:56:32 -08009460 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 + ": " + sticky);
9462
9463 if (receiver == null) {
9464 return sticky;
9465 }
9466
9467 ReceiverList rl
9468 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9469 if (rl == null) {
9470 rl = new ReceiverList(this, callerApp,
9471 Binder.getCallingPid(),
9472 Binder.getCallingUid(), receiver);
9473 if (rl.app != null) {
9474 rl.app.receivers.add(rl);
9475 } else {
9476 try {
9477 receiver.asBinder().linkToDeath(rl, 0);
9478 } catch (RemoteException e) {
9479 return sticky;
9480 }
9481 rl.linkedToDeath = true;
9482 }
9483 mRegisteredReceivers.put(receiver.asBinder(), rl);
9484 }
9485 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9486 rl.add(bf);
9487 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009488 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 }
9490 mReceiverResolver.addFilter(bf);
9491
9492 // Enqueue broadcasts for all existing stickies that match
9493 // this filter.
9494 if (allSticky != null) {
9495 ArrayList receivers = new ArrayList();
9496 receivers.add(bf);
9497
9498 int N = allSticky.size();
9499 for (int i=0; i<N; i++) {
9500 Intent intent = (Intent)allSticky.get(i);
9501 BroadcastRecord r = new BroadcastRecord(intent, null,
9502 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009503 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009504 if (mParallelBroadcasts.size() == 0) {
9505 scheduleBroadcastsLocked();
9506 }
9507 mParallelBroadcasts.add(r);
9508 }
9509 }
9510
9511 return sticky;
9512 }
9513 }
9514
9515 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009516 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517
9518 boolean doNext = false;
9519
9520 synchronized(this) {
9521 ReceiverList rl
9522 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9523 if (rl != null) {
9524 if (rl.curBroadcast != null) {
9525 BroadcastRecord r = rl.curBroadcast;
9526 doNext = finishReceiverLocked(
9527 receiver.asBinder(), r.resultCode, r.resultData,
9528 r.resultExtras, r.resultAbort, true);
9529 }
9530
9531 if (rl.app != null) {
9532 rl.app.receivers.remove(rl);
9533 }
9534 removeReceiverLocked(rl);
9535 if (rl.linkedToDeath) {
9536 rl.linkedToDeath = false;
9537 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9538 }
9539 }
9540 }
9541
9542 if (!doNext) {
9543 return;
9544 }
9545
9546 final long origId = Binder.clearCallingIdentity();
9547 processNextBroadcast(false);
9548 trimApplications();
9549 Binder.restoreCallingIdentity(origId);
9550 }
9551
9552 void removeReceiverLocked(ReceiverList rl) {
9553 mRegisteredReceivers.remove(rl.receiver.asBinder());
9554 int N = rl.size();
9555 for (int i=0; i<N; i++) {
9556 mReceiverResolver.removeFilter(rl.get(i));
9557 }
9558 }
9559
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009560 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9561 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9562 ProcessRecord r = mLruProcesses.get(i);
9563 if (r.thread != null) {
9564 try {
9565 r.thread.dispatchPackageBroadcast(cmd, packages);
9566 } catch (RemoteException ex) {
9567 }
9568 }
9569 }
9570 }
9571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 private final int broadcastIntentLocked(ProcessRecord callerApp,
9573 String callerPackage, Intent intent, String resolvedType,
9574 IIntentReceiver resultTo, int resultCode, String resultData,
9575 Bundle map, String requiredPermission,
9576 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9577 intent = new Intent(intent);
9578
Joe Onorato8a9b2202010-02-26 18:56:32 -08009579 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9581 + " ordered=" + ordered);
9582 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009583 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009584 }
9585
9586 // Handle special intents: if this broadcast is from the package
9587 // manager about a package being removed, we need to remove all of
9588 // its activities from the history stack.
9589 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9590 intent.getAction());
9591 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9592 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009593 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009594 || uidRemoved) {
9595 if (checkComponentPermission(
9596 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9597 callingPid, callingUid, -1)
9598 == PackageManager.PERMISSION_GRANTED) {
9599 if (uidRemoved) {
9600 final Bundle intentExtras = intent.getExtras();
9601 final int uid = intentExtras != null
9602 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9603 if (uid >= 0) {
9604 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9605 synchronized (bs) {
9606 bs.removeUidStatsLocked(uid);
9607 }
9608 }
9609 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009610 // If resources are unvailble just force stop all
9611 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009612 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009613 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9614 if (list != null && (list.length > 0)) {
9615 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009616 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009617 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009618 sendPackageBroadcastLocked(
9619 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009620 }
9621 } else {
9622 Uri data = intent.getData();
9623 String ssp;
9624 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9625 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9626 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009627 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009628 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009629 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9630 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9631 new String[] {ssp});
9632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 }
9634 }
9635 }
9636 } else {
9637 String msg = "Permission Denial: " + intent.getAction()
9638 + " broadcast from " + callerPackage + " (pid=" + callingPid
9639 + ", uid=" + callingUid + ")"
9640 + " requires "
9641 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009642 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 throw new SecurityException(msg);
9644 }
9645 }
9646
9647 /*
9648 * If this is the time zone changed action, queue up a message that will reset the timezone
9649 * of all currently running processes. This message will get queued up before the broadcast
9650 * happens.
9651 */
9652 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9653 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9654 }
9655
Dianne Hackborn854060af2009-07-09 18:14:31 -07009656 /*
9657 * Prevent non-system code (defined here to be non-persistent
9658 * processes) from sending protected broadcasts.
9659 */
9660 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9661 || callingUid == Process.SHELL_UID || callingUid == 0) {
9662 // Always okay.
9663 } else if (callerApp == null || !callerApp.persistent) {
9664 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009665 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009666 intent.getAction())) {
9667 String msg = "Permission Denial: not allowed to send broadcast "
9668 + intent.getAction() + " from pid="
9669 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009670 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009671 throw new SecurityException(msg);
9672 }
9673 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009674 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009675 return BROADCAST_SUCCESS;
9676 }
9677 }
9678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 // Add to the sticky list if requested.
9680 if (sticky) {
9681 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9682 callingPid, callingUid)
9683 != PackageManager.PERMISSION_GRANTED) {
9684 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9685 + callingPid + ", uid=" + callingUid
9686 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009687 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688 throw new SecurityException(msg);
9689 }
9690 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009691 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 + " and enforce permission " + requiredPermission);
9693 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9694 }
9695 if (intent.getComponent() != null) {
9696 throw new SecurityException(
9697 "Sticky broadcasts can't target a specific component");
9698 }
9699 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9700 if (list == null) {
9701 list = new ArrayList<Intent>();
9702 mStickyBroadcasts.put(intent.getAction(), list);
9703 }
9704 int N = list.size();
9705 int i;
9706 for (i=0; i<N; i++) {
9707 if (intent.filterEquals(list.get(i))) {
9708 // This sticky already exists, replace it.
9709 list.set(i, new Intent(intent));
9710 break;
9711 }
9712 }
9713 if (i >= N) {
9714 list.add(new Intent(intent));
9715 }
9716 }
9717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009718 // Figure out who all will receive this broadcast.
9719 List receivers = null;
9720 List<BroadcastFilter> registeredReceivers = null;
9721 try {
9722 if (intent.getComponent() != null) {
9723 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009724 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009725 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726 if (ai != null) {
9727 receivers = new ArrayList();
9728 ResolveInfo ri = new ResolveInfo();
9729 ri.activityInfo = ai;
9730 receivers.add(ri);
9731 }
9732 } else {
9733 // Need to resolve the intent to interested receivers...
9734 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9735 == 0) {
9736 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009737 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009738 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 }
Mihai Preda074edef2009-05-18 17:13:31 +02009740 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 }
9742 } catch (RemoteException ex) {
9743 // pm is in same process, this will never happen.
9744 }
9745
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009746 final boolean replacePending =
9747 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9748
Joe Onorato8a9b2202010-02-26 18:56:32 -08009749 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009750 + " replacePending=" + replacePending);
9751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9753 if (!ordered && NR > 0) {
9754 // If we are not serializing this broadcast, then send the
9755 // registered receivers separately so they don't wait for the
9756 // components to be launched.
9757 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9758 callerPackage, callingPid, callingUid, requiredPermission,
9759 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009760 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009761 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 TAG, "Enqueueing parallel broadcast " + r
9763 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009764 boolean replaced = false;
9765 if (replacePending) {
9766 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9767 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009768 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009769 "***** DROPPING PARALLEL: " + intent);
9770 mParallelBroadcasts.set(i, r);
9771 replaced = true;
9772 break;
9773 }
9774 }
9775 }
9776 if (!replaced) {
9777 mParallelBroadcasts.add(r);
9778 scheduleBroadcastsLocked();
9779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 registeredReceivers = null;
9781 NR = 0;
9782 }
9783
9784 // Merge into one list.
9785 int ir = 0;
9786 if (receivers != null) {
9787 // A special case for PACKAGE_ADDED: do not allow the package
9788 // being added to see this broadcast. This prevents them from
9789 // using this as a back door to get run as soon as they are
9790 // installed. Maybe in the future we want to have a special install
9791 // broadcast or such for apps, but we'd like to deliberately make
9792 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009793 String skipPackages[] = null;
9794 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9795 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9796 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9797 Uri data = intent.getData();
9798 if (data != null) {
9799 String pkgName = data.getSchemeSpecificPart();
9800 if (pkgName != null) {
9801 skipPackages = new String[] { pkgName };
9802 }
9803 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009804 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009805 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009806 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009807 if (skipPackages != null && (skipPackages.length > 0)) {
9808 for (String skipPackage : skipPackages) {
9809 if (skipPackage != null) {
9810 int NT = receivers.size();
9811 for (int it=0; it<NT; it++) {
9812 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9813 if (curt.activityInfo.packageName.equals(skipPackage)) {
9814 receivers.remove(it);
9815 it--;
9816 NT--;
9817 }
9818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 }
9820 }
9821 }
9822
9823 int NT = receivers != null ? receivers.size() : 0;
9824 int it = 0;
9825 ResolveInfo curt = null;
9826 BroadcastFilter curr = null;
9827 while (it < NT && ir < NR) {
9828 if (curt == null) {
9829 curt = (ResolveInfo)receivers.get(it);
9830 }
9831 if (curr == null) {
9832 curr = registeredReceivers.get(ir);
9833 }
9834 if (curr.getPriority() >= curt.priority) {
9835 // Insert this broadcast record into the final list.
9836 receivers.add(it, curr);
9837 ir++;
9838 curr = null;
9839 it++;
9840 NT++;
9841 } else {
9842 // Skip to the next ResolveInfo in the final list.
9843 it++;
9844 curt = null;
9845 }
9846 }
9847 }
9848 while (ir < NR) {
9849 if (receivers == null) {
9850 receivers = new ArrayList();
9851 }
9852 receivers.add(registeredReceivers.get(ir));
9853 ir++;
9854 }
9855
9856 if ((receivers != null && receivers.size() > 0)
9857 || resultTo != null) {
9858 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9859 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009860 receivers, resultTo, resultCode, resultData, map, ordered,
9861 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009862 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009863 TAG, "Enqueueing ordered broadcast " + r
9864 + ": prev had " + mOrderedBroadcasts.size());
9865 if (DEBUG_BROADCAST) {
9866 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009867 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009869 boolean replaced = false;
9870 if (replacePending) {
9871 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9872 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009873 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009874 "***** DROPPING ORDERED: " + intent);
9875 mOrderedBroadcasts.set(i, r);
9876 replaced = true;
9877 break;
9878 }
9879 }
9880 }
9881 if (!replaced) {
9882 mOrderedBroadcasts.add(r);
9883 scheduleBroadcastsLocked();
9884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 }
9886
9887 return BROADCAST_SUCCESS;
9888 }
9889
9890 public final int broadcastIntent(IApplicationThread caller,
9891 Intent intent, String resolvedType, IIntentReceiver resultTo,
9892 int resultCode, String resultData, Bundle map,
9893 String requiredPermission, boolean serialized, boolean sticky) {
9894 // Refuse possible leaked file descriptors
9895 if (intent != null && intent.hasFileDescriptors() == true) {
9896 throw new IllegalArgumentException("File descriptors passed in Intent");
9897 }
9898
9899 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009900 int flags = intent.getFlags();
9901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 if (!mSystemReady) {
9903 // if the caller really truly claims to know what they're doing, go
9904 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9906 intent = new Intent(intent);
9907 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9908 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009909 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910 + " before boot completion");
9911 throw new IllegalStateException("Cannot broadcast before boot completed");
9912 }
9913 }
9914
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009915 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9916 throw new IllegalArgumentException(
9917 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9918 }
9919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9921 final int callingPid = Binder.getCallingPid();
9922 final int callingUid = Binder.getCallingUid();
9923 final long origId = Binder.clearCallingIdentity();
9924 int res = broadcastIntentLocked(callerApp,
9925 callerApp != null ? callerApp.info.packageName : null,
9926 intent, resolvedType, resultTo,
9927 resultCode, resultData, map, requiredPermission, serialized,
9928 sticky, callingPid, callingUid);
9929 Binder.restoreCallingIdentity(origId);
9930 return res;
9931 }
9932 }
9933
9934 int broadcastIntentInPackage(String packageName, int uid,
9935 Intent intent, String resolvedType, IIntentReceiver resultTo,
9936 int resultCode, String resultData, Bundle map,
9937 String requiredPermission, boolean serialized, boolean sticky) {
9938 synchronized(this) {
9939 final long origId = Binder.clearCallingIdentity();
9940 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9941 resultTo, resultCode, resultData, map, requiredPermission,
9942 serialized, sticky, -1, uid);
9943 Binder.restoreCallingIdentity(origId);
9944 return res;
9945 }
9946 }
9947
9948 public final void unbroadcastIntent(IApplicationThread caller,
9949 Intent intent) {
9950 // Refuse possible leaked file descriptors
9951 if (intent != null && intent.hasFileDescriptors() == true) {
9952 throw new IllegalArgumentException("File descriptors passed in Intent");
9953 }
9954
9955 synchronized(this) {
9956 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9957 != PackageManager.PERMISSION_GRANTED) {
9958 String msg = "Permission Denial: unbroadcastIntent() from pid="
9959 + Binder.getCallingPid()
9960 + ", uid=" + Binder.getCallingUid()
9961 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009962 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 throw new SecurityException(msg);
9964 }
9965 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9966 if (list != null) {
9967 int N = list.size();
9968 int i;
9969 for (i=0; i<N; i++) {
9970 if (intent.filterEquals(list.get(i))) {
9971 list.remove(i);
9972 break;
9973 }
9974 }
9975 }
9976 }
9977 }
9978
9979 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9980 String resultData, Bundle resultExtras, boolean resultAbort,
9981 boolean explicit) {
9982 if (mOrderedBroadcasts.size() == 0) {
9983 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009984 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 }
9986 return false;
9987 }
9988 BroadcastRecord r = mOrderedBroadcasts.get(0);
9989 if (r.receiver == null) {
9990 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009991 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 }
9993 return false;
9994 }
9995 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009996 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 return false;
9998 }
9999 int state = r.state;
10000 r.state = r.IDLE;
10001 if (state == r.IDLE) {
10002 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010003 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 }
10005 }
10006 r.receiver = null;
10007 r.intent.setComponent(null);
10008 if (r.curApp != null) {
10009 r.curApp.curReceiver = null;
10010 }
10011 if (r.curFilter != null) {
10012 r.curFilter.receiverList.curBroadcast = null;
10013 }
10014 r.curFilter = null;
10015 r.curApp = null;
10016 r.curComponent = null;
10017 r.curReceiver = null;
10018 mPendingBroadcast = null;
10019
10020 r.resultCode = resultCode;
10021 r.resultData = resultData;
10022 r.resultExtras = resultExtras;
10023 r.resultAbort = resultAbort;
10024
10025 // We will process the next receiver right now if this is finishing
10026 // an app receiver (which is always asynchronous) or after we have
10027 // come back from calling a receiver.
10028 return state == BroadcastRecord.APP_RECEIVE
10029 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10030 }
10031
10032 public void finishReceiver(IBinder who, int resultCode, String resultData,
10033 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010034 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035
10036 // Refuse possible leaked file descriptors
10037 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10038 throw new IllegalArgumentException("File descriptors passed in Bundle");
10039 }
10040
10041 boolean doNext;
10042
10043 final long origId = Binder.clearCallingIdentity();
10044
10045 synchronized(this) {
10046 doNext = finishReceiverLocked(
10047 who, resultCode, resultData, resultExtras, resultAbort, true);
10048 }
10049
10050 if (doNext) {
10051 processNextBroadcast(false);
10052 }
10053 trimApplications();
10054
10055 Binder.restoreCallingIdentity(origId);
10056 }
10057
10058 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10059 if (r.nextReceiver > 0) {
10060 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10061 if (curReceiver instanceof BroadcastFilter) {
10062 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010063 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 System.identityHashCode(r),
10065 r.intent.getAction(),
10066 r.nextReceiver - 1,
10067 System.identityHashCode(bf));
10068 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010069 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 System.identityHashCode(r),
10071 r.intent.getAction(),
10072 r.nextReceiver - 1,
10073 ((ResolveInfo)curReceiver).toString());
10074 }
10075 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010076 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010078 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010079 System.identityHashCode(r),
10080 r.intent.getAction(),
10081 r.nextReceiver,
10082 "NONE");
10083 }
10084 }
10085
10086 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010087 ProcessRecord app = null;
10088 String anrMessage = null;
10089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010090 synchronized (this) {
10091 if (mOrderedBroadcasts.size() == 0) {
10092 return;
10093 }
10094 long now = SystemClock.uptimeMillis();
10095 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010096 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010097 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010099 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010100 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010101 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 return;
10103 }
10104
Joe Onorato8a9b2202010-02-26 18:56:32 -080010105 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010106 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 r.anrCount++;
10108
10109 // Current receiver has passed its expiration date.
10110 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010111 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 return;
10113 }
10114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010116 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 logBroadcastReceiverDiscard(r);
10118 if (curReceiver instanceof BroadcastFilter) {
10119 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10120 if (bf.receiverList.pid != 0
10121 && bf.receiverList.pid != MY_PID) {
10122 synchronized (this.mPidsSelfLocked) {
10123 app = this.mPidsSelfLocked.get(
10124 bf.receiverList.pid);
10125 }
10126 }
10127 } else {
10128 app = r.curApp;
10129 }
10130
10131 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010132 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 }
10134
10135 if (mPendingBroadcast == r) {
10136 mPendingBroadcast = null;
10137 }
10138
10139 // Move on to the next receiver.
10140 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10141 r.resultExtras, r.resultAbort, true);
10142 scheduleBroadcastsLocked();
10143 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010144
10145 if (anrMessage != null) {
10146 appNotResponding(app, null, null, anrMessage);
10147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 }
10149
10150 private final void processCurBroadcastLocked(BroadcastRecord r,
10151 ProcessRecord app) throws RemoteException {
10152 if (app.thread == null) {
10153 throw new RemoteException();
10154 }
10155 r.receiver = app.thread.asBinder();
10156 r.curApp = app;
10157 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010158 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010159
10160 // Tell the application to launch this receiver.
10161 r.intent.setComponent(r.curComponent);
10162
10163 boolean started = false;
10164 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010165 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 "Delivering to component " + r.curComponent
10167 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010168 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010169 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10170 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10171 started = true;
10172 } finally {
10173 if (!started) {
10174 r.receiver = null;
10175 r.curApp = null;
10176 app.curReceiver = null;
10177 }
10178 }
10179
10180 }
10181
10182 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010183 Intent intent, int resultCode, String data, Bundle extras,
10184 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010185 if (app != null && app.thread != null) {
10186 // If we have an app thread, do the call through that so it is
10187 // correctly ordered with other one-way calls.
10188 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010189 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010191 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 }
10193 }
10194
10195 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10196 BroadcastFilter filter, boolean ordered) {
10197 boolean skip = false;
10198 if (filter.requiredPermission != null) {
10199 int perm = checkComponentPermission(filter.requiredPermission,
10200 r.callingPid, r.callingUid, -1);
10201 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010202 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 + r.intent.toString()
10204 + " from " + r.callerPackage + " (pid="
10205 + r.callingPid + ", uid=" + r.callingUid + ")"
10206 + " requires " + filter.requiredPermission
10207 + " due to registered receiver " + filter);
10208 skip = true;
10209 }
10210 }
10211 if (r.requiredPermission != null) {
10212 int perm = checkComponentPermission(r.requiredPermission,
10213 filter.receiverList.pid, filter.receiverList.uid, -1);
10214 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010215 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010216 + r.intent.toString()
10217 + " to " + filter.receiverList.app
10218 + " (pid=" + filter.receiverList.pid
10219 + ", uid=" + filter.receiverList.uid + ")"
10220 + " requires " + r.requiredPermission
10221 + " due to sender " + r.callerPackage
10222 + " (uid " + r.callingUid + ")");
10223 skip = true;
10224 }
10225 }
10226
10227 if (!skip) {
10228 // If this is not being sent as an ordered broadcast, then we
10229 // don't want to touch the fields that keep track of the current
10230 // state of ordered broadcasts.
10231 if (ordered) {
10232 r.receiver = filter.receiverList.receiver.asBinder();
10233 r.curFilter = filter;
10234 filter.receiverList.curBroadcast = r;
10235 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010236 if (filter.receiverList.app != null) {
10237 // Bump hosting application to no longer be in background
10238 // scheduling class. Note that we can't do that if there
10239 // isn't an app... but we can only be in that case for
10240 // things that directly call the IActivityManager API, which
10241 // are already core system stuff so don't matter for this.
10242 r.curApp = filter.receiverList.app;
10243 filter.receiverList.app.curReceiver = r;
10244 updateOomAdjLocked();
10245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 }
10247 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010248 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010250 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010251 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010252 }
10253 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10254 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010255 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 if (ordered) {
10257 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10258 }
10259 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010260 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 if (ordered) {
10262 r.receiver = null;
10263 r.curFilter = null;
10264 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010265 if (filter.receiverList.app != null) {
10266 filter.receiverList.app.curReceiver = null;
10267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 }
10269 }
10270 }
10271 }
10272
Dianne Hackborn12527f92009-11-11 17:39:50 -080010273 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10274 if (r.callingUid < 0) {
10275 // This was from a registerReceiver() call; ignore it.
10276 return;
10277 }
10278 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10279 MAX_BROADCAST_HISTORY-1);
10280 r.finishTime = SystemClock.uptimeMillis();
10281 mBroadcastHistory[0] = r;
10282 }
10283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 private final void processNextBroadcast(boolean fromMsg) {
10285 synchronized(this) {
10286 BroadcastRecord r;
10287
Joe Onorato8a9b2202010-02-26 18:56:32 -080010288 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010290 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291
10292 updateCpuStats();
10293
10294 if (fromMsg) {
10295 mBroadcastsScheduled = false;
10296 }
10297
10298 // First, deliver any non-serialized broadcasts right away.
10299 while (mParallelBroadcasts.size() > 0) {
10300 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010301 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010304 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010305 for (int i=0; i<N; i++) {
10306 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010307 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010308 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 + target + ": " + r);
10310 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10311 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010312 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010313 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010314 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 }
10316
10317 // Now take care of the next serialized one...
10318
10319 // If we are waiting for a process to come up to handle the next
10320 // broadcast, then do nothing at this point. Just in case, we
10321 // check that the process we're waiting for still exists.
10322 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010323 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010324 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010325 + mPendingBroadcast.curApp);
10326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327
10328 boolean isDead;
10329 synchronized (mPidsSelfLocked) {
10330 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10331 }
10332 if (!isDead) {
10333 // It's still alive, so keep waiting
10334 return;
10335 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010336 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010337 + " died before responding to broadcast");
10338 mPendingBroadcast = null;
10339 }
10340 }
10341
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010342 boolean looped = false;
10343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010344 do {
10345 if (mOrderedBroadcasts.size() == 0) {
10346 // No more broadcasts pending, so all done!
10347 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010348 if (looped) {
10349 // If we had finished the last ordered broadcast, then
10350 // make sure all processes have correct oom and sched
10351 // adjustments.
10352 updateOomAdjLocked();
10353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 return;
10355 }
10356 r = mOrderedBroadcasts.get(0);
10357 boolean forceReceive = false;
10358
10359 // Ensure that even if something goes awry with the timeout
10360 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010361 // and continue to make progress.
10362 //
10363 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10364 // receivers don't get executed with with timeouts. They're intended for
10365 // one time heavy lifting after system upgrades and can take
10366 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010368 if (mSystemReady && r.dispatchTime > 0) {
10369 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 if ((numReceivers > 0) &&
10371 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010372 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 + " now=" + now
10374 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010375 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010376 + " intent=" + r.intent
10377 + " numReceivers=" + numReceivers
10378 + " nextReceiver=" + r.nextReceiver
10379 + " state=" + r.state);
10380 broadcastTimeout(); // forcibly finish this broadcast
10381 forceReceive = true;
10382 r.state = BroadcastRecord.IDLE;
10383 }
10384 }
10385
10386 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010387 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 "processNextBroadcast() called when not idle (state="
10389 + r.state + ")");
10390 return;
10391 }
10392
10393 if (r.receivers == null || r.nextReceiver >= numReceivers
10394 || r.resultAbort || forceReceive) {
10395 // No more receivers for this broadcast! Send the final
10396 // result if requested...
10397 if (r.resultTo != null) {
10398 try {
10399 if (DEBUG_BROADCAST) {
10400 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010401 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 + " seq=" + seq + " app=" + r.callerApp);
10403 }
10404 performReceive(r.callerApp, r.resultTo,
10405 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010406 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010408 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010409 }
10410 }
10411
Joe Onorato8a9b2202010-02-26 18:56:32 -080010412 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010413 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10414
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010416 + r);
10417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010419 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 mOrderedBroadcasts.remove(0);
10421 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010422 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 continue;
10424 }
10425 } while (r == null);
10426
10427 // Get the next receiver...
10428 int recIdx = r.nextReceiver++;
10429
10430 // Keep track of when this receiver started, and make sure there
10431 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010432 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010433 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010434 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435
Joe Onorato8a9b2202010-02-26 18:56:32 -080010436 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010437 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010438 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010440 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010441 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010442 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 }
10444
10445 Object nextReceiver = r.receivers.get(recIdx);
10446 if (nextReceiver instanceof BroadcastFilter) {
10447 // Simple case: this is a registered receiver who gets
10448 // a direct call.
10449 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010450 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010451 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010452 + filter + ": " + r);
10453 deliverToRegisteredReceiver(r, filter, r.ordered);
10454 if (r.receiver == null || !r.ordered) {
10455 // The receiver has already finished, so schedule to
10456 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010457 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10458 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 r.state = BroadcastRecord.IDLE;
10460 scheduleBroadcastsLocked();
10461 }
10462 return;
10463 }
10464
10465 // Hard case: need to instantiate the receiver, possibly
10466 // starting its application process to host it.
10467
10468 ResolveInfo info =
10469 (ResolveInfo)nextReceiver;
10470
10471 boolean skip = false;
10472 int perm = checkComponentPermission(info.activityInfo.permission,
10473 r.callingPid, r.callingUid,
10474 info.activityInfo.exported
10475 ? -1 : info.activityInfo.applicationInfo.uid);
10476 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010477 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 + r.intent.toString()
10479 + " from " + r.callerPackage + " (pid=" + r.callingPid
10480 + ", uid=" + r.callingUid + ")"
10481 + " requires " + info.activityInfo.permission
10482 + " due to receiver " + info.activityInfo.packageName
10483 + "/" + info.activityInfo.name);
10484 skip = true;
10485 }
10486 if (r.callingUid != Process.SYSTEM_UID &&
10487 r.requiredPermission != null) {
10488 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010489 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 checkPermission(r.requiredPermission,
10491 info.activityInfo.applicationInfo.packageName);
10492 } catch (RemoteException e) {
10493 perm = PackageManager.PERMISSION_DENIED;
10494 }
10495 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010496 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 + r.intent + " to "
10498 + info.activityInfo.applicationInfo.packageName
10499 + " requires " + r.requiredPermission
10500 + " due to sender " + r.callerPackage
10501 + " (uid " + r.callingUid + ")");
10502 skip = true;
10503 }
10504 }
10505 if (r.curApp != null && r.curApp.crashing) {
10506 // If the target process is crashing, just skip it.
10507 skip = true;
10508 }
10509
10510 if (skip) {
10511 r.receiver = null;
10512 r.curFilter = null;
10513 r.state = BroadcastRecord.IDLE;
10514 scheduleBroadcastsLocked();
10515 return;
10516 }
10517
10518 r.state = BroadcastRecord.APP_RECEIVE;
10519 String targetProcess = info.activityInfo.processName;
10520 r.curComponent = new ComponentName(
10521 info.activityInfo.applicationInfo.packageName,
10522 info.activityInfo.name);
10523 r.curReceiver = info.activityInfo;
10524
10525 // Is this receiver's application already running?
10526 ProcessRecord app = getProcessRecordLocked(targetProcess,
10527 info.activityInfo.applicationInfo.uid);
10528 if (app != null && app.thread != null) {
10529 try {
10530 processCurBroadcastLocked(r, app);
10531 return;
10532 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010533 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010534 + r.curComponent, e);
10535 }
10536
10537 // If a dead object exception was thrown -- fall through to
10538 // restart the application.
10539 }
10540
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010541 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010542 if ((r.curApp=startProcessLocked(targetProcess,
10543 info.activityInfo.applicationInfo, true,
10544 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010545 "broadcast", r.curComponent,
10546 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10547 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 // Ah, this recipient is unavailable. Finish it if necessary,
10549 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010550 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 + info.activityInfo.applicationInfo.packageName + "/"
10552 + info.activityInfo.applicationInfo.uid + " for broadcast "
10553 + r.intent + ": process is bad");
10554 logBroadcastReceiverDiscard(r);
10555 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10556 r.resultExtras, r.resultAbort, true);
10557 scheduleBroadcastsLocked();
10558 r.state = BroadcastRecord.IDLE;
10559 return;
10560 }
10561
10562 mPendingBroadcast = r;
10563 }
10564 }
10565
10566 // =========================================================
10567 // INSTRUMENTATION
10568 // =========================================================
10569
10570 public boolean startInstrumentation(ComponentName className,
10571 String profileFile, int flags, Bundle arguments,
10572 IInstrumentationWatcher watcher) {
10573 // Refuse possible leaked file descriptors
10574 if (arguments != null && arguments.hasFileDescriptors()) {
10575 throw new IllegalArgumentException("File descriptors passed in Bundle");
10576 }
10577
10578 synchronized(this) {
10579 InstrumentationInfo ii = null;
10580 ApplicationInfo ai = null;
10581 try {
10582 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010583 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010585 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 } catch (PackageManager.NameNotFoundException e) {
10587 }
10588 if (ii == null) {
10589 reportStartInstrumentationFailure(watcher, className,
10590 "Unable to find instrumentation info for: " + className);
10591 return false;
10592 }
10593 if (ai == null) {
10594 reportStartInstrumentationFailure(watcher, className,
10595 "Unable to find instrumentation target package: " + ii.targetPackage);
10596 return false;
10597 }
10598
10599 int match = mContext.getPackageManager().checkSignatures(
10600 ii.targetPackage, ii.packageName);
10601 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10602 String msg = "Permission Denial: starting instrumentation "
10603 + className + " from pid="
10604 + Binder.getCallingPid()
10605 + ", uid=" + Binder.getCallingPid()
10606 + " not allowed because package " + ii.packageName
10607 + " does not have a signature matching the target "
10608 + ii.targetPackage;
10609 reportStartInstrumentationFailure(watcher, className, msg);
10610 throw new SecurityException(msg);
10611 }
10612
10613 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010614 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 ProcessRecord app = addAppLocked(ai);
10616 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010617 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010618 app.instrumentationProfileFile = profileFile;
10619 app.instrumentationArguments = arguments;
10620 app.instrumentationWatcher = watcher;
10621 app.instrumentationResultClass = className;
10622 Binder.restoreCallingIdentity(origId);
10623 }
10624
10625 return true;
10626 }
10627
10628 /**
10629 * Report errors that occur while attempting to start Instrumentation. Always writes the
10630 * error to the logs, but if somebody is watching, send the report there too. This enables
10631 * the "am" command to report errors with more information.
10632 *
10633 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10634 * @param cn The component name of the instrumentation.
10635 * @param report The error report.
10636 */
10637 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10638 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010639 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 try {
10641 if (watcher != null) {
10642 Bundle results = new Bundle();
10643 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10644 results.putString("Error", report);
10645 watcher.instrumentationStatus(cn, -1, results);
10646 }
10647 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010648 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 }
10650 }
10651
10652 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10653 if (app.instrumentationWatcher != null) {
10654 try {
10655 // NOTE: IInstrumentationWatcher *must* be oneway here
10656 app.instrumentationWatcher.instrumentationFinished(
10657 app.instrumentationClass,
10658 resultCode,
10659 results);
10660 } catch (RemoteException e) {
10661 }
10662 }
10663 app.instrumentationWatcher = null;
10664 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010665 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 app.instrumentationProfileFile = null;
10667 app.instrumentationArguments = null;
10668
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010669 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 }
10671
10672 public void finishInstrumentation(IApplicationThread target,
10673 int resultCode, Bundle results) {
10674 // Refuse possible leaked file descriptors
10675 if (results != null && results.hasFileDescriptors()) {
10676 throw new IllegalArgumentException("File descriptors passed in Intent");
10677 }
10678
10679 synchronized(this) {
10680 ProcessRecord app = getRecordForAppLocked(target);
10681 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010682 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010683 return;
10684 }
10685 final long origId = Binder.clearCallingIdentity();
10686 finishInstrumentationLocked(app, resultCode, results);
10687 Binder.restoreCallingIdentity(origId);
10688 }
10689 }
10690
10691 // =========================================================
10692 // CONFIGURATION
10693 // =========================================================
10694
10695 public ConfigurationInfo getDeviceConfigurationInfo() {
10696 ConfigurationInfo config = new ConfigurationInfo();
10697 synchronized (this) {
10698 config.reqTouchScreen = mConfiguration.touchscreen;
10699 config.reqKeyboardType = mConfiguration.keyboard;
10700 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010701 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10702 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10704 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010705 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10706 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10708 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010709 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 }
10711 return config;
10712 }
10713
10714 public Configuration getConfiguration() {
10715 Configuration ci;
10716 synchronized(this) {
10717 ci = new Configuration(mConfiguration);
10718 }
10719 return ci;
10720 }
10721
10722 public void updateConfiguration(Configuration values) {
10723 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10724 "updateConfiguration()");
10725
10726 synchronized(this) {
10727 if (values == null && mWindowManager != null) {
10728 // sentinel: fetch the current configuration from the window manager
10729 values = mWindowManager.computeNewConfiguration();
10730 }
10731
10732 final long origId = Binder.clearCallingIdentity();
10733 updateConfigurationLocked(values, null);
10734 Binder.restoreCallingIdentity(origId);
10735 }
10736 }
10737
10738 /**
10739 * Do either or both things: (1) change the current configuration, and (2)
10740 * make sure the given activity is running with the (now) current
10741 * configuration. Returns true if the activity has been left running, or
10742 * false if <var>starting</var> is being destroyed to match the new
10743 * configuration.
10744 */
10745 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010746 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 int changes = 0;
10748
10749 boolean kept = true;
10750
10751 if (values != null) {
10752 Configuration newConfig = new Configuration(mConfiguration);
10753 changes = newConfig.updateFrom(values);
10754 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010755 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010756 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 }
10758
Doug Zongker2bec3d42009-12-04 12:52:44 -080010759 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760
10761 if (values.locale != null) {
10762 saveLocaleLocked(values.locale,
10763 !values.locale.equals(mConfiguration.locale),
10764 values.userSetLocale);
10765 }
10766
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010767 mConfigurationSeq++;
10768 if (mConfigurationSeq <= 0) {
10769 mConfigurationSeq = 1;
10770 }
10771 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010773 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010774
10775 AttributeCache ac = AttributeCache.instance();
10776 if (ac != null) {
10777 ac.updateConfiguration(mConfiguration);
10778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010780 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10781 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10782 msg.obj = new Configuration(mConfiguration);
10783 mHandler.sendMessage(msg);
10784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010786 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10787 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010788 try {
10789 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010790 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010791 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 app.thread.scheduleConfigurationChanged(mConfiguration);
10793 }
10794 } catch (Exception e) {
10795 }
10796 }
10797 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010798 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10799 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10801 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010802 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10803 broadcastIntentLocked(null, null,
10804 new Intent(Intent.ACTION_LOCALE_CHANGED),
10805 null, null, 0, null, null,
10806 null, false, false, MY_PID, Process.SYSTEM_UID);
10807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010808 }
10809 }
10810
10811 if (changes != 0 && starting == null) {
10812 // If the configuration changed, and the caller is not already
10813 // in the process of starting an activity, then find the top
10814 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010815 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 }
10817
10818 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010819 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010820 if (kept) {
10821 // If this didn't result in the starting activity being
10822 // destroyed, then we need to make sure at this point that all
10823 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010824 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010826 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 }
10828 }
10829
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010830 if (values != null && mWindowManager != null) {
10831 mWindowManager.setNewConfiguration(mConfiguration);
10832 }
10833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 return kept;
10835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836
10837 /**
10838 * Save the locale. You must be inside a synchronized (this) block.
10839 */
10840 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10841 if(isDiff) {
10842 SystemProperties.set("user.language", l.getLanguage());
10843 SystemProperties.set("user.region", l.getCountry());
10844 }
10845
10846 if(isPersist) {
10847 SystemProperties.set("persist.sys.language", l.getLanguage());
10848 SystemProperties.set("persist.sys.country", l.getCountry());
10849 SystemProperties.set("persist.sys.localevar", l.getVariant());
10850 }
10851 }
10852
10853 // =========================================================
10854 // LIFETIME MANAGEMENT
10855 // =========================================================
10856
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010857 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10858 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010860 // This adjustment has already been computed. If we are calling
10861 // from the top, we may have already computed our adjustment with
10862 // an earlier hidden adjustment that isn't really for us... if
10863 // so, use the new hidden adjustment.
10864 if (!recursed && app.hidden) {
10865 app.curAdj = hiddenAdj;
10866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867 return app.curAdj;
10868 }
10869
10870 if (app.thread == null) {
10871 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010872 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010873 return (app.curAdj=EMPTY_APP_ADJ);
10874 }
10875
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010876 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10877 // The max adjustment doesn't allow this app to be anything
10878 // below foreground, so it is not worth doing work for it.
10879 app.adjType = "fixed";
10880 app.adjSeq = mAdjSeq;
10881 app.curRawAdj = app.maxAdj;
10882 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10883 return (app.curAdj=app.maxAdj);
10884 }
10885
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010886 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010887 app.adjSource = null;
10888 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010889 app.empty = false;
10890 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891
The Android Open Source Project4df24232009-03-05 14:34:35 -080010892 // Determine the importance of the process, starting with most
10893 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010895 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010896 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010897 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 // The last app on the list is the foreground app.
10899 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010900 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010901 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010902 } else if (app.instrumentationClass != null) {
10903 // Don't want to kill running instrumentation.
10904 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010905 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010906 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010907 } else if (app.persistentActivities > 0) {
10908 // Special persistent activities... shouldn't be used these days.
10909 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010910 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010911 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010912 } else if (app.curReceiver != null ||
10913 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10914 // An app that is currently receiving a broadcast also
10915 // counts as being in the foreground.
10916 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010917 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010918 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 } else if (app.executingServices.size() > 0) {
10920 // An app that is currently executing a service callback also
10921 // counts as being in the foreground.
10922 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010923 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010924 app.adjType = "exec-service";
10925 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010927 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010928 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010929 app.adjType = "foreground-service";
10930 } else if (app.forcingToForeground != null) {
10931 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010932 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010933 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010934 app.adjType = "force-foreground";
10935 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010936 } else if (app == mHeavyWeightProcess) {
10937 // We don't want to kill the current heavy-weight process.
10938 adj = HEAVY_WEIGHT_APP_ADJ;
10939 schedGroup = Process.THREAD_GROUP_DEFAULT;
10940 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010941 } else if (app == mHomeProcess) {
10942 // This process is hosting what we currently consider to be the
10943 // home app, so we don't want to let it go into the background.
10944 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010945 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010946 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 } else if ((N=app.activities.size()) != 0) {
10948 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010949 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010951 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010952 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010953 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010955 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010957 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010959 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010960 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 break;
10962 }
10963 }
10964 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010965 // A very not-needed process. If this is lower in the lru list,
10966 // we will push it in to the empty bucket.
10967 app.hidden = true;
10968 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010969 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010970 adj = hiddenAdj;
10971 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010972 }
10973
Joe Onorato8a9b2202010-02-26 18:56:32 -080010974 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010975
The Android Open Source Project4df24232009-03-05 14:34:35 -080010976 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 // there are applications dependent on our services or providers, but
10978 // this gives us a baseline and makes sure we don't get into an
10979 // infinite recursion.
10980 app.adjSeq = mAdjSeq;
10981 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982
Christopher Tate6fa95972009-06-05 18:43:55 -070010983 if (mBackupTarget != null && app == mBackupTarget.app) {
10984 // If possible we want to avoid killing apps while they're being backed up
10985 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010986 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010987 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010988 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010989 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010990 }
10991 }
10992
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010993 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10994 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 final long now = SystemClock.uptimeMillis();
10996 // This process is more important if the top activity is
10997 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010998 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010999 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011000 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 if (s.startRequested) {
11002 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11003 // This service has seen some activity within
11004 // recent memory, so we will keep its process ahead
11005 // of the background processes.
11006 if (adj > SECONDARY_SERVER_ADJ) {
11007 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011008 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011009 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 }
11011 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011012 // If we have let the service slide into the background
11013 // state, still have some text describing what it is doing
11014 // even though the service no longer has an impact.
11015 if (adj > SECONDARY_SERVER_ADJ) {
11016 app.adjType = "started-bg-services";
11017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011019 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11020 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 Iterator<ConnectionRecord> kt
11022 = s.connections.values().iterator();
11023 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11024 // XXX should compute this based on the max of
11025 // all connected clients.
11026 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011027 if (cr.binding.client == app) {
11028 // Binding to ourself is not interesting.
11029 continue;
11030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11032 ProcessRecord client = cr.binding.client;
11033 int myHiddenAdj = hiddenAdj;
11034 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011035 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 myHiddenAdj = client.hiddenAdj;
11037 } else {
11038 myHiddenAdj = VISIBLE_APP_ADJ;
11039 }
11040 }
11041 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011042 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011043 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011044 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011045 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011046 if (!client.hidden) {
11047 app.hidden = false;
11048 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011049 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011050 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11051 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011052 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011053 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011055 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11056 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11057 schedGroup = Process.THREAD_GROUP_DEFAULT;
11058 }
11059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011061 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011063 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 //}
11065 if (a != null && adj > FOREGROUND_APP_ADJ &&
11066 (a.state == ActivityState.RESUMED
11067 || a.state == ActivityState.PAUSING)) {
11068 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011069 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011070 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011071 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011072 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11073 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011074 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011075 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 }
11077 }
11078 }
11079 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011080
11081 // Finally, f this process has active services running in it, we
11082 // would like to avoid killing it unless it would prevent the current
11083 // application from running. By default we put the process in
11084 // with the rest of the background processes; as we scan through
11085 // its services we may bump it up from there.
11086 if (adj > hiddenAdj) {
11087 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011088 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011089 app.adjType = "bg-services";
11090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 }
11092
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011093 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11094 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011095 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011096 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11097 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011098 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011099 if (cpr.clients.size() != 0) {
11100 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11101 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11102 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011103 if (client == app) {
11104 // Being our own client is not interesting.
11105 continue;
11106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 int myHiddenAdj = hiddenAdj;
11108 if (myHiddenAdj > client.hiddenAdj) {
11109 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11110 myHiddenAdj = client.hiddenAdj;
11111 } else {
11112 myHiddenAdj = FOREGROUND_APP_ADJ;
11113 }
11114 }
11115 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011116 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 if (adj > clientAdj) {
11118 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011119 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011120 if (!client.hidden) {
11121 app.hidden = false;
11122 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011123 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011124 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11125 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011126 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011127 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011129 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11130 schedGroup = Process.THREAD_GROUP_DEFAULT;
11131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132 }
11133 }
11134 // If the provider has external (non-framework) process
11135 // dependencies, ensure that its adjustment is at least
11136 // FOREGROUND_APP_ADJ.
11137 if (cpr.externals != 0) {
11138 if (adj > FOREGROUND_APP_ADJ) {
11139 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011140 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011141 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011142 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011143 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 }
11145 }
11146 }
11147 }
11148
11149 app.curRawAdj = adj;
11150
Joe Onorato8a9b2202010-02-26 18:56:32 -080011151 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11153 if (adj > app.maxAdj) {
11154 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011155 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011156 schedGroup = Process.THREAD_GROUP_DEFAULT;
11157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 }
11159
11160 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011161 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 return adj;
11164 }
11165
11166 /**
11167 * Ask a given process to GC right now.
11168 */
11169 final void performAppGcLocked(ProcessRecord app) {
11170 try {
11171 app.lastRequestedGc = SystemClock.uptimeMillis();
11172 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011173 if (app.reportLowMemory) {
11174 app.reportLowMemory = false;
11175 app.thread.scheduleLowMemory();
11176 } else {
11177 app.thread.processInBackground();
11178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 }
11180 } catch (Exception e) {
11181 // whatever.
11182 }
11183 }
11184
11185 /**
11186 * Returns true if things are idle enough to perform GCs.
11187 */
Josh Bartel7f208742010-02-25 11:01:44 -060011188 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 return mParallelBroadcasts.size() == 0
11190 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011191 && (mSleeping || (mMainStack.mResumedActivity != null &&
11192 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011193 }
11194
11195 /**
11196 * Perform GCs on all processes that are waiting for it, but only
11197 * if things are idle.
11198 */
11199 final void performAppGcsLocked() {
11200 final int N = mProcessesToGc.size();
11201 if (N <= 0) {
11202 return;
11203 }
Josh Bartel7f208742010-02-25 11:01:44 -060011204 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205 while (mProcessesToGc.size() > 0) {
11206 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011207 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011208 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11209 <= SystemClock.uptimeMillis()) {
11210 // To avoid spamming the system, we will GC processes one
11211 // at a time, waiting a few seconds between each.
11212 performAppGcLocked(proc);
11213 scheduleAppGcsLocked();
11214 return;
11215 } else {
11216 // It hasn't been long enough since we last GCed this
11217 // process... put it in the list to wait for its time.
11218 addProcessToGcListLocked(proc);
11219 break;
11220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 }
11222 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011223
11224 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011225 }
11226 }
11227
11228 /**
11229 * If all looks good, perform GCs on all processes waiting for them.
11230 */
11231 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011232 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 performAppGcsLocked();
11234 return;
11235 }
11236 // Still not idle, wait some more.
11237 scheduleAppGcsLocked();
11238 }
11239
11240 /**
11241 * Schedule the execution of all pending app GCs.
11242 */
11243 final void scheduleAppGcsLocked() {
11244 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011245
11246 if (mProcessesToGc.size() > 0) {
11247 // Schedule a GC for the time to the next process.
11248 ProcessRecord proc = mProcessesToGc.get(0);
11249 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11250
11251 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11252 long now = SystemClock.uptimeMillis();
11253 if (when < (now+GC_TIMEOUT)) {
11254 when = now + GC_TIMEOUT;
11255 }
11256 mHandler.sendMessageAtTime(msg, when);
11257 }
11258 }
11259
11260 /**
11261 * Add a process to the array of processes waiting to be GCed. Keeps the
11262 * list in sorted order by the last GC time. The process can't already be
11263 * on the list.
11264 */
11265 final void addProcessToGcListLocked(ProcessRecord proc) {
11266 boolean added = false;
11267 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11268 if (mProcessesToGc.get(i).lastRequestedGc <
11269 proc.lastRequestedGc) {
11270 added = true;
11271 mProcessesToGc.add(i+1, proc);
11272 break;
11273 }
11274 }
11275 if (!added) {
11276 mProcessesToGc.add(0, proc);
11277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 }
11279
11280 /**
11281 * Set up to ask a process to GC itself. This will either do it
11282 * immediately, or put it on the list of processes to gc the next
11283 * time things are idle.
11284 */
11285 final void scheduleAppGcLocked(ProcessRecord app) {
11286 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011287 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 return;
11289 }
11290 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011291 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 scheduleAppGcsLocked();
11293 }
11294 }
11295
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011296 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11297 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11298 if (mLastWakeLockCheckTime == 0) {
11299 doKills = false;
11300 }
11301 if (stats.isScreenOn()) {
11302 doKills = false;
11303 }
11304 final long curRealtime = SystemClock.elapsedRealtime();
11305 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11306 mLastWakeLockCheckTime = curRealtime;
11307 if (timeSince < 5*60*1000) {
11308 doKills = false;
11309 }
11310 int i = mLruProcesses.size();
11311 while (i > 0) {
11312 i--;
11313 ProcessRecord app = mLruProcesses.get(i);
11314 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11315 long wtime;
11316 synchronized (stats) {
11317 wtime = stats.getProcessWakeTime(app.info.uid,
11318 app.pid, curRealtime);
11319 }
11320 long timeUsed = wtime - app.lastWakeTime;
11321 Slog.i(TAG, "Wake for " + app + ": over "
11322 + timeSince + " used " + timeUsed
11323 + " (" + ((timeUsed*100)/timeSince) + "%)");
11324 // If a process has held a wake lock for more
11325 // than 50% of the time during this period,
11326 // that sounds pad. Kill!
11327 if (doKills && timeSince > 0
11328 && ((timeUsed*100)/timeSince) >= 50) {
11329 Slog.i(TAG, "Excessive wake lock in " + app.processName
11330 + " (pid " + app.pid + "): held " + timeUsed
11331 + " during " + timeSince);
11332 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11333 app.processName, app.setAdj, "excessive wake lock");
11334 Process.killProcessQuiet(app.pid);
11335 } else {
11336 app.lastWakeTime = wtime;
11337 }
11338 }
11339 }
11340 }
11341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011342 private final boolean updateOomAdjLocked(
11343 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11344 app.hiddenAdj = hiddenAdj;
11345
11346 if (app.thread == null) {
11347 return true;
11348 }
11349
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011350 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011352 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 if (app.curRawAdj != app.setRawAdj) {
11354 if (app.curRawAdj > FOREGROUND_APP_ADJ
11355 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11356 // If this app is transitioning from foreground to
11357 // non-foreground, have it do a gc.
11358 scheduleAppGcLocked(app);
11359 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11360 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11361 // Likewise do a gc when an app is moving in to the
11362 // background (such as a service stopping).
11363 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011364 // And note its current wake lock time.
11365 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11366 synchronized (stats) {
11367 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11368 app.pid, SystemClock.elapsedRealtime());
11369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 }
11371 app.setRawAdj = app.curRawAdj;
11372 }
11373 if (adj != app.setAdj) {
11374 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011375 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 TAG, "Set app " + app.processName +
11377 " oom adj to " + adj);
11378 app.setAdj = adj;
11379 } else {
11380 return false;
11381 }
11382 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011383 if (app.setSchedGroup != app.curSchedGroup) {
11384 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011385 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011386 "Setting process group of " + app.processName
11387 + " to " + app.curSchedGroup);
11388 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011389 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011390 try {
11391 Process.setProcessGroup(app.pid, app.curSchedGroup);
11392 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011393 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011394 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011395 e.printStackTrace();
11396 } finally {
11397 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011398 }
11399 }
11400 if (false) {
11401 if (app.thread != null) {
11402 try {
11403 app.thread.setSchedulingGroup(app.curSchedGroup);
11404 } catch (RemoteException e) {
11405 }
11406 }
11407 }
11408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 }
11410
11411 return true;
11412 }
11413
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011414 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011415 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011417 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011419 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 }
11421 }
11422 return resumedActivity;
11423 }
11424
11425 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011426 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11428 int curAdj = app.curAdj;
11429 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11430 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11431
11432 mAdjSeq++;
11433
11434 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11435 if (res) {
11436 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11437 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11438 if (nowHidden != wasHidden) {
11439 // Changed to/from hidden state, so apps after it in the LRU
11440 // list may also be changed.
11441 updateOomAdjLocked();
11442 }
11443 }
11444 return res;
11445 }
11446
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011447 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011448 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011449 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011450 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11451
11452 if (false) {
11453 RuntimeException e = new RuntimeException();
11454 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011455 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 }
11457
11458 mAdjSeq++;
11459
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011460 // Let's determine how many processes we have running vs.
11461 // how many slots we have for background processes; we may want
11462 // to put multiple processes in a slot of there are enough of
11463 // them.
11464 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11465 int factor = (mLruProcesses.size()-4)/numSlots;
11466 if (factor < 1) factor = 1;
11467 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011468 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 // First try updating the OOM adjustment for each of the
11471 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011472 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011473 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11474 while (i > 0) {
11475 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011476 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011477 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011479 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011481 step++;
11482 if (step >= factor) {
11483 step = 0;
11484 curHiddenAdj++;
11485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011487 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011488 if (!app.killedBackground) {
11489 numHidden++;
11490 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011491 Slog.i(TAG, "No longer want " + app.processName
11492 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011493 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11494 app.processName, app.setAdj, "too many background");
11495 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011496 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011497 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011498 }
11499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 } else {
11501 didOomAdj = false;
11502 }
11503 }
11504
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011505 // If we return false, we will fall back on killing processes to
11506 // have a fixed limit. Do this if a limit has been requested; else
11507 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11509 }
11510
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011511 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 synchronized (this) {
11513 int i;
11514
11515 // First remove any unused application processes whose package
11516 // has been removed.
11517 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11518 final ProcessRecord app = mRemovedProcesses.get(i);
11519 if (app.activities.size() == 0
11520 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011521 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 TAG, "Exiting empty application process "
11523 + app.processName + " ("
11524 + (app.thread != null ? app.thread.asBinder() : null)
11525 + ")\n");
11526 if (app.pid > 0 && app.pid != MY_PID) {
11527 Process.killProcess(app.pid);
11528 } else {
11529 try {
11530 app.thread.scheduleExit();
11531 } catch (Exception e) {
11532 // Ignore exceptions.
11533 }
11534 }
11535 cleanUpApplicationRecordLocked(app, false, -1);
11536 mRemovedProcesses.remove(i);
11537
11538 if (app.persistent) {
11539 if (app.persistent) {
11540 addAppLocked(app.info);
11541 }
11542 }
11543 }
11544 }
11545
11546 // Now try updating the OOM adjustment for each of the
11547 // application processes based on their current state.
11548 // If the setOomAdj() API is not supported, then go with our
11549 // back-up plan...
11550 if (!updateOomAdjLocked()) {
11551
11552 // Count how many processes are running services.
11553 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011554 for (i=mLruProcesses.size()-1; i>=0; i--) {
11555 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556
11557 if (app.persistent || app.services.size() != 0
11558 || app.curReceiver != null
11559 || app.persistentActivities > 0) {
11560 // Don't count processes holding services against our
11561 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 TAG, "Not trimming app " + app + " with services: "
11564 + app.services);
11565 numServiceProcs++;
11566 }
11567 }
11568
11569 int curMaxProcs = mProcessLimit;
11570 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11571 if (mAlwaysFinishActivities) {
11572 curMaxProcs = 1;
11573 }
11574 curMaxProcs += numServiceProcs;
11575
11576 // Quit as many processes as we can to get down to the desired
11577 // process count. First remove any processes that no longer
11578 // have activites running in them.
11579 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011580 i<mLruProcesses.size()
11581 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011583 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 // Quit an application only if it is not currently
11585 // running any activities.
11586 if (!app.persistent && app.activities.size() == 0
11587 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011588 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 TAG, "Exiting empty application process "
11590 + app.processName + " ("
11591 + (app.thread != null ? app.thread.asBinder() : null)
11592 + ")\n");
11593 if (app.pid > 0 && app.pid != MY_PID) {
11594 Process.killProcess(app.pid);
11595 } else {
11596 try {
11597 app.thread.scheduleExit();
11598 } catch (Exception e) {
11599 // Ignore exceptions.
11600 }
11601 }
11602 // todo: For now we assume the application is not buggy
11603 // or evil, and will quit as a result of our request.
11604 // Eventually we need to drive this off of the death
11605 // notification, and kill the process if it takes too long.
11606 cleanUpApplicationRecordLocked(app, false, i);
11607 i--;
11608 }
11609 }
11610
11611 // If we still have too many processes, now from the least
11612 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011613 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011614 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011615 " of " + curMaxProcs + " processes");
11616 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011617 i<mLruProcesses.size()
11618 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011619 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011620 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 // Quit the application only if we have a state saved for
11622 // all of its activities.
11623 boolean canQuit = !app.persistent && app.curReceiver == null
11624 && app.services.size() == 0
11625 && app.persistentActivities == 0;
11626 int NUMA = app.activities.size();
11627 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011628 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 TAG, "Looking to quit " + app.processName);
11630 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011631 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011632 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 TAG, " " + r.intent.getComponent().flattenToShortString()
11634 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11635 canQuit = (r.haveState || !r.stateNotNeeded)
11636 && !r.visible && r.stopped;
11637 }
11638 if (canQuit) {
11639 // Finish all of the activities, and then the app itself.
11640 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011641 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011643 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 }
11645 r.resultTo = null;
11646 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011647 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 + app.processName + " ("
11649 + (app.thread != null ? app.thread.asBinder() : null)
11650 + ")\n");
11651 if (app.pid > 0 && app.pid != MY_PID) {
11652 Process.killProcess(app.pid);
11653 } else {
11654 try {
11655 app.thread.scheduleExit();
11656 } catch (Exception e) {
11657 // Ignore exceptions.
11658 }
11659 }
11660 // todo: For now we assume the application is not buggy
11661 // or evil, and will quit as a result of our request.
11662 // Eventually we need to drive this off of the death
11663 // notification, and kill the process if it takes too long.
11664 cleanUpApplicationRecordLocked(app, false, i);
11665 i--;
11666 //dump();
11667 }
11668 }
11669
11670 }
11671
11672 int curMaxActivities = MAX_ACTIVITIES;
11673 if (mAlwaysFinishActivities) {
11674 curMaxActivities = 1;
11675 }
11676
11677 // Finally, if there are too many activities now running, try to
11678 // finish as many as we can to get back down to the limit.
11679 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011680 i<mMainStack.mLRUActivities.size()
11681 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011683 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011684 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011685
11686 // We can finish this one if we have its icicle saved and
11687 // it is not persistent.
11688 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11689 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011690 final int origSize = mMainStack.mLRUActivities.size();
11691 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692
11693 // This will remove it from the LRU list, so keep
11694 // our index at the same value. Note that this check to
11695 // see if the size changes is just paranoia -- if
11696 // something unexpected happens, we don't want to end up
11697 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011698 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 i--;
11700 }
11701 }
11702 }
11703 }
11704 }
11705
11706 /** This method sends the specified signal to each of the persistent apps */
11707 public void signalPersistentProcesses(int sig) throws RemoteException {
11708 if (sig != Process.SIGNAL_USR1) {
11709 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11710 }
11711
11712 synchronized (this) {
11713 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11714 != PackageManager.PERMISSION_GRANTED) {
11715 throw new SecurityException("Requires permission "
11716 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11717 }
11718
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011719 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11720 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 if (r.thread != null && r.persistent) {
11722 Process.sendSignal(r.pid, sig);
11723 }
11724 }
11725 }
11726 }
11727
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011728 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011729 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011730
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011731 try {
11732 synchronized (this) {
11733 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11734 // its own permission.
11735 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11736 != PackageManager.PERMISSION_GRANTED) {
11737 throw new SecurityException("Requires permission "
11738 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011739 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011740
11741 if (start && fd == null) {
11742 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011743 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011744
11745 ProcessRecord proc = null;
11746 try {
11747 int pid = Integer.parseInt(process);
11748 synchronized (mPidsSelfLocked) {
11749 proc = mPidsSelfLocked.get(pid);
11750 }
11751 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011752 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011753
11754 if (proc == null) {
11755 HashMap<String, SparseArray<ProcessRecord>> all
11756 = mProcessNames.getMap();
11757 SparseArray<ProcessRecord> procs = all.get(process);
11758 if (procs != null && procs.size() > 0) {
11759 proc = procs.valueAt(0);
11760 }
11761 }
11762
11763 if (proc == null || proc.thread == null) {
11764 throw new IllegalArgumentException("Unknown process: " + process);
11765 }
11766
11767 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11768 if (isSecure) {
11769 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11770 throw new SecurityException("Process not debuggable: " + proc);
11771 }
11772 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011773
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011774 proc.thread.profilerControl(start, path, fd);
11775 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011776 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011777 }
11778 } catch (RemoteException e) {
11779 throw new IllegalStateException("Process disappeared");
11780 } finally {
11781 if (fd != null) {
11782 try {
11783 fd.close();
11784 } catch (IOException e) {
11785 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011786 }
11787 }
11788 }
11789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11791 public void monitor() {
11792 synchronized (this) { }
11793 }
11794}