blob: dff6a8a9a79376a5301c01ef590d4a95f498c8c2 [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // How long we allow a receiver to run before giving up on it.
203 static final int BROADCAST_TIMEOUT = 10*1000;
204
205 // How long we wait for a service to finish executing.
206 static final int SERVICE_TIMEOUT = 20*1000;
207
208 // How long a service needs to be running until restarting its process
209 // is no longer considered to be a relaunch of the service.
210 static final int SERVICE_RESTART_DURATION = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // How long a service needs to be running until it will start back at
213 // SERVICE_RESTART_DURATION after being killed.
214 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
215
216 // Multiplying factor to increase restart duration time by, for each time
217 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
218 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
219
220 // The minimum amount of time between restarting services that we allow.
221 // That is, when multiple services are restarting, we won't allow each
222 // to restart less than this amount of time from the last one.
223 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Maximum amount of time for there to be no activity on a service before
226 // we consider it non-essential and allow its process to go on the
227 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700228 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 // How long we wait until we timeout on key dispatching.
231 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
232
233 // The minimum time we allow between crashes, for us to consider this
234 // application to be bad and stop and its services and reject broadcasts.
235 static final int MIN_CRASH_INTERVAL = 60*1000;
236
237 // How long we wait until we timeout on key dispatching during instrumentation.
238 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
239
240 // OOM adjustments for processes in various states:
241
242 // This is a process without anything currently running in it. Definitely
243 // the first to go! Value set in system/rootdir/init.rc on startup.
244 // This value is initalized in the constructor, careful when refering to
245 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800246 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // This is a process only hosting activities that are not visible,
249 // so it can be killed without any disruption. Value set in
250 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800251 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 static int HIDDEN_APP_MIN_ADJ;
253
The Android Open Source Project4df24232009-03-05 14:34:35 -0800254 // This is a process holding the home application -- we want to try
255 // avoiding killing it, even if it would normally be in the background,
256 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800257 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800258
Christopher Tate6fa95972009-06-05 18:43:55 -0700259 // This is a process currently hosting a backup operation. Killing it
260 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800261 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 // This is a process holding a secondary server -- killing it will not
264 // have much of an impact as far as the user is concerned. Value set in
265 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700268 // This is a process with a heavy-weight application. It is in the
269 // background, but we want to try to avoid killing it. Value set in
270 // system/rootdir/init.rc on startup.
271 static final int HEAVY_WEIGHT_APP_ADJ;
272
273 // This is a process only hosting components that are perceptible to the
274 // user, and we really want to avoid killing them, but they are not
275 // immediately visible. An example is background music playback. Value set in
276 // system/rootdir/init.rc on startup.
277 static final int PERCEPTIBLE_APP_ADJ;
278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 // This is a process only hosting activities that are visible to the
280 // user, so we'd prefer they don't disappear. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is the process running the current foreground app. We'd really
285 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is a process running a core server, such as telephony. Definitely
289 // don't want to kill it, but doing so is not completely fatal.
290 static final int CORE_SERVER_ADJ = -12;
291
292 // The system process runs at the default adjustment.
293 static final int SYSTEM_ADJ = -16;
294
295 // Memory pages are 4K.
296 static final int PAGE_SIZE = 4*1024;
297
298 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800299 static final int EMPTY_APP_MEM;
300 static final int HIDDEN_APP_MEM;
301 static final int HOME_APP_MEM;
302 static final int BACKUP_APP_MEM;
303 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700304 static final int HEAVY_WEIGHT_APP_MEM;
305 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_MEM;
307 static final int FOREGROUND_APP_MEM;
308
309 // The minimum number of hidden apps we want to be able to keep around,
310 // without empty apps being able to push them out of memory.
311 static final int MIN_HIDDEN_APPS = 2;
312
Dianne Hackborn8633e682010-04-22 16:03:41 -0700313 // The maximum number of hidden processes we will keep around before
314 // killing them; this is just a control to not let us go too crazy with
315 // keeping around processes on devices with large amounts of RAM.
316 static final int MAX_HIDDEN_APPS = 15;
317
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800318 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700319 // been idle for less than 15 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800321
322 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700323 // been idle for less than 120 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700326 static int getIntProp(String name, boolean allowZero) {
327 String str = SystemProperties.get(name);
328 if (str == null) {
329 throw new IllegalArgumentException("Property not defined: " + name);
330 }
331 int val = Integer.valueOf(str);
332 if (val == 0 && !allowZero) {
333 throw new IllegalArgumentException("Property must not be zero: " + name);
334 }
335 return val;
336 }
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 static {
339 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700340 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
341 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
342 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
343 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
344 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
345 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
346 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
347 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
348 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
349 // These days we use the last empty slot for hidden apps as well.
350 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
351 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
352 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
353 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
354 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
355 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
356 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
357 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
358 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
359 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Dan Egnor42471dd2010-01-07 17:25:22 -0800362 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
364 static final String[] EMPTY_STRING_ARRAY = new String[0];
365
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700366 public ActivityStack mMainStack;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700369 * Description of a request to start a new activity, which has been held
370 * due to app switches being disabled.
371 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700372 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700373 ActivityRecord r;
374 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700375 Uri[] grantedUriPermissions;
376 int grantedMode;
377 boolean onlyIfNeeded;
378 }
379
380 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
381 = new ArrayList<PendingActivityLaunch>();
382
383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 * List of all active broadcasts that are to be executed immediately
385 * (without waiting for another broadcast to finish). Currently this only
386 * contains broadcasts to registered receivers, to avoid spinning up
387 * a bunch of processes to execute IntentReceiver components.
388 */
389 final ArrayList<BroadcastRecord> mParallelBroadcasts
390 = new ArrayList<BroadcastRecord>();
391
392 /**
393 * List of all active broadcasts that are to be executed one at a time.
394 * The object at the top of the list is the currently activity broadcasts;
395 * those after it are waiting for the top to finish..
396 */
397 final ArrayList<BroadcastRecord> mOrderedBroadcasts
398 = new ArrayList<BroadcastRecord>();
399
400 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800401 * Historical data of past broadcasts, for debugging.
402 */
403 static final int MAX_BROADCAST_HISTORY = 100;
404 final BroadcastRecord[] mBroadcastHistory
405 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * Set when we current have a BROADCAST_INTENT_MSG in flight.
409 */
410 boolean mBroadcastsScheduled = false;
411
412 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 * Activity we have told the window manager to have key focus.
414 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700415 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 * List of intents that were used to start the most recent tasks.
418 */
419 final ArrayList<TaskRecord> mRecentTasks
420 = new ArrayList<TaskRecord>();
421
422 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 * All of the applications we currently have running organized by name.
424 * The keys are strings of the application package name (as
425 * returned by the package manager), and the keys are ApplicationRecord
426 * objects.
427 */
428 final ProcessMap<ProcessRecord> mProcessNames
429 = new ProcessMap<ProcessRecord>();
430
431 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700432 * The currently running heavy-weight process, if any.
433 */
434 ProcessRecord mHeavyWeightProcess = null;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * The last time that various processes have crashed.
438 */
439 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
440
441 /**
442 * Set of applications that we consider to be bad, and will reject
443 * incoming broadcasts from (which the user has no control over).
444 * Processes are added to this set when they have crashed twice within
445 * a minimum amount of time; they are removed from it when they are
446 * later restarted (hopefully due to some user action). The value is the
447 * time it was added to the list.
448 */
449 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
450
451 /**
452 * All of the processes we currently have running organized by pid.
453 * The keys are the pid running the application.
454 *
455 * <p>NOTE: This object is protected by its own lock, NOT the global
456 * activity manager lock!
457 */
458 final SparseArray<ProcessRecord> mPidsSelfLocked
459 = new SparseArray<ProcessRecord>();
460
461 /**
462 * All of the processes that have been forced to be foreground. The key
463 * is the pid of the caller who requested it (we hold a death
464 * link on it).
465 */
466 abstract class ForegroundToken implements IBinder.DeathRecipient {
467 int pid;
468 IBinder token;
469 }
470 final SparseArray<ForegroundToken> mForegroundProcesses
471 = new SparseArray<ForegroundToken>();
472
473 /**
474 * List of records for processes that someone had tried to start before the
475 * system was ready. We don't start them at that point, but ensure they
476 * are started by the time booting is complete.
477 */
478 final ArrayList<ProcessRecord> mProcessesOnHold
479 = new ArrayList<ProcessRecord>();
480
481 /**
482 * List of records for processes that we have started and are waiting
483 * for them to call back. This is really only needed when running in
484 * single processes mode, in which case we do not have a unique pid for
485 * each process.
486 */
487 final ArrayList<ProcessRecord> mStartingProcesses
488 = new ArrayList<ProcessRecord>();
489
490 /**
491 * List of persistent applications that are in the process
492 * of being started.
493 */
494 final ArrayList<ProcessRecord> mPersistentStartingProcesses
495 = new ArrayList<ProcessRecord>();
496
497 /**
498 * Processes that are being forcibly torn down.
499 */
500 final ArrayList<ProcessRecord> mRemovedProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * List of running applications, sorted by recent usage.
505 * The first entry in the list is the least recently used.
506 * It contains ApplicationRecord objects. This list does NOT include
507 * any persistent application records (since we never want to exit them).
508 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800509 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 = new ArrayList<ProcessRecord>();
511
512 /**
513 * List of processes that should gc as soon as things are idle.
514 */
515 final ArrayList<ProcessRecord> mProcessesToGc
516 = new ArrayList<ProcessRecord>();
517
518 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800519 * This is the process holding what we currently consider to be
520 * the "home" activity.
521 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700522 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800523
524 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 * Set of PendingResultRecord objects that are currently active.
526 */
527 final HashSet mPendingResultRecords = new HashSet();
528
529 /**
530 * Set of IntentSenderRecord objects that are currently active.
531 */
532 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
533 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
534
535 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700536 * Fingerprints (String.hashCode()) of stack traces that we've
537 * already logged DropBox entries for. Guarded by itself. If
538 * something (rogue user app) forces this over
539 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
540 */
541 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
542 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
543
544 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700545 * Strict Mode background batched logging state.
546 *
547 * The string buffer is guarded by itself, and its lock is also
548 * used to determine if another batched write is already
549 * in-flight.
550 */
551 private final StringBuilder mStrictModeBuffer = new StringBuilder();
552
553 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 * Intent broadcast that we have tried to start, but are
555 * waiting for its application's process to be created. We only
556 * need one (instead of a list) because we always process broadcasts
557 * one at a time, so no others can be started while waiting for this
558 * one.
559 */
560 BroadcastRecord mPendingBroadcast = null;
561
562 /**
563 * Keeps track of all IIntentReceivers that have been registered for
564 * broadcasts. Hash keys are the receiver IBinder, hash value is
565 * a ReceiverList.
566 */
567 final HashMap mRegisteredReceivers = new HashMap();
568
569 /**
570 * Resolver for broadcast intents to registered receivers.
571 * Holds BroadcastFilter (subclass of IntentFilter).
572 */
573 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
574 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
575 @Override
576 protected boolean allowFilterResult(
577 BroadcastFilter filter, List<BroadcastFilter> dest) {
578 IBinder target = filter.receiverList.receiver.asBinder();
579 for (int i=dest.size()-1; i>=0; i--) {
580 if (dest.get(i).receiverList.receiver.asBinder() == target) {
581 return false;
582 }
583 }
584 return true;
585 }
586 };
587
588 /**
589 * State of all active sticky broadcasts. Keys are the action of the
590 * sticky Intent, values are an ArrayList of all broadcasted intents with
591 * that action (which should usually be one).
592 */
593 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
594 new HashMap<String, ArrayList<Intent>>();
595
596 /**
597 * All currently running services.
598 */
599 final HashMap<ComponentName, ServiceRecord> mServices =
600 new HashMap<ComponentName, ServiceRecord>();
601
602 /**
603 * All currently running services indexed by the Intent used to start them.
604 */
605 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
606 new HashMap<Intent.FilterComparison, ServiceRecord>();
607
608 /**
609 * All currently bound service connections. Keys are the IBinder of
610 * the client's IServiceConnection.
611 */
612 final HashMap<IBinder, ConnectionRecord> mServiceConnections
613 = new HashMap<IBinder, ConnectionRecord>();
614
615 /**
616 * List of services that we have been asked to start,
617 * but haven't yet been able to. It is used to hold start requests
618 * while waiting for their corresponding application thread to get
619 * going.
620 */
621 final ArrayList<ServiceRecord> mPendingServices
622 = new ArrayList<ServiceRecord>();
623
624 /**
625 * List of services that are scheduled to restart following a crash.
626 */
627 final ArrayList<ServiceRecord> mRestartingServices
628 = new ArrayList<ServiceRecord>();
629
630 /**
631 * List of services that are in the process of being stopped.
632 */
633 final ArrayList<ServiceRecord> mStoppingServices
634 = new ArrayList<ServiceRecord>();
635
636 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700637 * Backup/restore process management
638 */
639 String mBackupAppName = null;
640 BackupRecord mBackupTarget = null;
641
642 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 * List of PendingThumbnailsRecord objects of clients who are still
644 * waiting to receive all of the thumbnails for a task.
645 */
646 final ArrayList mPendingThumbnails = new ArrayList();
647
648 /**
649 * List of HistoryRecord objects that have been finished and must
650 * still report back to a pending thumbnail receiver.
651 */
652 final ArrayList mCancelledThumbnails = new ArrayList();
653
654 /**
655 * All of the currently running global content providers. Keys are a
656 * string containing the provider name and values are a
657 * ContentProviderRecord object containing the data about it. Note
658 * that a single provider may be published under multiple names, so
659 * there may be multiple entries here for a single one in mProvidersByClass.
660 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700661 final HashMap<String, ContentProviderRecord> mProvidersByName
662 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663
664 /**
665 * All of the currently running global content providers. Keys are a
666 * string containing the provider's implementation class and values are a
667 * ContentProviderRecord object containing the data about it.
668 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700669 final HashMap<String, ContentProviderRecord> mProvidersByClass
670 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 /**
673 * List of content providers who have clients waiting for them. The
674 * application is currently being launched and the provider will be
675 * removed from this list once it is published.
676 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700677 final ArrayList<ContentProviderRecord> mLaunchingProviders
678 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 /**
681 * Global set of specific Uri permissions that have been granted.
682 */
683 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
684 = new SparseArray<HashMap<Uri, UriPermission>>();
685
686 /**
687 * Thread-local storage used to carry caller permissions over through
688 * indirect content-provider access.
689 * @see #ActivityManagerService.openContentUri()
690 */
691 private class Identity {
692 public int pid;
693 public int uid;
694
695 Identity(int _pid, int _uid) {
696 pid = _pid;
697 uid = _uid;
698 }
699 }
700 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
701
702 /**
703 * All information we have collected about the runtime performance of
704 * any user id that can impact battery performance.
705 */
706 final BatteryStatsService mBatteryStatsService;
707
708 /**
709 * information about component usage
710 */
711 final UsageStatsService mUsageStatsService;
712
713 /**
714 * Current configuration information. HistoryRecord objects are given
715 * a reference to this object to indicate which configuration they are
716 * currently running in, so this object must be kept immutable.
717 */
718 Configuration mConfiguration = new Configuration();
719
720 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800721 * Current sequencing integer of the configuration, for skipping old
722 * configurations.
723 */
724 int mConfigurationSeq = 0;
725
726 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700727 * Hardware-reported OpenGLES version.
728 */
729 final int GL_ES_VERSION;
730
731 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 * List of initialization arguments to pass to all processes when binding applications to them.
733 * For example, references to the commonly used services.
734 */
735 HashMap<String, IBinder> mAppBindArgs;
736
737 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700738 * Temporary to avoid allocations. Protected by main lock.
739 */
740 final StringBuilder mStringBuilder = new StringBuilder(256);
741
742 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 * Used to control how we initialize the service.
744 */
745 boolean mStartRunning = false;
746 ComponentName mTopComponent;
747 String mTopAction;
748 String mTopData;
749 boolean mSystemReady = false;
750 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700751 boolean mWaitingUpdate = false;
752 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753
754 Context mContext;
755
756 int mFactoryTest;
757
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700758 boolean mCheckedForSetup;
759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700761 * The time at which we will allow normal application switches again,
762 * after a call to {@link #stopAppSwitches()}.
763 */
764 long mAppSwitchesAllowedTime;
765
766 /**
767 * This is set to true after the first switch after mAppSwitchesAllowedTime
768 * is set; any switches after that will clear the time.
769 */
770 boolean mDidAppSwitch;
771
772 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 * Set while we are wanting to sleep, to prevent any
774 * activities from being started/resumed.
775 */
776 boolean mSleeping = false;
777
778 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700779 * Set if we are shutting down the system, similar to sleeping.
780 */
781 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782
783 /**
784 * Task identifier that activities are currently being started
785 * in. Incremented each time a new task is created.
786 * todo: Replace this with a TokenSpace class that generates non-repeating
787 * integers that won't wrap.
788 */
789 int mCurTask = 1;
790
791 /**
792 * Current sequence id for oom_adj computation traversal.
793 */
794 int mAdjSeq = 0;
795
796 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700797 * Current sequence id for process LRU updating.
798 */
799 int mLruSeq = 0;
800
801 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
803 * is set, indicating the user wants processes started in such a way
804 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
805 * running in each process (thus no pre-initialized process, etc).
806 */
807 boolean mSimpleProcessManagement = false;
808
809 /**
810 * System monitoring: number of processes that died since the last
811 * N procs were started.
812 */
813 int[] mProcDeaths = new int[20];
814
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700815 /**
816 * This is set if we had to do a delayed dexopt of an app before launching
817 * it, to increasing the ANR timeouts in that case.
818 */
819 boolean mDidDexOpt;
820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 String mDebugApp = null;
822 boolean mWaitForDebugger = false;
823 boolean mDebugTransient = false;
824 String mOrigDebugApp = null;
825 boolean mOrigWaitForDebugger = false;
826 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700827 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700829 final RemoteCallbackList<IActivityWatcher> mWatchers
830 = new RemoteCallbackList<IActivityWatcher>();
831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 /**
833 * Callback of last caller to {@link #requestPss}.
834 */
835 Runnable mRequestPssCallback;
836
837 /**
838 * Remaining processes for which we are waiting results from the last
839 * call to {@link #requestPss}.
840 */
841 final ArrayList<ProcessRecord> mRequestPssList
842 = new ArrayList<ProcessRecord>();
843
844 /**
845 * Runtime statistics collection thread. This object's lock is used to
846 * protect all related state.
847 */
848 final Thread mProcessStatsThread;
849
850 /**
851 * Used to collect process stats when showing not responding dialog.
852 * Protected by mProcessStatsThread.
853 */
854 final ProcessStats mProcessStats = new ProcessStats(
855 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700856 final AtomicLong mLastCpuTime = new AtomicLong(0);
857 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 long mLastWriteTime = 0;
860
861 /**
862 * Set to true after the system has finished booting.
863 */
864 boolean mBooted = false;
865
866 int mProcessLimit = 0;
867
868 WindowManagerService mWindowManager;
869
870 static ActivityManagerService mSelf;
871 static ActivityThread mSystemThread;
872
873 private final class AppDeathRecipient implements IBinder.DeathRecipient {
874 final ProcessRecord mApp;
875 final int mPid;
876 final IApplicationThread mAppThread;
877
878 AppDeathRecipient(ProcessRecord app, int pid,
879 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800880 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 TAG, "New death recipient " + this
882 + " for thread " + thread.asBinder());
883 mApp = app;
884 mPid = pid;
885 mAppThread = thread;
886 }
887
888 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800889 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 TAG, "Death received in " + this
891 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 synchronized(ActivityManagerService.this) {
893 appDiedLocked(mApp, mPid, mAppThread);
894 }
895 }
896 }
897
898 static final int SHOW_ERROR_MSG = 1;
899 static final int SHOW_NOT_RESPONDING_MSG = 2;
900 static final int SHOW_FACTORY_ERROR_MSG = 3;
901 static final int UPDATE_CONFIGURATION_MSG = 4;
902 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
903 static final int WAIT_FOR_DEBUGGER_MSG = 6;
904 static final int BROADCAST_INTENT_MSG = 7;
905 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 static final int SERVICE_TIMEOUT_MSG = 12;
907 static final int UPDATE_TIME_ZONE = 13;
908 static final int SHOW_UID_ERROR_MSG = 14;
909 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700911 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700912 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800913 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700914 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
915 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700916 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917
918 AlertDialog mUidAlert;
919
920 final Handler mHandler = new Handler() {
921 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800922 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 //}
924
925 public void handleMessage(Message msg) {
926 switch (msg.what) {
927 case SHOW_ERROR_MSG: {
928 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 synchronized (ActivityManagerService.this) {
930 ProcessRecord proc = (ProcessRecord)data.get("app");
931 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800932 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 return;
934 }
935 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700936 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800937 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 d.show();
939 proc.crashDialog = d;
940 } else {
941 // The device is asleep, so just pretend that the user
942 // saw a crash dialog and hit "force quit".
943 res.set(0);
944 }
945 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700946
947 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 } break;
949 case SHOW_NOT_RESPONDING_MSG: {
950 synchronized (ActivityManagerService.this) {
951 HashMap data = (HashMap) msg.obj;
952 ProcessRecord proc = (ProcessRecord)data.get("app");
953 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800954 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 return;
956 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800957
958 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
959 null, null, 0, null, null, null,
960 false, false, MY_PID, Process.SYSTEM_UID);
961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700963 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 d.show();
965 proc.anrDialog = d;
966 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700967
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700968 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700970 case SHOW_STRICT_MODE_VIOLATION_MSG: {
971 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
972 synchronized (ActivityManagerService.this) {
973 ProcessRecord proc = (ProcessRecord) data.get("app");
974 if (proc == null) {
975 Slog.e(TAG, "App not found when showing strict mode dialog.");
976 break;
977 }
978 if (proc.crashDialog != null) {
979 Slog.e(TAG, "App already has strict mode dialog: " + proc);
980 return;
981 }
982 AppErrorResult res = (AppErrorResult) data.get("result");
983 if (!mSleeping && !mShuttingDown) {
984 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
985 d.show();
986 proc.crashDialog = d;
987 } else {
988 // The device is asleep, so just pretend that the user
989 // saw a crash dialog and hit "force quit".
990 res.set(0);
991 }
992 }
993 ensureBootCompleted();
994 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 case SHOW_FACTORY_ERROR_MSG: {
996 Dialog d = new FactoryErrorDialog(
997 mContext, msg.getData().getCharSequence("msg"));
998 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700999 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 } break;
1001 case UPDATE_CONFIGURATION_MSG: {
1002 final ContentResolver resolver = mContext.getContentResolver();
1003 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1004 } break;
1005 case GC_BACKGROUND_PROCESSES_MSG: {
1006 synchronized (ActivityManagerService.this) {
1007 performAppGcsIfAppropriateLocked();
1008 }
1009 } break;
1010 case WAIT_FOR_DEBUGGER_MSG: {
1011 synchronized (ActivityManagerService.this) {
1012 ProcessRecord app = (ProcessRecord)msg.obj;
1013 if (msg.arg1 != 0) {
1014 if (!app.waitedForDebugger) {
1015 Dialog d = new AppWaitingForDebuggerDialog(
1016 ActivityManagerService.this,
1017 mContext, app);
1018 app.waitDialog = d;
1019 app.waitedForDebugger = true;
1020 d.show();
1021 }
1022 } else {
1023 if (app.waitDialog != null) {
1024 app.waitDialog.dismiss();
1025 app.waitDialog = null;
1026 }
1027 }
1028 }
1029 } break;
1030 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001031 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 TAG, "Received BROADCAST_INTENT_MSG");
1033 processNextBroadcast(true);
1034 } break;
1035 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001036 if (mDidDexOpt) {
1037 mDidDexOpt = false;
1038 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1039 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1040 return;
1041 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001042 // Only process broadcast timeouts if the system is ready. That way
1043 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1044 // to do heavy lifting for system up
1045 if (mSystemReady) {
1046 broadcastTimeout();
1047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001050 if (mDidDexOpt) {
1051 mDidDexOpt = false;
1052 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1053 nmsg.obj = msg.obj;
1054 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1055 return;
1056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 serviceTimeout((ProcessRecord)msg.obj);
1058 } break;
1059 case UPDATE_TIME_ZONE: {
1060 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001061 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1062 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 if (r.thread != null) {
1064 try {
1065 r.thread.updateTimeZone();
1066 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001067 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 }
1069 }
1070 }
1071 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001072 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 case SHOW_UID_ERROR_MSG: {
1074 // XXX This is a temporary dialog, no need to localize.
1075 AlertDialog d = new BaseErrorDialog(mContext);
1076 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1077 d.setCancelable(false);
1078 d.setTitle("System UIDs Inconsistent");
1079 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1080 d.setButton("I'm Feeling Lucky",
1081 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1082 mUidAlert = d;
1083 d.show();
1084 } break;
1085 case IM_FEELING_LUCKY_MSG: {
1086 if (mUidAlert != null) {
1087 mUidAlert.dismiss();
1088 mUidAlert = null;
1089 }
1090 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001092 if (mDidDexOpt) {
1093 mDidDexOpt = false;
1094 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1095 nmsg.obj = msg.obj;
1096 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1097 return;
1098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 ProcessRecord app = (ProcessRecord)msg.obj;
1100 synchronized (ActivityManagerService.this) {
1101 processStartTimedOutLocked(app);
1102 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001103 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001104 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1105 synchronized (ActivityManagerService.this) {
1106 doPendingActivityLaunchesLocked(true);
1107 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001108 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001109 case KILL_APPLICATION_MSG: {
1110 synchronized (ActivityManagerService.this) {
1111 int uid = msg.arg1;
1112 boolean restart = (msg.arg2 == 1);
1113 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001114 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001115 }
1116 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001117 case FINALIZE_PENDING_INTENT_MSG: {
1118 ((PendingIntentRecord)msg.obj).completeFinalize();
1119 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001120 case POST_HEAVY_NOTIFICATION_MSG: {
1121 INotificationManager inm = NotificationManager.getService();
1122 if (inm == null) {
1123 return;
1124 }
1125
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001126 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001127 ProcessRecord process = root.app;
1128 if (process == null) {
1129 return;
1130 }
1131
1132 try {
1133 Context context = mContext.createPackageContext(process.info.packageName, 0);
1134 String text = mContext.getString(R.string.heavy_weight_notification,
1135 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1136 Notification notification = new Notification();
1137 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1138 notification.when = 0;
1139 notification.flags = Notification.FLAG_ONGOING_EVENT;
1140 notification.tickerText = text;
1141 notification.defaults = 0; // please be quiet
1142 notification.sound = null;
1143 notification.vibrate = null;
1144 notification.setLatestEventInfo(context, text,
1145 mContext.getText(R.string.heavy_weight_notification_detail),
1146 PendingIntent.getActivity(mContext, 0, root.intent,
1147 PendingIntent.FLAG_CANCEL_CURRENT));
1148
1149 try {
1150 int[] outId = new int[1];
1151 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1152 notification, outId);
1153 } catch (RuntimeException e) {
1154 Slog.w(ActivityManagerService.TAG,
1155 "Error showing notification for heavy-weight app", e);
1156 } catch (RemoteException e) {
1157 }
1158 } catch (NameNotFoundException e) {
1159 Log.w(TAG, "Unable to create context for heavy notification", e);
1160 }
1161 } break;
1162 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1163 INotificationManager inm = NotificationManager.getService();
1164 if (inm == null) {
1165 return;
1166 }
1167 try {
1168 inm.cancelNotification("android",
1169 R.string.heavy_weight_notification);
1170 } catch (RuntimeException e) {
1171 Slog.w(ActivityManagerService.TAG,
1172 "Error canceling notification for service", e);
1173 } catch (RemoteException e) {
1174 }
1175 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 }
1177 }
1178 };
1179
1180 public static void setSystemProcess() {
1181 try {
1182 ActivityManagerService m = mSelf;
1183
1184 ServiceManager.addService("activity", m);
1185 ServiceManager.addService("meminfo", new MemBinder(m));
1186 if (MONITOR_CPU_USAGE) {
1187 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 ServiceManager.addService("permission", new PermissionController(m));
1190
1191 ApplicationInfo info =
1192 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001193 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001194 mSystemThread.installSystemApplicationInfo(info);
1195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 synchronized (mSelf) {
1197 ProcessRecord app = mSelf.newProcessRecordLocked(
1198 mSystemThread.getApplicationThread(), info,
1199 info.processName);
1200 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001201 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 app.maxAdj = SYSTEM_ADJ;
1203 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1204 synchronized (mSelf.mPidsSelfLocked) {
1205 mSelf.mPidsSelfLocked.put(app.pid, app);
1206 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001207 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 }
1209 } catch (PackageManager.NameNotFoundException e) {
1210 throw new RuntimeException(
1211 "Unable to find android system package", e);
1212 }
1213 }
1214
1215 public void setWindowManager(WindowManagerService wm) {
1216 mWindowManager = wm;
1217 }
1218
1219 public static final Context main(int factoryTest) {
1220 AThread thr = new AThread();
1221 thr.start();
1222
1223 synchronized (thr) {
1224 while (thr.mService == null) {
1225 try {
1226 thr.wait();
1227 } catch (InterruptedException e) {
1228 }
1229 }
1230 }
1231
1232 ActivityManagerService m = thr.mService;
1233 mSelf = m;
1234 ActivityThread at = ActivityThread.systemMain();
1235 mSystemThread = at;
1236 Context context = at.getSystemContext();
1237 m.mContext = context;
1238 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001239 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240
1241 m.mBatteryStatsService.publish(context);
1242 m.mUsageStatsService.publish(context);
1243
1244 synchronized (thr) {
1245 thr.mReady = true;
1246 thr.notifyAll();
1247 }
1248
1249 m.startRunning(null, null, null, null);
1250
1251 return context;
1252 }
1253
1254 public static ActivityManagerService self() {
1255 return mSelf;
1256 }
1257
1258 static class AThread extends Thread {
1259 ActivityManagerService mService;
1260 boolean mReady = false;
1261
1262 public AThread() {
1263 super("ActivityManager");
1264 }
1265
1266 public void run() {
1267 Looper.prepare();
1268
1269 android.os.Process.setThreadPriority(
1270 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001271 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272
1273 ActivityManagerService m = new ActivityManagerService();
1274
1275 synchronized (this) {
1276 mService = m;
1277 notifyAll();
1278 }
1279
1280 synchronized (this) {
1281 while (!mReady) {
1282 try {
1283 wait();
1284 } catch (InterruptedException e) {
1285 }
1286 }
1287 }
1288
1289 Looper.loop();
1290 }
1291 }
1292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 static class MemBinder extends Binder {
1294 ActivityManagerService mActivityManagerService;
1295 MemBinder(ActivityManagerService activityManagerService) {
1296 mActivityManagerService = activityManagerService;
1297 }
1298
1299 @Override
1300 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1301 ActivityManagerService service = mActivityManagerService;
1302 ArrayList<ProcessRecord> procs;
1303 synchronized (mActivityManagerService) {
1304 if (args != null && args.length > 0
1305 && args[0].charAt(0) != '-') {
1306 procs = new ArrayList<ProcessRecord>();
1307 int pid = -1;
1308 try {
1309 pid = Integer.parseInt(args[0]);
1310 } catch (NumberFormatException e) {
1311
1312 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001313 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1314 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 if (proc.pid == pid) {
1316 procs.add(proc);
1317 } else if (proc.processName.equals(args[0])) {
1318 procs.add(proc);
1319 }
1320 }
1321 if (procs.size() <= 0) {
1322 pw.println("No process found for: " + args[0]);
1323 return;
1324 }
1325 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001326 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 }
1328 }
1329 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1330 }
1331 }
1332
1333 static class CpuBinder extends Binder {
1334 ActivityManagerService mActivityManagerService;
1335 CpuBinder(ActivityManagerService activityManagerService) {
1336 mActivityManagerService = activityManagerService;
1337 }
1338
1339 @Override
1340 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1341 synchronized (mActivityManagerService.mProcessStatsThread) {
1342 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1343 }
1344 }
1345 }
1346
1347 private ActivityManagerService() {
1348 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1349 if (v != null && Integer.getInteger(v) != 0) {
1350 mSimpleProcessManagement = true;
1351 }
1352 v = System.getenv("ANDROID_DEBUG_APP");
1353 if (v != null) {
1354 mSimpleProcessManagement = true;
1355 }
1356
Joe Onorato8a9b2202010-02-26 18:56:32 -08001357 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 File dataDir = Environment.getDataDirectory();
1360 File systemDir = new File(dataDir, "system");
1361 systemDir.mkdirs();
1362 mBatteryStatsService = new BatteryStatsService(new File(
1363 systemDir, "batterystats.bin").toString());
1364 mBatteryStatsService.getActiveStatistics().readLocked();
1365 mBatteryStatsService.getActiveStatistics().writeLocked();
1366
1367 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001368 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369
Jack Palevichb90d28c2009-07-22 15:35:24 -07001370 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1371 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1372
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001373 mConfiguration.setToDefaults();
1374 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 mProcessStats.init();
1376
1377 // Add ourself to the Watchdog monitors.
1378 Watchdog.getInstance().addMonitor(this);
1379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 mProcessStatsThread = new Thread("ProcessStats") {
1381 public void run() {
1382 while (true) {
1383 try {
1384 try {
1385 synchronized(this) {
1386 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001387 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001389 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 // + ", write delay=" + nextWriteDelay);
1391 if (nextWriteDelay < nextCpuDelay) {
1392 nextCpuDelay = nextWriteDelay;
1393 }
1394 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001395 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 this.wait(nextCpuDelay);
1397 }
1398 }
1399 } catch (InterruptedException e) {
1400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 updateCpuStatsNow();
1402 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001403 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 }
1405 }
1406 }
1407 };
1408 mProcessStatsThread.start();
1409 }
1410
1411 @Override
1412 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1413 throws RemoteException {
1414 try {
1415 return super.onTransact(code, data, reply, flags);
1416 } catch (RuntimeException e) {
1417 // The activity manager only throws security exceptions, so let's
1418 // log all others.
1419 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001420 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 }
1422 throw e;
1423 }
1424 }
1425
1426 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001427 final long now = SystemClock.uptimeMillis();
1428 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1429 return;
1430 }
1431 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1432 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 mProcessStatsThread.notify();
1434 }
1435 }
1436 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 void updateCpuStatsNow() {
1439 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001440 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 final long now = SystemClock.uptimeMillis();
1442 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001445 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1446 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 haveNewCpuStats = true;
1448 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001449 //Slog.i(TAG, mProcessStats.printCurrentState());
1450 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 // + mProcessStats.getTotalCpuPercent() + "%");
1452
Joe Onorato8a9b2202010-02-26 18:56:32 -08001453 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 if ("true".equals(SystemProperties.get("events.cpu"))) {
1455 int user = mProcessStats.getLastUserTime();
1456 int system = mProcessStats.getLastSystemTime();
1457 int iowait = mProcessStats.getLastIoWaitTime();
1458 int irq = mProcessStats.getLastIrqTime();
1459 int softIrq = mProcessStats.getLastSoftIrqTime();
1460 int idle = mProcessStats.getLastIdleTime();
1461
1462 int total = user + system + iowait + irq + softIrq + idle;
1463 if (total == 0) total = 1;
1464
Doug Zongker2bec3d42009-12-04 12:52:44 -08001465 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 ((user+system+iowait+irq+softIrq) * 100) / total,
1467 (user * 100) / total,
1468 (system * 100) / total,
1469 (iowait * 100) / total,
1470 (irq * 100) / total,
1471 (softIrq * 100) / total);
1472 }
1473 }
1474
Amith Yamasanie43530a2009-08-21 13:11:37 -07001475 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001476 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001477 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 synchronized(mPidsSelfLocked) {
1479 if (haveNewCpuStats) {
1480 if (mBatteryStatsService.isOnBattery()) {
1481 final int N = mProcessStats.countWorkingStats();
1482 for (int i=0; i<N; i++) {
1483 ProcessStats.Stats st
1484 = mProcessStats.getWorkingStats(i);
1485 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1486 if (pr != null) {
1487 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1488 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001489 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001490 } else {
1491 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001492 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001493 if (ps != null) {
1494 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001495 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 }
1498 }
1499 }
1500 }
1501 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1504 mLastWriteTime = now;
1505 mBatteryStatsService.getActiveStatistics().writeLocked();
1506 }
1507 }
1508 }
1509 }
1510
1511 /**
1512 * Initialize the application bind args. These are passed to each
1513 * process when the bindApplication() IPC is sent to the process. They're
1514 * lazily setup to make sure the services are running when they're asked for.
1515 */
1516 private HashMap<String, IBinder> getCommonServicesLocked() {
1517 if (mAppBindArgs == null) {
1518 mAppBindArgs = new HashMap<String, IBinder>();
1519
1520 // Setup the application init args
1521 mAppBindArgs.put("package", ServiceManager.getService("package"));
1522 mAppBindArgs.put("window", ServiceManager.getService("window"));
1523 mAppBindArgs.put(Context.ALARM_SERVICE,
1524 ServiceManager.getService(Context.ALARM_SERVICE));
1525 }
1526 return mAppBindArgs;
1527 }
1528
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001529 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 if (mFocusedActivity != r) {
1531 mFocusedActivity = r;
1532 mWindowManager.setFocusedApp(r, true);
1533 }
1534 }
1535
Dianne Hackborn906497c2010-05-10 15:57:38 -07001536 private final void updateLruProcessInternalLocked(ProcessRecord app,
1537 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001539 int lrui = mLruProcesses.indexOf(app);
1540 if (lrui >= 0) mLruProcesses.remove(lrui);
1541
1542 int i = mLruProcesses.size()-1;
1543 int skipTop = 0;
1544
Dianne Hackborn906497c2010-05-10 15:57:38 -07001545 app.lruSeq = mLruSeq;
1546
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001547 // compute the new weight for this process.
1548 if (updateActivityTime) {
1549 app.lastActivityTime = SystemClock.uptimeMillis();
1550 }
1551 if (app.activities.size() > 0) {
1552 // If this process has activities, we more strongly want to keep
1553 // it around.
1554 app.lruWeight = app.lastActivityTime;
1555 } else if (app.pubProviders.size() > 0) {
1556 // If this process contains content providers, we want to keep
1557 // it a little more strongly.
1558 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1559 // Also don't let it kick out the first few "real" hidden processes.
1560 skipTop = MIN_HIDDEN_APPS;
1561 } else {
1562 // If this process doesn't have activities, we less strongly
1563 // want to keep it around, and generally want to avoid getting
1564 // in front of any very recently used activities.
1565 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1566 // Also don't let it kick out the first few "real" hidden processes.
1567 skipTop = MIN_HIDDEN_APPS;
1568 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001569
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001570 while (i >= 0) {
1571 ProcessRecord p = mLruProcesses.get(i);
1572 // If this app shouldn't be in front of the first N background
1573 // apps, then skip over that many that are currently hidden.
1574 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1575 skipTop--;
1576 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001577 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001578 mLruProcesses.add(i+1, app);
1579 break;
1580 }
1581 i--;
1582 }
1583 if (i < 0) {
1584 mLruProcesses.add(0, app);
1585 }
1586
Dianne Hackborn906497c2010-05-10 15:57:38 -07001587 // If the app is currently using a content provider or service,
1588 // bump those processes as well.
1589 if (app.connections.size() > 0) {
1590 for (ConnectionRecord cr : app.connections) {
1591 if (cr.binding != null && cr.binding.service != null
1592 && cr.binding.service.app != null
1593 && cr.binding.service.app.lruSeq != mLruSeq) {
1594 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1595 updateActivityTime, i+1);
1596 }
1597 }
1598 }
1599 if (app.conProviders.size() > 0) {
1600 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1601 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1602 updateLruProcessInternalLocked(cpr.app, oomAdj,
1603 updateActivityTime, i+1);
1604 }
1605 }
1606 }
1607
Joe Onorato8a9b2202010-02-26 18:56:32 -08001608 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 if (oomAdj) {
1610 updateOomAdjLocked();
1611 }
1612 }
1613
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001614 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001615 boolean oomAdj, boolean updateActivityTime) {
1616 mLruSeq++;
1617 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1618 }
1619
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001620 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 String processName, int uid) {
1622 if (uid == Process.SYSTEM_UID) {
1623 // The system gets to run in any process. If there are multiple
1624 // processes with the same uid, just pick the first (this
1625 // should never happen).
1626 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1627 processName);
1628 return procs != null ? procs.valueAt(0) : null;
1629 }
1630 ProcessRecord proc = mProcessNames.get(processName, uid);
1631 return proc;
1632 }
1633
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001634 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001635 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001636 try {
1637 if (pm.performDexOpt(packageName)) {
1638 mDidDexOpt = true;
1639 }
1640 } catch (RemoteException e) {
1641 }
1642 }
1643
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001644 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 int transit = mWindowManager.getPendingAppTransition();
1646 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1647 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1648 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1649 }
1650
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001651 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001653 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1655 // We don't have to do anything more if:
1656 // (1) There is an existing application record; and
1657 // (2) The caller doesn't think it is dead, OR there is no thread
1658 // object attached to it so we know it couldn't have crashed; and
1659 // (3) There is a pid assigned to it, so it is either starting or
1660 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001661 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 + " app=" + app + " knownToBeDead=" + knownToBeDead
1663 + " thread=" + (app != null ? app.thread : null)
1664 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001665 if (app != null && app.pid > 0) {
1666 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001667 // We already have the app running, or are waiting for it to
1668 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001669 return app;
1670 } else {
1671 // An application record is attached to a previous process,
1672 // clean it up now.
1673 handleAppDiedLocked(app, true);
1674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 String hostingNameStr = hostingName != null
1678 ? hostingName.flattenToShortString() : null;
1679
1680 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1681 // If we are in the background, then check to see if this process
1682 // is bad. If so, we will just silently fail.
1683 if (mBadProcesses.get(info.processName, info.uid) != null) {
1684 return null;
1685 }
1686 } else {
1687 // When the user is explicitly starting a process, then clear its
1688 // crash count so that we won't make it bad until they see at
1689 // least one crash dialog again, and make the process good again
1690 // if it had been bad.
1691 mProcessCrashTimes.remove(info.processName, info.uid);
1692 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001693 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 info.processName);
1695 mBadProcesses.remove(info.processName, info.uid);
1696 if (app != null) {
1697 app.bad = false;
1698 }
1699 }
1700 }
1701
1702 if (app == null) {
1703 app = newProcessRecordLocked(null, info, processName);
1704 mProcessNames.put(processName, info.uid, app);
1705 } else {
1706 // If this is a new package in the process, add the package to the list
1707 app.addPackage(info.packageName);
1708 }
1709
1710 // If the system is not ready yet, then hold off on starting this
1711 // process until it is.
1712 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001713 && !isAllowedWhileBooting(info)
1714 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 if (!mProcessesOnHold.contains(app)) {
1716 mProcessesOnHold.add(app);
1717 }
1718 return app;
1719 }
1720
1721 startProcessLocked(app, hostingType, hostingNameStr);
1722 return (app.pid != 0) ? app : null;
1723 }
1724
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001725 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1726 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1727 }
1728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 private final void startProcessLocked(ProcessRecord app,
1730 String hostingType, String hostingNameStr) {
1731 if (app.pid > 0 && app.pid != MY_PID) {
1732 synchronized (mPidsSelfLocked) {
1733 mPidsSelfLocked.remove(app.pid);
1734 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1735 }
1736 app.pid = 0;
1737 }
1738
1739 mProcessesOnHold.remove(app);
1740
1741 updateCpuStats();
1742
1743 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1744 mProcDeaths[0] = 0;
1745
1746 try {
1747 int uid = app.info.uid;
1748 int[] gids = null;
1749 try {
1750 gids = mContext.getPackageManager().getPackageGids(
1751 app.info.packageName);
1752 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001753 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 }
1755 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1756 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1757 && mTopComponent != null
1758 && app.processName.equals(mTopComponent.getPackageName())) {
1759 uid = 0;
1760 }
1761 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1762 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1763 uid = 0;
1764 }
1765 }
1766 int debugFlags = 0;
1767 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1768 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1769 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001770 // Run the app in safe mode if its manifest requests so or the
1771 // system is booted in safe mode.
1772 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1773 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001774 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1777 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1778 }
1779 if ("1".equals(SystemProperties.get("debug.assert"))) {
1780 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1781 }
1782 int pid = Process.start("android.app.ActivityThread",
1783 mSimpleProcessManagement ? app.processName : null, uid, uid,
1784 gids, debugFlags, null);
1785 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1786 synchronized (bs) {
1787 if (bs.isOnBattery()) {
1788 app.batteryStats.incStartsLocked();
1789 }
1790 }
1791
Doug Zongker2bec3d42009-12-04 12:52:44 -08001792 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 app.processName, hostingType,
1794 hostingNameStr != null ? hostingNameStr : "");
1795
1796 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001797 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 }
1799
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001800 StringBuilder buf = mStringBuilder;
1801 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 buf.append("Start proc ");
1803 buf.append(app.processName);
1804 buf.append(" for ");
1805 buf.append(hostingType);
1806 if (hostingNameStr != null) {
1807 buf.append(" ");
1808 buf.append(hostingNameStr);
1809 }
1810 buf.append(": pid=");
1811 buf.append(pid);
1812 buf.append(" uid=");
1813 buf.append(uid);
1814 buf.append(" gids={");
1815 if (gids != null) {
1816 for (int gi=0; gi<gids.length; gi++) {
1817 if (gi != 0) buf.append(", ");
1818 buf.append(gids[gi]);
1819
1820 }
1821 }
1822 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001823 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 if (pid == 0 || pid == MY_PID) {
1825 // Processes are being emulated with threads.
1826 app.pid = MY_PID;
1827 app.removed = false;
1828 mStartingProcesses.add(app);
1829 } else if (pid > 0) {
1830 app.pid = pid;
1831 app.removed = false;
1832 synchronized (mPidsSelfLocked) {
1833 this.mPidsSelfLocked.put(pid, app);
1834 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1835 msg.obj = app;
1836 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1837 }
1838 } else {
1839 app.pid = 0;
1840 RuntimeException e = new RuntimeException(
1841 "Failure starting process " + app.processName
1842 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001843 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 }
1845 } catch (RuntimeException e) {
1846 // XXX do better error recovery.
1847 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001848 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 }
1850 }
1851
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001852 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 if (resumed) {
1854 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1855 } else {
1856 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1857 }
1858 }
1859
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001860 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001861 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1862 && mTopAction == null) {
1863 // We are running in factory test mode, but unable to find
1864 // the factory test app, so just sit around displaying the
1865 // error message and don't try to start anything.
1866 return false;
1867 }
1868 Intent intent = new Intent(
1869 mTopAction,
1870 mTopData != null ? Uri.parse(mTopData) : null);
1871 intent.setComponent(mTopComponent);
1872 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1873 intent.addCategory(Intent.CATEGORY_HOME);
1874 }
1875 ActivityInfo aInfo =
1876 intent.resolveActivityInfo(mContext.getPackageManager(),
1877 STOCK_PM_FLAGS);
1878 if (aInfo != null) {
1879 intent.setComponent(new ComponentName(
1880 aInfo.applicationInfo.packageName, aInfo.name));
1881 // Don't do this if the home app is currently being
1882 // instrumented.
1883 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1884 aInfo.applicationInfo.uid);
1885 if (app == null || app.instrumentationClass == null) {
1886 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001887 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001888 null, null, 0, 0, 0, false, false);
1889 }
1890 }
1891
1892
1893 return true;
1894 }
1895
1896 /**
1897 * Starts the "new version setup screen" if appropriate.
1898 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001899 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001900 // Only do this once per boot.
1901 if (mCheckedForSetup) {
1902 return;
1903 }
1904
1905 // We will show this screen if the current one is a different
1906 // version than the last one shown, and we are not running in
1907 // low-level factory test mode.
1908 final ContentResolver resolver = mContext.getContentResolver();
1909 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1910 Settings.Secure.getInt(resolver,
1911 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1912 mCheckedForSetup = true;
1913
1914 // See if we should be showing the platform update setup UI.
1915 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1916 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1917 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1918
1919 // We don't allow third party apps to replace this.
1920 ResolveInfo ri = null;
1921 for (int i=0; ris != null && i<ris.size(); i++) {
1922 if ((ris.get(i).activityInfo.applicationInfo.flags
1923 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1924 ri = ris.get(i);
1925 break;
1926 }
1927 }
1928
1929 if (ri != null) {
1930 String vers = ri.activityInfo.metaData != null
1931 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1932 : null;
1933 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1934 vers = ri.activityInfo.applicationInfo.metaData.getString(
1935 Intent.METADATA_SETUP_VERSION);
1936 }
1937 String lastVers = Settings.Secure.getString(
1938 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1939 if (vers != null && !vers.equals(lastVers)) {
1940 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1941 intent.setComponent(new ComponentName(
1942 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001943 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001944 null, null, 0, 0, 0, false, false);
1945 }
1946 }
1947 }
1948 }
1949
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001950 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001951 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001952
1953 final int identHash = System.identityHashCode(r);
1954 updateUsageStats(r, true);
1955
1956 int i = mWatchers.beginBroadcast();
1957 while (i > 0) {
1958 i--;
1959 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1960 if (w != null) {
1961 try {
1962 w.activityResuming(identHash);
1963 } catch (RemoteException e) {
1964 }
1965 }
1966 }
1967 mWatchers.finishBroadcast();
1968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001970 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001971 final int N = mPendingActivityLaunches.size();
1972 if (N <= 0) {
1973 return;
1974 }
1975 for (int i=0; i<N; i++) {
1976 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001977 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001978 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1979 doResume && i == (N-1));
1980 }
1981 mPendingActivityLaunches.clear();
1982 }
1983
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001984 public final int startActivity(IApplicationThread caller,
1985 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1986 int grantedMode, IBinder resultTo,
1987 String resultWho, int requestCode, boolean onlyIfNeeded,
1988 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001989 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001990 grantedUriPermissions, grantedMode, resultTo, resultWho,
1991 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001992 }
1993
1994 public final WaitResult startActivityAndWait(IApplicationThread caller,
1995 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1996 int grantedMode, IBinder resultTo,
1997 String resultWho, int requestCode, boolean onlyIfNeeded,
1998 boolean debug) {
1999 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002000 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002001 grantedUriPermissions, grantedMode, resultTo, resultWho,
2002 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002003 return res;
2004 }
2005
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002006 public final int startActivityWithConfig(IApplicationThread caller,
2007 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2008 int grantedMode, IBinder resultTo,
2009 String resultWho, int requestCode, boolean onlyIfNeeded,
2010 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002011 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002012 grantedUriPermissions, grantedMode, resultTo, resultWho,
2013 requestCode, onlyIfNeeded, debug, null, config);
2014 }
2015
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002016 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002017 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002018 IBinder resultTo, String resultWho, int requestCode,
2019 int flagsMask, int flagsValues) {
2020 // Refuse possible leaked file descriptors
2021 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2022 throw new IllegalArgumentException("File descriptors passed in Intent");
2023 }
2024
2025 IIntentSender sender = intent.getTarget();
2026 if (!(sender instanceof PendingIntentRecord)) {
2027 throw new IllegalArgumentException("Bad PendingIntent object");
2028 }
2029
2030 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002031
2032 synchronized (this) {
2033 // If this is coming from the currently resumed activity, it is
2034 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002035 if (mMainStack.mResumedActivity != null
2036 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002037 Binder.getCallingUid()) {
2038 mAppSwitchesAllowedTime = 0;
2039 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002040 }
2041
2042 return pir.sendInner(0, fillInIntent, resolvedType,
2043 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2044 }
2045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 public boolean startNextMatchingActivity(IBinder callingActivity,
2047 Intent intent) {
2048 // Refuse possible leaked file descriptors
2049 if (intent != null && intent.hasFileDescriptors() == true) {
2050 throw new IllegalArgumentException("File descriptors passed in Intent");
2051 }
2052
2053 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002054 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 if (index < 0) {
2056 return false;
2057 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002058 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 if (r.app == null || r.app.thread == null) {
2060 // The caller is not running... d'oh!
2061 return false;
2062 }
2063 intent = new Intent(intent);
2064 // The caller is not allowed to change the data.
2065 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2066 // And we are resetting to find the next component...
2067 intent.setComponent(null);
2068
2069 ActivityInfo aInfo = null;
2070 try {
2071 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002072 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002074 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075
2076 // Look for the original activity in the list...
2077 final int N = resolves != null ? resolves.size() : 0;
2078 for (int i=0; i<N; i++) {
2079 ResolveInfo rInfo = resolves.get(i);
2080 if (rInfo.activityInfo.packageName.equals(r.packageName)
2081 && rInfo.activityInfo.name.equals(r.info.name)) {
2082 // We found the current one... the next matching is
2083 // after it.
2084 i++;
2085 if (i<N) {
2086 aInfo = resolves.get(i).activityInfo;
2087 }
2088 break;
2089 }
2090 }
2091 } catch (RemoteException e) {
2092 }
2093
2094 if (aInfo == null) {
2095 // Nobody who is next!
2096 return false;
2097 }
2098
2099 intent.setComponent(new ComponentName(
2100 aInfo.applicationInfo.packageName, aInfo.name));
2101 intent.setFlags(intent.getFlags()&~(
2102 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2103 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2104 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2105 Intent.FLAG_ACTIVITY_NEW_TASK));
2106
2107 // Okay now we need to start the new activity, replacing the
2108 // currently running activity. This is a little tricky because
2109 // we want to start the new one as if the current one is finished,
2110 // but not finish the current one first so that there is no flicker.
2111 // And thus...
2112 final boolean wasFinishing = r.finishing;
2113 r.finishing = true;
2114
2115 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002116 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 final String resultWho = r.resultWho;
2118 final int requestCode = r.requestCode;
2119 r.resultTo = null;
2120 if (resultTo != null) {
2121 resultTo.removeResultsLocked(r, resultWho, requestCode);
2122 }
2123
2124 final long origId = Binder.clearCallingIdentity();
2125 // XXX we are not dealing with propagating grantedUriPermissions...
2126 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002127 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002129 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 Binder.restoreCallingIdentity(origId);
2131
2132 r.finishing = wasFinishing;
2133 if (res != START_SUCCESS) {
2134 return false;
2135 }
2136 return true;
2137 }
2138 }
2139
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002140 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 Intent intent, String resolvedType, IBinder resultTo,
2142 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002143
2144 // This is so super not safe, that only the system (or okay root)
2145 // can do it.
2146 final int callingUid = Binder.getCallingUid();
2147 if (callingUid != 0 && callingUid != Process.myUid()) {
2148 throw new SecurityException(
2149 "startActivityInPackage only available to the system");
2150 }
2151
The Android Open Source Project4df24232009-03-05 14:34:35 -08002152 final boolean componentSpecified = intent.getComponent() != null;
2153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 // Don't modify the client's object!
2155 intent = new Intent(intent);
2156
2157 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 ActivityInfo aInfo;
2159 try {
2160 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002161 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002163 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164 aInfo = rInfo != null ? rInfo.activityInfo : null;
2165 } catch (RemoteException e) {
2166 aInfo = null;
2167 }
2168
2169 if (aInfo != null) {
2170 // Store the found target back into the intent, because now that
2171 // we have it we never want to do this again. For example, if the
2172 // user navigates back to this point in the history, we should
2173 // always restart the exact same activity.
2174 intent.setComponent(new ComponentName(
2175 aInfo.applicationInfo.packageName, aInfo.name));
2176 }
2177
2178 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002179 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002181 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 }
2183 }
2184
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002185 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 // Remove any existing entries that are the same kind of task.
2187 int N = mRecentTasks.size();
2188 for (int i=0; i<N; i++) {
2189 TaskRecord tr = mRecentTasks.get(i);
2190 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2191 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2192 mRecentTasks.remove(i);
2193 i--;
2194 N--;
2195 if (task.intent == null) {
2196 // If the new recent task we are adding is not fully
2197 // specified, then replace it with the existing recent task.
2198 task = tr;
2199 }
2200 }
2201 }
2202 if (N >= MAX_RECENT_TASKS) {
2203 mRecentTasks.remove(N-1);
2204 }
2205 mRecentTasks.add(0, task);
2206 }
2207
2208 public void setRequestedOrientation(IBinder token,
2209 int requestedOrientation) {
2210 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002211 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 if (index < 0) {
2213 return;
2214 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002215 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 final long origId = Binder.clearCallingIdentity();
2217 mWindowManager.setAppOrientation(r, requestedOrientation);
2218 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002219 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 r.mayFreezeScreenLocked(r.app) ? r : null);
2221 if (config != null) {
2222 r.frozenBeforeDestroy = true;
2223 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002224 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 }
2226 }
2227 Binder.restoreCallingIdentity(origId);
2228 }
2229 }
2230
2231 public int getRequestedOrientation(IBinder token) {
2232 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002233 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 if (index < 0) {
2235 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2236 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002237 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 return mWindowManager.getAppOrientation(r);
2239 }
2240 }
2241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 /**
2243 * This is the internal entry point for handling Activity.finish().
2244 *
2245 * @param token The Binder token referencing the Activity we want to finish.
2246 * @param resultCode Result code, if any, from this Activity.
2247 * @param resultData Result data (Intent), if any, from this Activity.
2248 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002249 * @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 -08002250 */
2251 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2252 // Refuse possible leaked file descriptors
2253 if (resultData != null && resultData.hasFileDescriptors() == true) {
2254 throw new IllegalArgumentException("File descriptors passed in Intent");
2255 }
2256
2257 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002258 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002260 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 if (next != null) {
2262 // ask watcher if this is allowed
2263 boolean resumeOK = true;
2264 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002265 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002267 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 }
2269
2270 if (!resumeOK) {
2271 return false;
2272 }
2273 }
2274 }
2275 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002276 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 resultData, "app-request");
2278 Binder.restoreCallingIdentity(origId);
2279 return res;
2280 }
2281 }
2282
Dianne Hackborn860755f2010-06-03 18:47:52 -07002283 public final void finishHeavyWeightApp() {
2284 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2285 != PackageManager.PERMISSION_GRANTED) {
2286 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2287 + Binder.getCallingPid()
2288 + ", uid=" + Binder.getCallingUid()
2289 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2290 Slog.w(TAG, msg);
2291 throw new SecurityException(msg);
2292 }
2293
2294 synchronized(this) {
2295 if (mHeavyWeightProcess == null) {
2296 return;
2297 }
2298
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002299 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002300 mHeavyWeightProcess.activities);
2301 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002302 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002303 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002304 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002305 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002306 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002307 null, "finish-heavy");
2308 }
2309 }
2310 }
2311
2312 mHeavyWeightProcess = null;
2313 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2314 }
2315 }
2316
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002317 public void crashApplication(int uid, int initialPid, String packageName,
2318 String message) {
2319 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2320 != PackageManager.PERMISSION_GRANTED) {
2321 String msg = "Permission Denial: crashApplication() from pid="
2322 + Binder.getCallingPid()
2323 + ", uid=" + Binder.getCallingUid()
2324 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2325 Slog.w(TAG, msg);
2326 throw new SecurityException(msg);
2327 }
2328
2329 synchronized(this) {
2330 ProcessRecord proc = null;
2331
2332 // Figure out which process to kill. We don't trust that initialPid
2333 // still has any relation to current pids, so must scan through the
2334 // list.
2335 synchronized (mPidsSelfLocked) {
2336 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2337 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2338 if (p.info.uid != uid) {
2339 continue;
2340 }
2341 if (p.pid == initialPid) {
2342 proc = p;
2343 break;
2344 }
2345 for (String str : p.pkgList) {
2346 if (str.equals(packageName)) {
2347 proc = p;
2348 }
2349 }
2350 }
2351 }
2352
2353 if (proc == null) {
2354 Log.w(TAG, "crashApplication: nothing for uid=" + uid
2355 + " initialPid=" + initialPid
2356 + " packageName=" + packageName);
2357 return;
2358 }
2359
2360 if (proc.thread != null) {
2361 long ident = Binder.clearCallingIdentity();
2362 try {
2363 proc.thread.scheduleCrash(message);
2364 } catch (RemoteException e) {
2365 }
2366 Binder.restoreCallingIdentity(ident);
2367 }
2368 }
2369 }
2370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 public final void finishSubActivity(IBinder token, String resultWho,
2372 int requestCode) {
2373 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002374 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 if (index < 0) {
2376 return;
2377 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002378 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379
2380 final long origId = Binder.clearCallingIdentity();
2381
2382 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002383 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2384 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 if (r.resultTo == self && r.requestCode == requestCode) {
2386 if ((r.resultWho == null && resultWho == null) ||
2387 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002388 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 Activity.RESULT_CANCELED, null, "request-sub");
2390 }
2391 }
2392 }
2393
2394 Binder.restoreCallingIdentity(origId);
2395 }
2396 }
2397
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002398 public boolean willActivityBeVisible(IBinder token) {
2399 synchronized(this) {
2400 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002401 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2402 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002403 if (r == token) {
2404 return true;
2405 }
2406 if (r.fullscreen && !r.finishing) {
2407 return false;
2408 }
2409 }
2410 return true;
2411 }
2412 }
2413
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002414 public void overridePendingTransition(IBinder token, String packageName,
2415 int enterAnim, int exitAnim) {
2416 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002417 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002418 if (index < 0) {
2419 return;
2420 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002421 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002422
2423 final long origId = Binder.clearCallingIdentity();
2424
2425 if (self.state == ActivityState.RESUMED
2426 || self.state == ActivityState.PAUSING) {
2427 mWindowManager.overridePendingAppTransition(packageName,
2428 enterAnim, exitAnim);
2429 }
2430
2431 Binder.restoreCallingIdentity(origId);
2432 }
2433 }
2434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 * Main function for removing an existing process from the activity manager
2437 * as a result of that process going away. Clears out all connections
2438 * to the process.
2439 */
2440 private final void handleAppDiedLocked(ProcessRecord app,
2441 boolean restarting) {
2442 cleanUpApplicationRecordLocked(app, restarting, -1);
2443 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002444 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 }
2446
2447 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002448 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2449 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2450 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002452 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2453 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 }
2455
2456 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002457 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458
2459 boolean atTop = true;
2460 boolean hasVisibleActivities = false;
2461
2462 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002463 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002464 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 TAG, "Removing app " + app + " from history with " + i + " entries");
2466 while (i > 0) {
2467 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002469 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2471 if (r.app == app) {
2472 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002473 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474 TAG, "Removing this entry! frozen=" + r.haveState
2475 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002476 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477
2478 r.inHistory = false;
2479 mWindowManager.removeAppToken(r);
2480 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002481 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002483 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484
2485 } else {
2486 // We have the current state for this activity, so
2487 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002488 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 TAG, "Keeping entry, setting app to null");
2490 if (r.visible) {
2491 hasVisibleActivities = true;
2492 }
2493 r.app = null;
2494 r.nowVisible = false;
2495 if (!r.haveState) {
2496 r.icicle = null;
2497 }
2498 }
2499
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002500 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 r.state = ActivityState.STOPPED;
2502 }
2503 atTop = false;
2504 }
2505
2506 app.activities.clear();
2507
2508 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002509 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 + " running instrumentation " + app.instrumentationClass);
2511 Bundle info = new Bundle();
2512 info.putString("shortMsg", "Process crashed.");
2513 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2514 }
2515
2516 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002517 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 // If there was nothing to resume, and we are not already
2519 // restarting this process, but there is a visible activity that
2520 // is hosted by the process... then make sure all visible
2521 // activities are running, taking care of restarting this
2522 // process.
2523 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002524 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 }
2526 }
2527 }
2528 }
2529
2530 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2531 IBinder threadBinder = thread.asBinder();
2532
2533 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002534 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2535 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002536 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2537 return i;
2538 }
2539 }
2540 return -1;
2541 }
2542
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002543 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 IApplicationThread thread) {
2545 if (thread == null) {
2546 return null;
2547 }
2548
2549 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002550 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 }
2552
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002553 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 IApplicationThread thread) {
2555
2556 mProcDeaths[0]++;
2557
Magnus Edlund7bb25812010-02-24 15:45:06 +01002558 // Clean up already done if the process has been re-started.
2559 if (app.pid == pid && app.thread != null &&
2560 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002561 if (!app.killedBackground) {
2562 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2563 + ") has died.");
2564 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002565 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002566 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 TAG, "Dying app: " + app + ", pid: " + pid
2568 + ", thread: " + thread.asBinder());
2569 boolean doLowMem = app.instrumentationClass == null;
2570 handleAppDiedLocked(app, false);
2571
2572 if (doLowMem) {
2573 // If there are no longer any background processes running,
2574 // and the app that died was not running instrumentation,
2575 // then tell everyone we are now low on memory.
2576 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002577 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2578 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2580 haveBg = true;
2581 break;
2582 }
2583 }
2584
2585 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002587 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002588 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002589 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2590 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002591 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002592 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2593 // The low memory report is overriding any current
2594 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002595 // heavy/important/visible/foreground processes first.
2596 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002597 rec.lastRequestedGc = 0;
2598 } else {
2599 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002601 rec.reportLowMemory = true;
2602 rec.lastLowMemory = now;
2603 mProcessesToGc.remove(rec);
2604 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 }
2606 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002607 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 }
2609 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002610 } else if (app.pid != pid) {
2611 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002613 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002614 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002615 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002616 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 + thread.asBinder());
2618 }
2619 }
2620
Dan Egnor42471dd2010-01-07 17:25:22 -08002621 /**
2622 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002623 * @param clearTraces causes the dump file to be erased prior to the new
2624 * traces being written, if true; when false, the new traces will be
2625 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002626 * @param pids of dalvik VM processes to dump stack traces for
2627 * @return file containing stack traces, or null if no dump file is configured
2628 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002629 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002630 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2631 if (tracesPath == null || tracesPath.length() == 0) {
2632 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002634
2635 File tracesFile = new File(tracesPath);
2636 try {
2637 File tracesDir = tracesFile.getParentFile();
2638 if (!tracesDir.exists()) tracesFile.mkdirs();
2639 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2640
Christopher Tate6ee412d2010-05-28 12:01:56 -07002641 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002642 tracesFile.createNewFile();
2643 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2644 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002645 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002646 return null;
2647 }
2648
2649 // Use a FileObserver to detect when traces finish writing.
2650 // The order of traces is considered important to maintain for legibility.
2651 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2652 public synchronized void onEvent(int event, String path) { notify(); }
2653 };
2654
2655 try {
2656 observer.startWatching();
2657 int num = pids.size();
2658 for (int i = 0; i < num; i++) {
2659 synchronized (observer) {
2660 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2661 observer.wait(200); // Wait for write-close, give up after 200msec
2662 }
2663 }
2664 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002665 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002666 } finally {
2667 observer.stopWatching();
2668 }
2669
2670 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 }
2672
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002673 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2674 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002675 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002676
2677 synchronized (this) {
2678 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2679 if (mShuttingDown) {
2680 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2681 return;
2682 } else if (app.notResponding) {
2683 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2684 return;
2685 } else if (app.crashing) {
2686 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2687 return;
2688 }
2689
2690 // In case we come through here for the same app before completing
2691 // this one, mark as anring now so we will bail out.
2692 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002693
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002694 // Log the ANR to the event log.
2695 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2696 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002697
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002698 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2699 pids.add(app.pid);
2700
2701 int parentPid = app.pid;
2702 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2703 if (parentPid != app.pid) pids.add(parentPid);
2704
2705 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002706
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002707 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2708 ProcessRecord r = mLruProcesses.get(i);
2709 if (r != null && r.thread != null) {
2710 int pid = r.pid;
2711 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 }
2714 }
2715
Christopher Tate6ee412d2010-05-28 12:01:56 -07002716 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002717
2718 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002719 StringBuilder info = mStringBuilder;
2720 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002721 info.append("ANR in ").append(app.processName);
2722 if (activity != null && activity.shortComponentName != null) {
2723 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002724 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002725 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002727 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002729 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002730 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732
Dan Egnor42471dd2010-01-07 17:25:22 -08002733 String cpuInfo = null;
2734 if (MONITOR_CPU_USAGE) {
2735 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002736 synchronized (mProcessStatsThread) {
2737 cpuInfo = mProcessStats.printCurrentState();
2738 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002739 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 }
2741
Joe Onorato8a9b2202010-02-26 18:56:32 -08002742 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002743 if (tracesFile == null) {
2744 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2745 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2746 }
2747
2748 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2749
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002750 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002752 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2753 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002755 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2756 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 }
2758 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002759 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 }
2761 }
2762
Dan Egnor42471dd2010-01-07 17:25:22 -08002763 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2764 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2765 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002766
2767 synchronized (this) {
2768 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2769 Process.killProcess(app.pid);
2770 return;
2771 }
2772
2773 // Set the app's notResponding state, and look up the errorReportReceiver
2774 makeAppNotRespondingLocked(app,
2775 activity != null ? activity.shortComponentName : null,
2776 annotation != null ? "ANR " + annotation : "ANR",
2777 info.toString());
2778
2779 // Bring up the infamous App Not Responding dialog
2780 Message msg = Message.obtain();
2781 HashMap map = new HashMap();
2782 msg.what = SHOW_NOT_RESPONDING_MSG;
2783 msg.obj = map;
2784 map.put("app", app);
2785 if (activity != null) {
2786 map.put("activity", activity);
2787 }
2788
2789 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 }
2792
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002793 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 app.persistentActivities--;
2795 if (app.persistentActivities > 0) {
2796 // Still more of 'em...
2797 return;
2798 }
2799 if (app.persistent) {
2800 // Ah, but the application itself is persistent. Whatever!
2801 return;
2802 }
2803
2804 // App is no longer persistent... make sure it and the ones
2805 // following it in the LRU list have the correc oom_adj.
2806 updateOomAdjLocked();
2807 }
2808
2809 public void setPersistent(IBinder token, boolean isPersistent) {
2810 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2811 != PackageManager.PERMISSION_GRANTED) {
2812 String msg = "Permission Denial: setPersistent() from pid="
2813 + Binder.getCallingPid()
2814 + ", uid=" + Binder.getCallingUid()
2815 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002816 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 throw new SecurityException(msg);
2818 }
2819
2820 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002821 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 if (index < 0) {
2823 return;
2824 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002825 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 ProcessRecord app = r.app;
2827
Joe Onorato8a9b2202010-02-26 18:56:32 -08002828 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 TAG, "Setting persistence " + isPersistent + ": " + r);
2830
2831 if (isPersistent) {
2832 if (r.persistent) {
2833 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002834 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 return;
2836 }
2837 r.persistent = true;
2838 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002839 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 if (app.persistentActivities > 1) {
2841 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002842 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 return;
2844 }
2845 if (app.persistent) {
2846 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002847 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 return;
2849 }
2850
2851 // App is now persistent... make sure it and the ones
2852 // following it now have the correct oom_adj.
2853 final long origId = Binder.clearCallingIdentity();
2854 updateOomAdjLocked();
2855 Binder.restoreCallingIdentity(origId);
2856
2857 } else {
2858 if (!r.persistent) {
2859 // Okay okay, I heard you already!
2860 return;
2861 }
2862 r.persistent = false;
2863 final long origId = Binder.clearCallingIdentity();
2864 decPersistentCountLocked(app);
2865 Binder.restoreCallingIdentity(origId);
2866
2867 }
2868 }
2869 }
2870
2871 public boolean clearApplicationUserData(final String packageName,
2872 final IPackageDataObserver observer) {
2873 int uid = Binder.getCallingUid();
2874 int pid = Binder.getCallingPid();
2875 long callingId = Binder.clearCallingIdentity();
2876 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002877 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 int pkgUid = -1;
2879 synchronized(this) {
2880 try {
2881 pkgUid = pm.getPackageUid(packageName);
2882 } catch (RemoteException e) {
2883 }
2884 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002885 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 return false;
2887 }
2888 if (uid == pkgUid || checkComponentPermission(
2889 android.Manifest.permission.CLEAR_APP_USER_DATA,
2890 pid, uid, -1)
2891 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002892 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 } else {
2894 throw new SecurityException(pid+" does not have permission:"+
2895 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2896 "for process:"+packageName);
2897 }
2898 }
2899
2900 try {
2901 //clear application user data
2902 pm.clearApplicationUserData(packageName, observer);
2903 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2904 Uri.fromParts("package", packageName, null));
2905 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002906 synchronized (this) {
2907 broadcastIntentLocked(null, null, intent,
2908 null, null, 0, null, null, null,
2909 false, false, MY_PID, Process.SYSTEM_UID);
2910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 } catch (RemoteException e) {
2912 }
2913 } finally {
2914 Binder.restoreCallingIdentity(callingId);
2915 }
2916 return true;
2917 }
2918
Dianne Hackborn03abb812010-01-04 18:43:19 -08002919 public void killBackgroundProcesses(final String packageName) {
2920 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2921 != PackageManager.PERMISSION_GRANTED &&
2922 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2923 != PackageManager.PERMISSION_GRANTED) {
2924 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 + Binder.getCallingPid()
2926 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002927 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002928 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 throw new SecurityException(msg);
2930 }
2931
2932 long callingId = Binder.clearCallingIdentity();
2933 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002934 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 int pkgUid = -1;
2936 synchronized(this) {
2937 try {
2938 pkgUid = pm.getPackageUid(packageName);
2939 } catch (RemoteException e) {
2940 }
2941 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002942 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 return;
2944 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002945 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002946 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002947 }
2948 } finally {
2949 Binder.restoreCallingIdentity(callingId);
2950 }
2951 }
2952
2953 public void forceStopPackage(final String packageName) {
2954 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2955 != PackageManager.PERMISSION_GRANTED) {
2956 String msg = "Permission Denial: forceStopPackage() from pid="
2957 + Binder.getCallingPid()
2958 + ", uid=" + Binder.getCallingUid()
2959 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002960 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002961 throw new SecurityException(msg);
2962 }
2963
2964 long callingId = Binder.clearCallingIdentity();
2965 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002966 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002967 int pkgUid = -1;
2968 synchronized(this) {
2969 try {
2970 pkgUid = pm.getPackageUid(packageName);
2971 } catch (RemoteException e) {
2972 }
2973 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002974 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002975 return;
2976 }
2977 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 }
2979 } finally {
2980 Binder.restoreCallingIdentity(callingId);
2981 }
2982 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002983
2984 /*
2985 * The pkg name and uid have to be specified.
2986 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
2987 */
2988 public void killApplicationWithUid(String pkg, int uid) {
2989 if (pkg == null) {
2990 return;
2991 }
2992 // Make sure the uid is valid.
2993 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002994 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002995 return;
2996 }
2997 int callerUid = Binder.getCallingUid();
2998 // Only the system server can kill an application
2999 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003000 // Post an aysnc message to kill the application
3001 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3002 msg.arg1 = uid;
3003 msg.arg2 = 0;
3004 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003005 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003006 } else {
3007 throw new SecurityException(callerUid + " cannot kill pkg: " +
3008 pkg);
3009 }
3010 }
3011
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003012 public void closeSystemDialogs(String reason) {
3013 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3014 if (reason != null) {
3015 intent.putExtra("reason", reason);
3016 }
3017
3018 final int uid = Binder.getCallingUid();
3019 final long origId = Binder.clearCallingIdentity();
3020 synchronized (this) {
3021 int i = mWatchers.beginBroadcast();
3022 while (i > 0) {
3023 i--;
3024 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3025 if (w != null) {
3026 try {
3027 w.closingSystemDialogs(reason);
3028 } catch (RemoteException e) {
3029 }
3030 }
3031 }
3032 mWatchers.finishBroadcast();
3033
Dianne Hackbornffa42482009-09-23 22:20:11 -07003034 mWindowManager.closeSystemDialogs(reason);
3035
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003036 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3037 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003038 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003039 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003040 Activity.RESULT_CANCELED, null, "close-sys");
3041 }
3042 }
3043
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003044 broadcastIntentLocked(null, null, intent, null,
3045 null, 0, null, null, null, false, false, -1, uid);
3046 }
3047 Binder.restoreCallingIdentity(origId);
3048 }
3049
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003050 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003051 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003052 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3053 for (int i=pids.length-1; i>=0; i--) {
3054 infos[i] = new Debug.MemoryInfo();
3055 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003056 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003057 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003058 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003059
3060 public void killApplicationProcess(String processName, int uid) {
3061 if (processName == null) {
3062 return;
3063 }
3064
3065 int callerUid = Binder.getCallingUid();
3066 // Only the system server can kill an application
3067 if (callerUid == Process.SYSTEM_UID) {
3068 synchronized (this) {
3069 ProcessRecord app = getProcessRecordLocked(processName, uid);
3070 if (app != null) {
3071 try {
3072 app.thread.scheduleSuicide();
3073 } catch (RemoteException e) {
3074 // If the other end already died, then our work here is done.
3075 }
3076 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003077 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003078 + processName + " / " + uid);
3079 }
3080 }
3081 } else {
3082 throw new SecurityException(callerUid + " cannot kill app process: " +
3083 processName);
3084 }
3085 }
3086
Dianne Hackborn03abb812010-01-04 18:43:19 -08003087 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003088 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3090 Uri.fromParts("package", packageName, null));
3091 intent.putExtra(Intent.EXTRA_UID, uid);
3092 broadcastIntentLocked(null, null, intent,
3093 null, null, 0, null, null, null,
3094 false, false, MY_PID, Process.SYSTEM_UID);
3095 }
3096
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003097 private final boolean killPackageProcessesLocked(String packageName, int uid,
3098 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003099 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100
Dianne Hackborn03abb812010-01-04 18:43:19 -08003101 // Remove all processes this package may have touched: all with the
3102 // same UID (except for the system or root user), and all whose name
3103 // matches the package name.
3104 final String procNamePrefix = packageName + ":";
3105 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3106 final int NA = apps.size();
3107 for (int ia=0; ia<NA; ia++) {
3108 ProcessRecord app = apps.valueAt(ia);
3109 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003110 if (doit) {
3111 procs.add(app);
3112 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003113 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3114 || app.processName.equals(packageName)
3115 || app.processName.startsWith(procNamePrefix)) {
3116 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003117 if (!doit) {
3118 return true;
3119 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 app.removed = true;
3121 procs.add(app);
3122 }
3123 }
3124 }
3125 }
3126
3127 int N = procs.size();
3128 for (int i=0; i<N; i++) {
3129 removeProcessLocked(procs.get(i), callerWillRestart);
3130 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003131 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003132 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003133
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003134 private final boolean forceStopPackageLocked(String name, int uid,
3135 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 int i, N;
3137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 if (uid < 0) {
3139 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003140 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003141 } catch (RemoteException e) {
3142 }
3143 }
3144
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003145 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003146 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003147
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003148 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3149 while (badApps.hasNext()) {
3150 SparseArray<Long> ba = badApps.next();
3151 if (ba.get(uid) != null) {
3152 badApps.remove();
3153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003154 }
3155 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003156
3157 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3158 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003160 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3161 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003163 if (!doit) {
3164 return true;
3165 }
3166 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003167 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003168 if (r.app != null) {
3169 r.app.removed = true;
3170 }
3171 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003172 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 }
3174 }
3175
3176 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3177 for (ServiceRecord service : mServices.values()) {
3178 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003179 if (!doit) {
3180 return true;
3181 }
3182 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003183 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 if (service.app != null) {
3185 service.app.removed = true;
3186 }
3187 service.app = null;
3188 services.add(service);
3189 }
3190 }
3191
3192 N = services.size();
3193 for (i=0; i<N; i++) {
3194 bringDownServiceLocked(services.get(i), true);
3195 }
3196
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003197 if (doit) {
3198 if (purgeCache) {
3199 AttributeCache ac = AttributeCache.instance();
3200 if (ac != null) {
3201 ac.removePackage(name);
3202 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003203 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003204 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003205 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003206
3207 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 }
3209
3210 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3211 final String name = app.processName;
3212 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003213 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 TAG, "Force removing process " + app + " (" + name
3215 + "/" + uid + ")");
3216
3217 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003218 if (mHeavyWeightProcess == app) {
3219 mHeavyWeightProcess = null;
3220 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 boolean needRestart = false;
3223 if (app.pid > 0 && app.pid != MY_PID) {
3224 int pid = app.pid;
3225 synchronized (mPidsSelfLocked) {
3226 mPidsSelfLocked.remove(pid);
3227 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3228 }
3229 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003230 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 Process.killProcess(pid);
3232
3233 if (app.persistent) {
3234 if (!callerWillRestart) {
3235 addAppLocked(app.info);
3236 } else {
3237 needRestart = true;
3238 }
3239 }
3240 } else {
3241 mRemovedProcesses.add(app);
3242 }
3243
3244 return needRestart;
3245 }
3246
3247 private final void processStartTimedOutLocked(ProcessRecord app) {
3248 final int pid = app.pid;
3249 boolean gone = false;
3250 synchronized (mPidsSelfLocked) {
3251 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3252 if (knownApp != null && knownApp.thread == null) {
3253 mPidsSelfLocked.remove(pid);
3254 gone = true;
3255 }
3256 }
3257
3258 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003259 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003260 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003261 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003263 if (mHeavyWeightProcess == app) {
3264 mHeavyWeightProcess = null;
3265 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3266 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003267 // Take care of any launching providers waiting for this process.
3268 checkAppInLaunchingProvidersLocked(app, true);
3269 // Take care of any services that are waiting for the process.
3270 for (int i=0; i<mPendingServices.size(); i++) {
3271 ServiceRecord sr = mPendingServices.get(i);
3272 if (app.info.uid == sr.appInfo.uid
3273 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003274 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003275 mPendingServices.remove(i);
3276 i--;
3277 bringDownServiceLocked(sr, true);
3278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003280 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003281 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003282 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003283 try {
3284 IBackupManager bm = IBackupManager.Stub.asInterface(
3285 ServiceManager.getService(Context.BACKUP_SERVICE));
3286 bm.agentDisconnected(app.info.packageName);
3287 } catch (RemoteException e) {
3288 // Can't happen; the backup manager is local
3289 }
3290 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003291 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003292 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003293 mPendingBroadcast = null;
3294 scheduleBroadcastsLocked();
3295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003297 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 }
3299 }
3300
3301 private final boolean attachApplicationLocked(IApplicationThread thread,
3302 int pid) {
3303
3304 // Find the application record that is being attached... either via
3305 // the pid if we are running in multiple processes, or just pull the
3306 // next app record if we are emulating process with anonymous threads.
3307 ProcessRecord app;
3308 if (pid != MY_PID && pid >= 0) {
3309 synchronized (mPidsSelfLocked) {
3310 app = mPidsSelfLocked.get(pid);
3311 }
3312 } else if (mStartingProcesses.size() > 0) {
3313 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003314 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 } else {
3316 app = null;
3317 }
3318
3319 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003320 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003322 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 if (pid > 0 && pid != MY_PID) {
3324 Process.killProcess(pid);
3325 } else {
3326 try {
3327 thread.scheduleExit();
3328 } catch (Exception e) {
3329 // Ignore exceptions.
3330 }
3331 }
3332 return false;
3333 }
3334
3335 // If this application record is still attached to a previous
3336 // process, clean it up now.
3337 if (app.thread != null) {
3338 handleAppDiedLocked(app, true);
3339 }
3340
3341 // Tell the process all about itself.
3342
Joe Onorato8a9b2202010-02-26 18:56:32 -08003343 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 TAG, "Binding process pid " + pid + " to record " + app);
3345
3346 String processName = app.processName;
3347 try {
3348 thread.asBinder().linkToDeath(new AppDeathRecipient(
3349 app, pid, thread), 0);
3350 } catch (RemoteException e) {
3351 app.resetPackageList();
3352 startProcessLocked(app, "link fail", processName);
3353 return false;
3354 }
3355
Doug Zongker2bec3d42009-12-04 12:52:44 -08003356 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357
3358 app.thread = thread;
3359 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003360 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3361 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 app.forcingToForeground = null;
3363 app.foregroundServices = false;
3364 app.debugging = false;
3365
3366 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3367
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003368 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3369 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003371 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003372 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003373 }
3374
Joe Onorato8a9b2202010-02-26 18:56:32 -08003375 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 TAG, "New app record " + app
3377 + " thread=" + thread.asBinder() + " pid=" + pid);
3378 try {
3379 int testMode = IApplicationThread.DEBUG_OFF;
3380 if (mDebugApp != null && mDebugApp.equals(processName)) {
3381 testMode = mWaitForDebugger
3382 ? IApplicationThread.DEBUG_WAIT
3383 : IApplicationThread.DEBUG_ON;
3384 app.debugging = true;
3385 if (mDebugTransient) {
3386 mDebugApp = mOrigDebugApp;
3387 mWaitForDebugger = mOrigWaitForDebugger;
3388 }
3389 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003390
Christopher Tate181fafa2009-05-14 11:12:14 -07003391 // If the app is being launched for restore or full backup, set it up specially
3392 boolean isRestrictedBackupMode = false;
3393 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3394 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3395 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3396 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003397
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003398 ensurePackageDexOpt(app.instrumentationInfo != null
3399 ? app.instrumentationInfo.packageName
3400 : app.info.packageName);
3401 if (app.instrumentationClass != null) {
3402 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003403 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003404 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003405 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003406 thread.bindApplication(processName, app.instrumentationInfo != null
3407 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 app.instrumentationClass, app.instrumentationProfileFile,
3409 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003410 isRestrictedBackupMode || !normalMode,
3411 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003412 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003413 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003414 } catch (Exception e) {
3415 // todo: Yikes! What should we do? For now we will try to
3416 // start another process, but that could easily get us in
3417 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003418 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419
3420 app.resetPackageList();
3421 startProcessLocked(app, "bind fail", processName);
3422 return false;
3423 }
3424
3425 // Remove this record from the list of starting applications.
3426 mPersistentStartingProcesses.remove(app);
3427 mProcessesOnHold.remove(app);
3428
3429 boolean badApp = false;
3430 boolean didSomething = false;
3431
3432 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003433 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003434 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3436 && processName.equals(hr.processName)) {
3437 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003438 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 didSomething = true;
3440 }
3441 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003442 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 + hr.intent.getComponent().flattenToShortString(), e);
3444 badApp = true;
3445 }
3446 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003447 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 }
3449 }
3450
3451 // Find any services that should be running in this process...
3452 if (!badApp && mPendingServices.size() > 0) {
3453 ServiceRecord sr = null;
3454 try {
3455 for (int i=0; i<mPendingServices.size(); i++) {
3456 sr = mPendingServices.get(i);
3457 if (app.info.uid != sr.appInfo.uid
3458 || !processName.equals(sr.processName)) {
3459 continue;
3460 }
3461
3462 mPendingServices.remove(i);
3463 i--;
3464 realStartServiceLocked(sr, app);
3465 didSomething = true;
3466 }
3467 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003468 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 + sr.shortName, e);
3470 badApp = true;
3471 }
3472 }
3473
3474 // Check if the next broadcast receiver is in this process...
3475 BroadcastRecord br = mPendingBroadcast;
3476 if (!badApp && br != null && br.curApp == app) {
3477 try {
3478 mPendingBroadcast = null;
3479 processCurBroadcastLocked(br, app);
3480 didSomething = true;
3481 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003482 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 + br.curComponent.flattenToShortString(), e);
3484 badApp = true;
3485 logBroadcastReceiverDiscard(br);
3486 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3487 br.resultExtras, br.resultAbort, true);
3488 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003489 // We need to reset the state if we fails to start the receiver.
3490 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 }
3492 }
3493
Christopher Tate181fafa2009-05-14 11:12:14 -07003494 // Check whether the next backup agent is in this process...
3495 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003497 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003498 try {
3499 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3500 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003501 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003502 e.printStackTrace();
3503 }
3504 }
3505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 if (badApp) {
3507 // todo: Also need to kill application to deal with all
3508 // kinds of exceptions.
3509 handleAppDiedLocked(app, false);
3510 return false;
3511 }
3512
3513 if (!didSomething) {
3514 updateOomAdjLocked();
3515 }
3516
3517 return true;
3518 }
3519
3520 public final void attachApplication(IApplicationThread thread) {
3521 synchronized (this) {
3522 int callingPid = Binder.getCallingPid();
3523 final long origId = Binder.clearCallingIdentity();
3524 attachApplicationLocked(thread, callingPid);
3525 Binder.restoreCallingIdentity(origId);
3526 }
3527 }
3528
Dianne Hackborne88846e2009-09-30 21:34:25 -07003529 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003531 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 Binder.restoreCallingIdentity(origId);
3533 }
3534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003536 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003537 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 mWindowManager.enableScreenAfterBoot();
3539 }
3540
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003541 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003542 IntentFilter pkgFilter = new IntentFilter();
3543 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3544 pkgFilter.addDataScheme("package");
3545 mContext.registerReceiver(new BroadcastReceiver() {
3546 @Override
3547 public void onReceive(Context context, Intent intent) {
3548 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3549 if (pkgs != null) {
3550 for (String pkg : pkgs) {
3551 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3552 setResultCode(Activity.RESULT_OK);
3553 return;
3554 }
3555 }
3556 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003557 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003558 }, pkgFilter);
3559
3560 synchronized (this) {
3561 // Ensure that any processes we had put on hold are now started
3562 // up.
3563 final int NP = mProcessesOnHold.size();
3564 if (NP > 0) {
3565 ArrayList<ProcessRecord> procs =
3566 new ArrayList<ProcessRecord>(mProcessesOnHold);
3567 for (int ip=0; ip<NP; ip++) {
3568 this.startProcessLocked(procs.get(ip), "on-hold", null);
3569 }
3570 }
3571
3572 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
3573 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003574 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003575 broadcastIntentLocked(null, null,
3576 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3577 null, null, 0, null, null,
3578 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3579 false, false, MY_PID, Process.SYSTEM_UID);
3580 }
3581 }
3582 }
3583
3584 final void ensureBootCompleted() {
3585 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003586 boolean enableScreen;
3587 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003588 booting = mBooting;
3589 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003590 enableScreen = !mBooted;
3591 mBooted = true;
3592 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003593
3594 if (booting) {
3595 finishBooting();
3596 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003597
3598 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003599 enableScreenAfterBoot();
3600 }
3601 }
3602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 public final void activityPaused(IBinder token, Bundle icicle) {
3604 // Refuse possible leaked file descriptors
3605 if (icicle != null && icicle.hasFileDescriptors()) {
3606 throw new IllegalArgumentException("File descriptors passed in Bundle");
3607 }
3608
3609 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003610 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 Binder.restoreCallingIdentity(origId);
3612 }
3613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 public final void activityStopped(IBinder token, Bitmap thumbnail,
3615 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003616 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 TAG, "Activity stopped: token=" + token);
3618
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003619 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620
3621 final long origId = Binder.clearCallingIdentity();
3622
3623 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003624 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003626 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 r.thumbnail = thumbnail;
3628 r.description = description;
3629 r.stopped = true;
3630 r.state = ActivityState.STOPPED;
3631 if (!r.finishing) {
3632 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003633 r.stack.destroyActivityLocked(r, true);
3634 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 }
3636 }
3637 }
3638 }
3639
3640 if (r != null) {
3641 sendPendingThumbnail(r, null, null, null, false);
3642 }
3643
3644 trimApplications();
3645
3646 Binder.restoreCallingIdentity(origId);
3647 }
3648
3649 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003650 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003651 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 }
3653
3654 public String getCallingPackage(IBinder token) {
3655 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003656 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003657 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 }
3659 }
3660
3661 public ComponentName getCallingActivity(IBinder token) {
3662 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003663 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 return r != null ? r.intent.getComponent() : null;
3665 }
3666 }
3667
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003668 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003669 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003671 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 if (r != null) {
3673 return r.resultTo;
3674 }
3675 }
3676 return null;
3677 }
3678
3679 public ComponentName getActivityClassForToken(IBinder token) {
3680 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003681 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003683 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 return r.intent.getComponent();
3685 }
3686 return null;
3687 }
3688 }
3689
3690 public String getPackageForToken(IBinder token) {
3691 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003692 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003694 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 return r.packageName;
3696 }
3697 return null;
3698 }
3699 }
3700
3701 public IIntentSender getIntentSender(int type,
3702 String packageName, IBinder token, String resultWho,
3703 int requestCode, Intent intent, String resolvedType, int flags) {
3704 // Refuse possible leaked file descriptors
3705 if (intent != null && intent.hasFileDescriptors() == true) {
3706 throw new IllegalArgumentException("File descriptors passed in Intent");
3707 }
3708
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003709 if (type == INTENT_SENDER_BROADCAST) {
3710 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3711 throw new IllegalArgumentException(
3712 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3713 }
3714 }
3715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 synchronized(this) {
3717 int callingUid = Binder.getCallingUid();
3718 try {
3719 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3720 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003721 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 .getPackageUid(packageName);
3723 if (uid != Binder.getCallingUid()) {
3724 String msg = "Permission Denial: getIntentSender() from pid="
3725 + Binder.getCallingPid()
3726 + ", uid=" + Binder.getCallingUid()
3727 + ", (need uid=" + uid + ")"
3728 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003729 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 throw new SecurityException(msg);
3731 }
3732 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003733
3734 return getIntentSenderLocked(type, packageName, callingUid,
3735 token, resultWho, requestCode, intent, resolvedType, flags);
3736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 } catch (RemoteException e) {
3738 throw new SecurityException(e);
3739 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003740 }
3741 }
3742
3743 IIntentSender getIntentSenderLocked(int type,
3744 String packageName, int callingUid, IBinder token, String resultWho,
3745 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003746 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003747 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003748 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003749 if (index < 0) {
3750 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003752 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003753 if (activity.finishing) {
3754 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003756 }
3757
3758 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3759 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3760 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3761 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3762 |PendingIntent.FLAG_UPDATE_CURRENT);
3763
3764 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3765 type, packageName, activity, resultWho,
3766 requestCode, intent, resolvedType, flags);
3767 WeakReference<PendingIntentRecord> ref;
3768 ref = mIntentSenderRecords.get(key);
3769 PendingIntentRecord rec = ref != null ? ref.get() : null;
3770 if (rec != null) {
3771 if (!cancelCurrent) {
3772 if (updateCurrent) {
3773 rec.key.requestIntent.replaceExtras(intent);
3774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 return rec;
3776 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003777 rec.canceled = true;
3778 mIntentSenderRecords.remove(key);
3779 }
3780 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 return rec;
3782 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003783 rec = new PendingIntentRecord(this, key, callingUid);
3784 mIntentSenderRecords.put(key, rec.ref);
3785 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3786 if (activity.pendingResults == null) {
3787 activity.pendingResults
3788 = new HashSet<WeakReference<PendingIntentRecord>>();
3789 }
3790 activity.pendingResults.add(rec.ref);
3791 }
3792 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 }
3794
3795 public void cancelIntentSender(IIntentSender sender) {
3796 if (!(sender instanceof PendingIntentRecord)) {
3797 return;
3798 }
3799 synchronized(this) {
3800 PendingIntentRecord rec = (PendingIntentRecord)sender;
3801 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003802 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 .getPackageUid(rec.key.packageName);
3804 if (uid != Binder.getCallingUid()) {
3805 String msg = "Permission Denial: cancelIntentSender() from pid="
3806 + Binder.getCallingPid()
3807 + ", uid=" + Binder.getCallingUid()
3808 + " is not allowed to cancel packges "
3809 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003810 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 throw new SecurityException(msg);
3812 }
3813 } catch (RemoteException e) {
3814 throw new SecurityException(e);
3815 }
3816 cancelIntentSenderLocked(rec, true);
3817 }
3818 }
3819
3820 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3821 rec.canceled = true;
3822 mIntentSenderRecords.remove(rec.key);
3823 if (cleanActivity && rec.key.activity != null) {
3824 rec.key.activity.pendingResults.remove(rec.ref);
3825 }
3826 }
3827
3828 public String getPackageForIntentSender(IIntentSender pendingResult) {
3829 if (!(pendingResult instanceof PendingIntentRecord)) {
3830 return null;
3831 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003832 try {
3833 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3834 return res.key.packageName;
3835 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 }
3837 return null;
3838 }
3839
3840 public void setProcessLimit(int max) {
3841 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3842 "setProcessLimit()");
3843 mProcessLimit = max;
3844 }
3845
3846 public int getProcessLimit() {
3847 return mProcessLimit;
3848 }
3849
3850 void foregroundTokenDied(ForegroundToken token) {
3851 synchronized (ActivityManagerService.this) {
3852 synchronized (mPidsSelfLocked) {
3853 ForegroundToken cur
3854 = mForegroundProcesses.get(token.pid);
3855 if (cur != token) {
3856 return;
3857 }
3858 mForegroundProcesses.remove(token.pid);
3859 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3860 if (pr == null) {
3861 return;
3862 }
3863 pr.forcingToForeground = null;
3864 pr.foregroundServices = false;
3865 }
3866 updateOomAdjLocked();
3867 }
3868 }
3869
3870 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3871 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3872 "setProcessForeground()");
3873 synchronized(this) {
3874 boolean changed = false;
3875
3876 synchronized (mPidsSelfLocked) {
3877 ProcessRecord pr = mPidsSelfLocked.get(pid);
3878 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003879 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 return;
3881 }
3882 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3883 if (oldToken != null) {
3884 oldToken.token.unlinkToDeath(oldToken, 0);
3885 mForegroundProcesses.remove(pid);
3886 pr.forcingToForeground = null;
3887 changed = true;
3888 }
3889 if (isForeground && token != null) {
3890 ForegroundToken newToken = new ForegroundToken() {
3891 public void binderDied() {
3892 foregroundTokenDied(this);
3893 }
3894 };
3895 newToken.pid = pid;
3896 newToken.token = token;
3897 try {
3898 token.linkToDeath(newToken, 0);
3899 mForegroundProcesses.put(pid, newToken);
3900 pr.forcingToForeground = token;
3901 changed = true;
3902 } catch (RemoteException e) {
3903 // If the process died while doing this, we will later
3904 // do the cleanup with the process death link.
3905 }
3906 }
3907 }
3908
3909 if (changed) {
3910 updateOomAdjLocked();
3911 }
3912 }
3913 }
3914
3915 // =========================================================
3916 // PERMISSIONS
3917 // =========================================================
3918
3919 static class PermissionController extends IPermissionController.Stub {
3920 ActivityManagerService mActivityManagerService;
3921 PermissionController(ActivityManagerService activityManagerService) {
3922 mActivityManagerService = activityManagerService;
3923 }
3924
3925 public boolean checkPermission(String permission, int pid, int uid) {
3926 return mActivityManagerService.checkPermission(permission, pid,
3927 uid) == PackageManager.PERMISSION_GRANTED;
3928 }
3929 }
3930
3931 /**
3932 * This can be called with or without the global lock held.
3933 */
3934 int checkComponentPermission(String permission, int pid, int uid,
3935 int reqUid) {
3936 // We might be performing an operation on behalf of an indirect binder
3937 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3938 // client identity accordingly before proceeding.
3939 Identity tlsIdentity = sCallerIdentity.get();
3940 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003941 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3943 uid = tlsIdentity.uid;
3944 pid = tlsIdentity.pid;
3945 }
3946
3947 // Root, system server and our own process get to do everything.
3948 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3949 !Process.supportsProcesses()) {
3950 return PackageManager.PERMISSION_GRANTED;
3951 }
3952 // If the target requires a specific UID, always fail for others.
3953 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003954 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 return PackageManager.PERMISSION_DENIED;
3956 }
3957 if (permission == null) {
3958 return PackageManager.PERMISSION_GRANTED;
3959 }
3960 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003961 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 .checkUidPermission(permission, uid);
3963 } catch (RemoteException e) {
3964 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003965 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 }
3967 return PackageManager.PERMISSION_DENIED;
3968 }
3969
3970 /**
3971 * As the only public entry point for permissions checking, this method
3972 * can enforce the semantic that requesting a check on a null global
3973 * permission is automatically denied. (Internally a null permission
3974 * string is used when calling {@link #checkComponentPermission} in cases
3975 * when only uid-based security is needed.)
3976 *
3977 * This can be called with or without the global lock held.
3978 */
3979 public int checkPermission(String permission, int pid, int uid) {
3980 if (permission == null) {
3981 return PackageManager.PERMISSION_DENIED;
3982 }
3983 return checkComponentPermission(permission, pid, uid, -1);
3984 }
3985
3986 /**
3987 * Binder IPC calls go through the public entry point.
3988 * This can be called with or without the global lock held.
3989 */
3990 int checkCallingPermission(String permission) {
3991 return checkPermission(permission,
3992 Binder.getCallingPid(),
3993 Binder.getCallingUid());
3994 }
3995
3996 /**
3997 * This can be called with or without the global lock held.
3998 */
3999 void enforceCallingPermission(String permission, String func) {
4000 if (checkCallingPermission(permission)
4001 == PackageManager.PERMISSION_GRANTED) {
4002 return;
4003 }
4004
4005 String msg = "Permission Denial: " + func + " from pid="
4006 + Binder.getCallingPid()
4007 + ", uid=" + Binder.getCallingUid()
4008 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004009 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 throw new SecurityException(msg);
4011 }
4012
4013 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4014 ProviderInfo pi, int uid, int modeFlags) {
4015 try {
4016 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4017 if ((pi.readPermission != null) &&
4018 (pm.checkUidPermission(pi.readPermission, uid)
4019 != PackageManager.PERMISSION_GRANTED)) {
4020 return false;
4021 }
4022 }
4023 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4024 if ((pi.writePermission != null) &&
4025 (pm.checkUidPermission(pi.writePermission, uid)
4026 != PackageManager.PERMISSION_GRANTED)) {
4027 return false;
4028 }
4029 }
4030 return true;
4031 } catch (RemoteException e) {
4032 return false;
4033 }
4034 }
4035
4036 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4037 int modeFlags) {
4038 // Root gets to do everything.
4039 if (uid == 0 || !Process.supportsProcesses()) {
4040 return true;
4041 }
4042 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4043 if (perms == null) return false;
4044 UriPermission perm = perms.get(uri);
4045 if (perm == null) return false;
4046 return (modeFlags&perm.modeFlags) == modeFlags;
4047 }
4048
4049 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4050 // Another redirected-binder-call permissions check as in
4051 // {@link checkComponentPermission}.
4052 Identity tlsIdentity = sCallerIdentity.get();
4053 if (tlsIdentity != null) {
4054 uid = tlsIdentity.uid;
4055 pid = tlsIdentity.pid;
4056 }
4057
4058 // Our own process gets to do everything.
4059 if (pid == MY_PID) {
4060 return PackageManager.PERMISSION_GRANTED;
4061 }
4062 synchronized(this) {
4063 return checkUriPermissionLocked(uri, uid, modeFlags)
4064 ? PackageManager.PERMISSION_GRANTED
4065 : PackageManager.PERMISSION_DENIED;
4066 }
4067 }
4068
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004069 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004070 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4072 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4073 if (modeFlags == 0) {
4074 return;
4075 }
4076
Joe Onorato8a9b2202010-02-26 18:56:32 -08004077 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004078 "Requested grant " + targetPkg + " permission to " + uri);
4079
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004080 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081
4082 // If this is not a content: uri, we can't do anything with it.
4083 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004084 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004085 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 return;
4087 }
4088
4089 String name = uri.getAuthority();
4090 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004091 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 if (cpr != null) {
4093 pi = cpr.info;
4094 } else {
4095 try {
4096 pi = pm.resolveContentProvider(name,
4097 PackageManager.GET_URI_PERMISSION_PATTERNS);
4098 } catch (RemoteException ex) {
4099 }
4100 }
4101 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004102 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 return;
4104 }
4105
4106 int targetUid;
4107 try {
4108 targetUid = pm.getPackageUid(targetPkg);
4109 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004110 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004111 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004112 return;
4113 }
4114 } catch (RemoteException ex) {
4115 return;
4116 }
4117
4118 // First... does the target actually need this permission?
4119 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4120 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004121 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004122 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 return;
4124 }
4125
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004126 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 if (!pi.grantUriPermissions) {
4128 throw new SecurityException("Provider " + pi.packageName
4129 + "/" + pi.name
4130 + " does not allow granting of Uri permissions (uri "
4131 + uri + ")");
4132 }
4133 if (pi.uriPermissionPatterns != null) {
4134 final int N = pi.uriPermissionPatterns.length;
4135 boolean allowed = false;
4136 for (int i=0; i<N; i++) {
4137 if (pi.uriPermissionPatterns[i] != null
4138 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4139 allowed = true;
4140 break;
4141 }
4142 }
4143 if (!allowed) {
4144 throw new SecurityException("Provider " + pi.packageName
4145 + "/" + pi.name
4146 + " does not allow granting of permission to path of Uri "
4147 + uri);
4148 }
4149 }
4150
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004151 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 // this uri?
4153 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4154 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4155 throw new SecurityException("Uid " + callingUid
4156 + " does not have permission to uri " + uri);
4157 }
4158 }
4159
4160 // Okay! So here we are: the caller has the assumed permission
4161 // to the uri, and the target doesn't. Let's now give this to
4162 // the target.
4163
Joe Onorato8a9b2202010-02-26 18:56:32 -08004164 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004165 "Granting " + targetPkg + " permission to " + uri);
4166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 HashMap<Uri, UriPermission> targetUris
4168 = mGrantedUriPermissions.get(targetUid);
4169 if (targetUris == null) {
4170 targetUris = new HashMap<Uri, UriPermission>();
4171 mGrantedUriPermissions.put(targetUid, targetUris);
4172 }
4173
4174 UriPermission perm = targetUris.get(uri);
4175 if (perm == null) {
4176 perm = new UriPermission(targetUid, uri);
4177 targetUris.put(uri, perm);
4178
4179 }
4180 perm.modeFlags |= modeFlags;
4181 if (activity == null) {
4182 perm.globalModeFlags |= modeFlags;
4183 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4184 perm.readActivities.add(activity);
4185 if (activity.readUriPermissions == null) {
4186 activity.readUriPermissions = new HashSet<UriPermission>();
4187 }
4188 activity.readUriPermissions.add(perm);
4189 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4190 perm.writeActivities.add(activity);
4191 if (activity.writeUriPermissions == null) {
4192 activity.writeUriPermissions = new HashSet<UriPermission>();
4193 }
4194 activity.writeUriPermissions.add(perm);
4195 }
4196 }
4197
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004198 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004199 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 if (intent == null) {
4201 return;
4202 }
4203 Uri data = intent.getData();
4204 if (data == null) {
4205 return;
4206 }
4207 grantUriPermissionLocked(callingUid, targetPkg, data,
4208 intent.getFlags(), activity);
4209 }
4210
4211 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4212 Uri uri, int modeFlags) {
4213 synchronized(this) {
4214 final ProcessRecord r = getRecordForAppLocked(caller);
4215 if (r == null) {
4216 throw new SecurityException("Unable to find app for caller "
4217 + caller
4218 + " when granting permission to uri " + uri);
4219 }
4220 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004221 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 return;
4223 }
4224 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004225 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 return;
4227 }
4228
4229 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4230 null);
4231 }
4232 }
4233
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004234 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4236 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4237 HashMap<Uri, UriPermission> perms
4238 = mGrantedUriPermissions.get(perm.uid);
4239 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004240 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004241 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 perms.remove(perm.uri);
4243 if (perms.size() == 0) {
4244 mGrantedUriPermissions.remove(perm.uid);
4245 }
4246 }
4247 }
4248 }
4249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4251 int modeFlags) {
4252 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4253 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4254 if (modeFlags == 0) {
4255 return;
4256 }
4257
Joe Onorato8a9b2202010-02-26 18:56:32 -08004258 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004259 "Revoking all granted permissions to " + uri);
4260
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004261 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262
4263 final String authority = uri.getAuthority();
4264 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004265 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 if (cpr != null) {
4267 pi = cpr.info;
4268 } else {
4269 try {
4270 pi = pm.resolveContentProvider(authority,
4271 PackageManager.GET_URI_PERMISSION_PATTERNS);
4272 } catch (RemoteException ex) {
4273 }
4274 }
4275 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004276 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 return;
4278 }
4279
4280 // Does the caller have this permission on the URI?
4281 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4282 // Right now, if you are not the original owner of the permission,
4283 // you are not allowed to revoke it.
4284 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4285 throw new SecurityException("Uid " + callingUid
4286 + " does not have permission to uri " + uri);
4287 //}
4288 }
4289
4290 // Go through all of the permissions and remove any that match.
4291 final List<String> SEGMENTS = uri.getPathSegments();
4292 if (SEGMENTS != null) {
4293 final int NS = SEGMENTS.size();
4294 int N = mGrantedUriPermissions.size();
4295 for (int i=0; i<N; i++) {
4296 HashMap<Uri, UriPermission> perms
4297 = mGrantedUriPermissions.valueAt(i);
4298 Iterator<UriPermission> it = perms.values().iterator();
4299 toploop:
4300 while (it.hasNext()) {
4301 UriPermission perm = it.next();
4302 Uri targetUri = perm.uri;
4303 if (!authority.equals(targetUri.getAuthority())) {
4304 continue;
4305 }
4306 List<String> targetSegments = targetUri.getPathSegments();
4307 if (targetSegments == null) {
4308 continue;
4309 }
4310 if (targetSegments.size() < NS) {
4311 continue;
4312 }
4313 for (int j=0; j<NS; j++) {
4314 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4315 continue toploop;
4316 }
4317 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004318 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004319 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 perm.clearModes(modeFlags);
4321 if (perm.modeFlags == 0) {
4322 it.remove();
4323 }
4324 }
4325 if (perms.size() == 0) {
4326 mGrantedUriPermissions.remove(
4327 mGrantedUriPermissions.keyAt(i));
4328 N--;
4329 i--;
4330 }
4331 }
4332 }
4333 }
4334
4335 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4336 int modeFlags) {
4337 synchronized(this) {
4338 final ProcessRecord r = getRecordForAppLocked(caller);
4339 if (r == null) {
4340 throw new SecurityException("Unable to find app for caller "
4341 + caller
4342 + " when revoking permission to uri " + uri);
4343 }
4344 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004345 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 return;
4347 }
4348
4349 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4350 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4351 if (modeFlags == 0) {
4352 return;
4353 }
4354
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004355 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356
4357 final String authority = uri.getAuthority();
4358 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004359 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 if (cpr != null) {
4361 pi = cpr.info;
4362 } else {
4363 try {
4364 pi = pm.resolveContentProvider(authority,
4365 PackageManager.GET_URI_PERMISSION_PATTERNS);
4366 } catch (RemoteException ex) {
4367 }
4368 }
4369 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004370 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 return;
4372 }
4373
4374 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4375 }
4376 }
4377
4378 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4379 synchronized (this) {
4380 ProcessRecord app =
4381 who != null ? getRecordForAppLocked(who) : null;
4382 if (app == null) return;
4383
4384 Message msg = Message.obtain();
4385 msg.what = WAIT_FOR_DEBUGGER_MSG;
4386 msg.obj = app;
4387 msg.arg1 = waiting ? 1 : 0;
4388 mHandler.sendMessage(msg);
4389 }
4390 }
4391
4392 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4393 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004394 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004396 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398
4399 // =========================================================
4400 // TASK MANAGEMENT
4401 // =========================================================
4402
4403 public List getTasks(int maxNum, int flags,
4404 IThumbnailReceiver receiver) {
4405 ArrayList list = new ArrayList();
4406
4407 PendingThumbnailsRecord pending = null;
4408 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004409 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410
4411 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004412 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4414 + ", receiver=" + receiver);
4415
4416 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4417 != PackageManager.PERMISSION_GRANTED) {
4418 if (receiver != null) {
4419 // If the caller wants to wait for pending thumbnails,
4420 // it ain't gonna get them.
4421 try {
4422 receiver.finished();
4423 } catch (RemoteException ex) {
4424 }
4425 }
4426 String msg = "Permission Denial: getTasks() from pid="
4427 + Binder.getCallingPid()
4428 + ", uid=" + Binder.getCallingUid()
4429 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004430 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 throw new SecurityException(msg);
4432 }
4433
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004434 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004435 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004436 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004437 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 CharSequence topDescription = null;
4439 TaskRecord curTask = null;
4440 int numActivities = 0;
4441 int numRunning = 0;
4442 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004443 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004445 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446
4447 // Initialize state for next task if needed.
4448 if (top == null ||
4449 (top.state == ActivityState.INITIALIZING
4450 && top.task == r.task)) {
4451 top = r;
4452 topDescription = r.description;
4453 curTask = r.task;
4454 numActivities = numRunning = 0;
4455 }
4456
4457 // Add 'r' into the current task.
4458 numActivities++;
4459 if (r.app != null && r.app.thread != null) {
4460 numRunning++;
4461 }
4462 if (topDescription == null) {
4463 topDescription = r.description;
4464 }
4465
Joe Onorato8a9b2202010-02-26 18:56:32 -08004466 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 TAG, r.intent.getComponent().flattenToShortString()
4468 + ": task=" + r.task);
4469
4470 // If the next one is a different task, generate a new
4471 // TaskInfo entry for what we have.
4472 if (next == null || next.task != curTask) {
4473 ActivityManager.RunningTaskInfo ci
4474 = new ActivityManager.RunningTaskInfo();
4475 ci.id = curTask.taskId;
4476 ci.baseActivity = r.intent.getComponent();
4477 ci.topActivity = top.intent.getComponent();
4478 ci.thumbnail = top.thumbnail;
4479 ci.description = topDescription;
4480 ci.numActivities = numActivities;
4481 ci.numRunning = numRunning;
4482 //System.out.println(
4483 // "#" + maxNum + ": " + " descr=" + ci.description);
4484 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004485 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 TAG, "State=" + top.state + "Idle=" + top.idle
4487 + " app=" + top.app
4488 + " thr=" + (top.app != null ? top.app.thread : null));
4489 if (top.state == ActivityState.RESUMED
4490 || top.state == ActivityState.PAUSING) {
4491 if (top.idle && top.app != null
4492 && top.app.thread != null) {
4493 topRecord = top;
4494 topThumbnail = top.app.thread;
4495 } else {
4496 top.thumbnailNeeded = true;
4497 }
4498 }
4499 if (pending == null) {
4500 pending = new PendingThumbnailsRecord(receiver);
4501 }
4502 pending.pendingRecords.add(top);
4503 }
4504 list.add(ci);
4505 maxNum--;
4506 top = null;
4507 }
4508 }
4509
4510 if (pending != null) {
4511 mPendingThumbnails.add(pending);
4512 }
4513 }
4514
Joe Onorato8a9b2202010-02-26 18:56:32 -08004515 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516
4517 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004518 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 try {
4520 topThumbnail.requestThumbnail(topRecord);
4521 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004522 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 sendPendingThumbnail(null, topRecord, null, null, true);
4524 }
4525 }
4526
4527 if (pending == null && receiver != null) {
4528 // In this case all thumbnails were available and the client
4529 // is being asked to be told when the remaining ones come in...
4530 // which is unusually, since the top-most currently running
4531 // activity should never have a canned thumbnail! Oh well.
4532 try {
4533 receiver.finished();
4534 } catch (RemoteException ex) {
4535 }
4536 }
4537
4538 return list;
4539 }
4540
4541 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4542 int flags) {
4543 synchronized (this) {
4544 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4545 "getRecentTasks()");
4546
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004547 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 final int N = mRecentTasks.size();
4550 ArrayList<ActivityManager.RecentTaskInfo> res
4551 = new ArrayList<ActivityManager.RecentTaskInfo>(
4552 maxNum < N ? maxNum : N);
4553 for (int i=0; i<N && maxNum > 0; i++) {
4554 TaskRecord tr = mRecentTasks.get(i);
4555 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4556 || (tr.intent == null)
4557 || ((tr.intent.getFlags()
4558 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4559 ActivityManager.RecentTaskInfo rti
4560 = new ActivityManager.RecentTaskInfo();
4561 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4562 rti.baseIntent = new Intent(
4563 tr.intent != null ? tr.intent : tr.affinityIntent);
4564 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004565
4566 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4567 // Check whether this activity is currently available.
4568 try {
4569 if (rti.origActivity != null) {
4570 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4571 continue;
4572 }
4573 } else if (rti.baseIntent != null) {
4574 if (pm.queryIntentActivities(rti.baseIntent,
4575 null, 0) == null) {
4576 continue;
4577 }
4578 }
4579 } catch (RemoteException e) {
4580 // Will never happen.
4581 }
4582 }
4583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 res.add(rti);
4585 maxNum--;
4586 }
4587 }
4588 return res;
4589 }
4590 }
4591
4592 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4593 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004594 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 TaskRecord jt = startTask;
4596
4597 // First look backwards
4598 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004599 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 if (r.task != jt) {
4601 jt = r.task;
4602 if (affinity.equals(jt.affinity)) {
4603 return j;
4604 }
4605 }
4606 }
4607
4608 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004609 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 jt = startTask;
4611 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004612 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 if (r.task != jt) {
4614 if (affinity.equals(jt.affinity)) {
4615 return j;
4616 }
4617 jt = r.task;
4618 }
4619 }
4620
4621 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004622 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 return N-1;
4624 }
4625
4626 return -1;
4627 }
4628
4629 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004630 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 */
4632 public void moveTaskToFront(int task) {
4633 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4634 "moveTaskToFront()");
4635
4636 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004637 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4638 Binder.getCallingUid(), "Task to front")) {
4639 return;
4640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 final long origId = Binder.clearCallingIdentity();
4642 try {
4643 int N = mRecentTasks.size();
4644 for (int i=0; i<N; i++) {
4645 TaskRecord tr = mRecentTasks.get(i);
4646 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004647 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004648 return;
4649 }
4650 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004651 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4652 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004654 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 return;
4656 }
4657 }
4658 } finally {
4659 Binder.restoreCallingIdentity(origId);
4660 }
4661 }
4662 }
4663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 public void moveTaskToBack(int task) {
4665 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4666 "moveTaskToBack()");
4667
4668 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004669 if (mMainStack.mResumedActivity != null
4670 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004671 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4672 Binder.getCallingUid(), "Task to back")) {
4673 return;
4674 }
4675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004677 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 Binder.restoreCallingIdentity(origId);
4679 }
4680 }
4681
4682 /**
4683 * Moves an activity, and all of the other activities within the same task, to the bottom
4684 * of the history stack. The activity's order within the task is unchanged.
4685 *
4686 * @param token A reference to the activity we wish to move
4687 * @param nonRoot If false then this only works if the activity is the root
4688 * of a task; if true it will work for any activity in a task.
4689 * @return Returns true if the move completed, false if not.
4690 */
4691 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4692 synchronized(this) {
4693 final long origId = Binder.clearCallingIdentity();
4694 int taskId = getTaskForActivityLocked(token, !nonRoot);
4695 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004696 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 }
4698 Binder.restoreCallingIdentity(origId);
4699 }
4700 return false;
4701 }
4702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 public void moveTaskBackwards(int task) {
4704 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4705 "moveTaskBackwards()");
4706
4707 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004708 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4709 Binder.getCallingUid(), "Task backwards")) {
4710 return;
4711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 final long origId = Binder.clearCallingIdentity();
4713 moveTaskBackwardsLocked(task);
4714 Binder.restoreCallingIdentity(origId);
4715 }
4716 }
4717
4718 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004719 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 }
4721
4722 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4723 synchronized(this) {
4724 return getTaskForActivityLocked(token, onlyRoot);
4725 }
4726 }
4727
4728 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004729 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 TaskRecord lastTask = null;
4731 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004732 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 if (r == token) {
4734 if (!onlyRoot || lastTask != r.task) {
4735 return r.task.taskId;
4736 }
4737 return -1;
4738 }
4739 lastTask = r.task;
4740 }
4741
4742 return -1;
4743 }
4744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 public void finishOtherInstances(IBinder token, ComponentName className) {
4746 synchronized(this) {
4747 final long origId = Binder.clearCallingIdentity();
4748
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004749 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 TaskRecord lastTask = null;
4751 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004752 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753 if (r.realActivity.equals(className)
4754 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004755 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 null, "others")) {
4757 i--;
4758 N--;
4759 }
4760 }
4761 lastTask = r.task;
4762 }
4763
4764 Binder.restoreCallingIdentity(origId);
4765 }
4766 }
4767
4768 // =========================================================
4769 // THUMBNAILS
4770 // =========================================================
4771
4772 public void reportThumbnail(IBinder token,
4773 Bitmap thumbnail, CharSequence description) {
4774 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4775 final long origId = Binder.clearCallingIdentity();
4776 sendPendingThumbnail(null, token, thumbnail, description, true);
4777 Binder.restoreCallingIdentity(origId);
4778 }
4779
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004780 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004781 Bitmap thumbnail, CharSequence description, boolean always) {
4782 TaskRecord task = null;
4783 ArrayList receivers = null;
4784
4785 //System.out.println("Send pending thumbnail: " + r);
4786
4787 synchronized(this) {
4788 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004789 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 if (index < 0) {
4791 return;
4792 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004793 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 }
4795 if (thumbnail == null) {
4796 thumbnail = r.thumbnail;
4797 description = r.description;
4798 }
4799 if (thumbnail == null && !always) {
4800 // If there is no thumbnail, and this entry is not actually
4801 // going away, then abort for now and pick up the next
4802 // thumbnail we get.
4803 return;
4804 }
4805 task = r.task;
4806
4807 int N = mPendingThumbnails.size();
4808 int i=0;
4809 while (i<N) {
4810 PendingThumbnailsRecord pr =
4811 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4812 //System.out.println("Looking in " + pr.pendingRecords);
4813 if (pr.pendingRecords.remove(r)) {
4814 if (receivers == null) {
4815 receivers = new ArrayList();
4816 }
4817 receivers.add(pr);
4818 if (pr.pendingRecords.size() == 0) {
4819 pr.finished = true;
4820 mPendingThumbnails.remove(i);
4821 N--;
4822 continue;
4823 }
4824 }
4825 i++;
4826 }
4827 }
4828
4829 if (receivers != null) {
4830 final int N = receivers.size();
4831 for (int i=0; i<N; i++) {
4832 try {
4833 PendingThumbnailsRecord pr =
4834 (PendingThumbnailsRecord)receivers.get(i);
4835 pr.receiver.newThumbnail(
4836 task != null ? task.taskId : -1, thumbnail, description);
4837 if (pr.finished) {
4838 pr.receiver.finished();
4839 }
4840 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004841 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004842 }
4843 }
4844 }
4845 }
4846
4847 // =========================================================
4848 // CONTENT PROVIDERS
4849 // =========================================================
4850
4851 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4852 List providers = null;
4853 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004854 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004856 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 } catch (RemoteException ex) {
4858 }
4859 if (providers != null) {
4860 final int N = providers.size();
4861 for (int i=0; i<N; i++) {
4862 ProviderInfo cpi =
4863 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004864 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 if (cpr == null) {
4866 cpr = new ContentProviderRecord(cpi, app.info);
4867 mProvidersByClass.put(cpi.name, cpr);
4868 }
4869 app.pubProviders.put(cpi.name, cpr);
4870 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004871 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 }
4873 }
4874 return providers;
4875 }
4876
4877 private final String checkContentProviderPermissionLocked(
4878 ProviderInfo cpi, ProcessRecord r, int mode) {
4879 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4880 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4881 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4882 cpi.exported ? -1 : cpi.applicationInfo.uid)
4883 == PackageManager.PERMISSION_GRANTED
4884 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4885 return null;
4886 }
4887 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4888 cpi.exported ? -1 : cpi.applicationInfo.uid)
4889 == PackageManager.PERMISSION_GRANTED) {
4890 return null;
4891 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004892
4893 PathPermission[] pps = cpi.pathPermissions;
4894 if (pps != null) {
4895 int i = pps.length;
4896 while (i > 0) {
4897 i--;
4898 PathPermission pp = pps[i];
4899 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4900 cpi.exported ? -1 : cpi.applicationInfo.uid)
4901 == PackageManager.PERMISSION_GRANTED
4902 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4903 return null;
4904 }
4905 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4906 cpi.exported ? -1 : cpi.applicationInfo.uid)
4907 == PackageManager.PERMISSION_GRANTED) {
4908 return null;
4909 }
4910 }
4911 }
4912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 String msg = "Permission Denial: opening provider " + cpi.name
4914 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4915 + ", uid=" + callingUid + ") requires "
4916 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004917 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 return msg;
4919 }
4920
4921 private final ContentProviderHolder getContentProviderImpl(
4922 IApplicationThread caller, String name) {
4923 ContentProviderRecord cpr;
4924 ProviderInfo cpi = null;
4925
4926 synchronized(this) {
4927 ProcessRecord r = null;
4928 if (caller != null) {
4929 r = getRecordForAppLocked(caller);
4930 if (r == null) {
4931 throw new SecurityException(
4932 "Unable to find app for caller " + caller
4933 + " (pid=" + Binder.getCallingPid()
4934 + ") when getting content provider " + name);
4935 }
4936 }
4937
4938 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004939 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 if (cpr != null) {
4941 cpi = cpr.info;
4942 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4943 return new ContentProviderHolder(cpi,
4944 cpi.readPermission != null
4945 ? cpi.readPermission : cpi.writePermission);
4946 }
4947
4948 if (r != null && cpr.canRunHere(r)) {
4949 // This provider has been published or is in the process
4950 // of being published... but it is also allowed to run
4951 // in the caller's process, so don't make a connection
4952 // and just let the caller instantiate its own instance.
4953 if (cpr.provider != null) {
4954 // don't give caller the provider object, it needs
4955 // to make its own.
4956 cpr = new ContentProviderRecord(cpr);
4957 }
4958 return cpr;
4959 }
4960
4961 final long origId = Binder.clearCallingIdentity();
4962
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004963 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 // return it right away.
4965 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004966 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004967 "Adding provider requested by "
4968 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004969 + cpr.info.processName);
4970 Integer cnt = r.conProviders.get(cpr);
4971 if (cnt == null) {
4972 r.conProviders.put(cpr, new Integer(1));
4973 } else {
4974 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
4975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004977 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
4978 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07004979 // make sure to count it as being accessed and thus
4980 // back up on the LRU list. This is good because
4981 // content providers are often expensive to start.
4982 updateLruProcessLocked(cpr.app, false, true);
4983 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07004984 } else {
4985 cpr.externals++;
4986 }
4987
4988 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 updateOomAdjLocked(cpr.app);
4990 }
4991
4992 Binder.restoreCallingIdentity(origId);
4993
4994 } else {
4995 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004996 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07004997 resolveContentProvider(name,
4998 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 } catch (RemoteException ex) {
5000 }
5001 if (cpi == null) {
5002 return null;
5003 }
5004
5005 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
5006 return new ContentProviderHolder(cpi,
5007 cpi.readPermission != null
5008 ? cpi.readPermission : cpi.writePermission);
5009 }
5010
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005011 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5012 && !cpi.processName.equals("system")) {
5013 // If this content provider does not run in the system
5014 // process, and the system is not yet ready to run other
5015 // processes, then fail fast instead of hanging.
5016 throw new IllegalArgumentException(
5017 "Attempt to launch content provider before system ready");
5018 }
5019
Dianne Hackborn860755f2010-06-03 18:47:52 -07005020 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 final boolean firstClass = cpr == null;
5022 if (firstClass) {
5023 try {
5024 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005025 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 getApplicationInfo(
5027 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005028 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005030 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 + cpi.name);
5032 return null;
5033 }
5034 cpr = new ContentProviderRecord(cpi, ai);
5035 } catch (RemoteException ex) {
5036 // pm is in same process, this will never happen.
5037 }
5038 }
5039
5040 if (r != null && cpr.canRunHere(r)) {
5041 // If this is a multiprocess provider, then just return its
5042 // info and allow the caller to instantiate it. Only do
5043 // this if the provider is the same user as the caller's
5044 // process, or can run as root (so can be in any process).
5045 return cpr;
5046 }
5047
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005048 if (DEBUG_PROVIDER) {
5049 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005050 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005051 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 }
5053
5054 // This is single process, and our app is now connecting to it.
5055 // See if we are already in the process of launching this
5056 // provider.
5057 final int N = mLaunchingProviders.size();
5058 int i;
5059 for (i=0; i<N; i++) {
5060 if (mLaunchingProviders.get(i) == cpr) {
5061 break;
5062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 }
5064
5065 // If the provider is not already being launched, then get it
5066 // started.
5067 if (i >= N) {
5068 final long origId = Binder.clearCallingIdentity();
5069 ProcessRecord proc = startProcessLocked(cpi.processName,
5070 cpr.appInfo, false, 0, "content provider",
5071 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005072 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005073 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005074 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 + cpi.applicationInfo.packageName + "/"
5076 + cpi.applicationInfo.uid + " for provider "
5077 + name + ": process is bad");
5078 return null;
5079 }
5080 cpr.launchingApp = proc;
5081 mLaunchingProviders.add(cpr);
5082 Binder.restoreCallingIdentity(origId);
5083 }
5084
5085 // Make sure the provider is published (the same provider class
5086 // may be published under multiple names).
5087 if (firstClass) {
5088 mProvidersByClass.put(cpi.name, cpr);
5089 }
5090 mProvidersByName.put(name, cpr);
5091
5092 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005093 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005094 "Adding provider requested by "
5095 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005096 + cpr.info.processName);
5097 Integer cnt = r.conProviders.get(cpr);
5098 if (cnt == null) {
5099 r.conProviders.put(cpr, new Integer(1));
5100 } else {
5101 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 cpr.clients.add(r);
5104 } else {
5105 cpr.externals++;
5106 }
5107 }
5108 }
5109
5110 // Wait for the provider to be published...
5111 synchronized (cpr) {
5112 while (cpr.provider == null) {
5113 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005114 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 + cpi.applicationInfo.packageName + "/"
5116 + cpi.applicationInfo.uid + " for provider "
5117 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005118 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 cpi.applicationInfo.packageName,
5120 cpi.applicationInfo.uid, name);
5121 return null;
5122 }
5123 try {
5124 cpr.wait();
5125 } catch (InterruptedException ex) {
5126 }
5127 }
5128 }
5129 return cpr;
5130 }
5131
5132 public final ContentProviderHolder getContentProvider(
5133 IApplicationThread caller, String name) {
5134 if (caller == null) {
5135 String msg = "null IApplicationThread when getting content provider "
5136 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005137 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 throw new SecurityException(msg);
5139 }
5140
5141 return getContentProviderImpl(caller, name);
5142 }
5143
5144 private ContentProviderHolder getContentProviderExternal(String name) {
5145 return getContentProviderImpl(null, name);
5146 }
5147
5148 /**
5149 * Drop a content provider from a ProcessRecord's bookkeeping
5150 * @param cpr
5151 */
5152 public void removeContentProvider(IApplicationThread caller, String name) {
5153 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005154 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005156 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005157 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005158 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 return;
5160 }
5161 final ProcessRecord r = getRecordForAppLocked(caller);
5162 if (r == null) {
5163 throw new SecurityException(
5164 "Unable to find app for caller " + caller +
5165 " when removing content provider " + name);
5166 }
5167 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005168 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005169 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005170 + r.info.processName + " from process "
5171 + localCpr.appInfo.processName);
5172 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005174 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005175 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 return;
5177 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005178 Integer cnt = r.conProviders.get(localCpr);
5179 if (cnt == null || cnt.intValue() <= 1) {
5180 localCpr.clients.remove(r);
5181 r.conProviders.remove(localCpr);
5182 } else {
5183 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 }
5186 updateOomAdjLocked();
5187 }
5188 }
5189
5190 private void removeContentProviderExternal(String name) {
5191 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005192 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 if(cpr == null) {
5194 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005195 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 return;
5197 }
5198
5199 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005200 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 localCpr.externals--;
5202 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005203 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 }
5205 updateOomAdjLocked();
5206 }
5207 }
5208
5209 public final void publishContentProviders(IApplicationThread caller,
5210 List<ContentProviderHolder> providers) {
5211 if (providers == null) {
5212 return;
5213 }
5214
5215 synchronized(this) {
5216 final ProcessRecord r = getRecordForAppLocked(caller);
5217 if (r == null) {
5218 throw new SecurityException(
5219 "Unable to find app for caller " + caller
5220 + " (pid=" + Binder.getCallingPid()
5221 + ") when publishing content providers");
5222 }
5223
5224 final long origId = Binder.clearCallingIdentity();
5225
5226 final int N = providers.size();
5227 for (int i=0; i<N; i++) {
5228 ContentProviderHolder src = providers.get(i);
5229 if (src == null || src.info == null || src.provider == null) {
5230 continue;
5231 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005232 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 if (dst != null) {
5234 mProvidersByClass.put(dst.info.name, dst);
5235 String names[] = dst.info.authority.split(";");
5236 for (int j = 0; j < names.length; j++) {
5237 mProvidersByName.put(names[j], dst);
5238 }
5239
5240 int NL = mLaunchingProviders.size();
5241 int j;
5242 for (j=0; j<NL; j++) {
5243 if (mLaunchingProviders.get(j) == dst) {
5244 mLaunchingProviders.remove(j);
5245 j--;
5246 NL--;
5247 }
5248 }
5249 synchronized (dst) {
5250 dst.provider = src.provider;
5251 dst.app = r;
5252 dst.notifyAll();
5253 }
5254 updateOomAdjLocked(r);
5255 }
5256 }
5257
5258 Binder.restoreCallingIdentity(origId);
5259 }
5260 }
5261
5262 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005263 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005264 synchronized (mSelf) {
5265 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5266 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005267 if (providers != null) {
5268 for (int i=providers.size()-1; i>=0; i--) {
5269 ProviderInfo pi = (ProviderInfo)providers.get(i);
5270 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5271 Slog.w(TAG, "Not installing system proc provider " + pi.name
5272 + ": not system .apk");
5273 providers.remove(i);
5274 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005275 }
5276 }
5277 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005278 if (providers != null) {
5279 mSystemThread.installSystemProviders(providers);
5280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 }
5282
5283 // =========================================================
5284 // GLOBAL MANAGEMENT
5285 // =========================================================
5286
5287 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5288 ApplicationInfo info, String customProcess) {
5289 String proc = customProcess != null ? customProcess : info.processName;
5290 BatteryStatsImpl.Uid.Proc ps = null;
5291 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5292 synchronized (stats) {
5293 ps = stats.getProcessStatsLocked(info.uid, proc);
5294 }
5295 return new ProcessRecord(ps, thread, info, proc);
5296 }
5297
5298 final ProcessRecord addAppLocked(ApplicationInfo info) {
5299 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5300
5301 if (app == null) {
5302 app = newProcessRecordLocked(null, info, null);
5303 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005304 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
5306
5307 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5308 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5309 app.persistent = true;
5310 app.maxAdj = CORE_SERVER_ADJ;
5311 }
5312 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5313 mPersistentStartingProcesses.add(app);
5314 startProcessLocked(app, "added application", app.processName);
5315 }
5316
5317 return app;
5318 }
5319
5320 public void unhandledBack() {
5321 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5322 "unhandledBack()");
5323
5324 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005325 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005326 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 TAG, "Performing unhandledBack(): stack size = " + count);
5328 if (count > 1) {
5329 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005330 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5332 Binder.restoreCallingIdentity(origId);
5333 }
5334 }
5335 }
5336
5337 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5338 String name = uri.getAuthority();
5339 ContentProviderHolder cph = getContentProviderExternal(name);
5340 ParcelFileDescriptor pfd = null;
5341 if (cph != null) {
5342 // We record the binder invoker's uid in thread-local storage before
5343 // going to the content provider to open the file. Later, in the code
5344 // that handles all permissions checks, we look for this uid and use
5345 // that rather than the Activity Manager's own uid. The effect is that
5346 // we do the check against the caller's permissions even though it looks
5347 // to the content provider like the Activity Manager itself is making
5348 // the request.
5349 sCallerIdentity.set(new Identity(
5350 Binder.getCallingPid(), Binder.getCallingUid()));
5351 try {
5352 pfd = cph.provider.openFile(uri, "r");
5353 } catch (FileNotFoundException e) {
5354 // do nothing; pfd will be returned null
5355 } finally {
5356 // Ensure that whatever happens, we clean up the identity state
5357 sCallerIdentity.remove();
5358 }
5359
5360 // We've got the fd now, so we're done with the provider.
5361 removeContentProviderExternal(name);
5362 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005363 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 }
5365 return pfd;
5366 }
5367
5368 public void goingToSleep() {
5369 synchronized(this) {
5370 mSleeping = true;
5371 mWindowManager.setEventDispatching(false);
5372
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005373 if (mMainStack.mResumedActivity != null) {
5374 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005376 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 }
5378 }
5379 }
5380
Dianne Hackborn55280a92009-05-07 15:53:46 -07005381 public boolean shutdown(int timeout) {
5382 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5383 != PackageManager.PERMISSION_GRANTED) {
5384 throw new SecurityException("Requires permission "
5385 + android.Manifest.permission.SHUTDOWN);
5386 }
5387
5388 boolean timedout = false;
5389
5390 synchronized(this) {
5391 mShuttingDown = true;
5392 mWindowManager.setEventDispatching(false);
5393
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005394 if (mMainStack.mResumedActivity != null) {
5395 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005396 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005397 while (mMainStack.mResumedActivity != null
5398 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005399 long delay = endTime - System.currentTimeMillis();
5400 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005401 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005402 timedout = true;
5403 break;
5404 }
5405 try {
5406 this.wait();
5407 } catch (InterruptedException e) {
5408 }
5409 }
5410 }
5411 }
5412
5413 mUsageStatsService.shutdown();
5414 mBatteryStatsService.shutdown();
5415
5416 return timedout;
5417 }
5418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 public void wakingUp() {
5420 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005421 if (mMainStack.mGoingToSleep.isHeld()) {
5422 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005423 }
5424 mWindowManager.setEventDispatching(true);
5425 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005426 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 }
5428 }
5429
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005430 public void stopAppSwitches() {
5431 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5432 != PackageManager.PERMISSION_GRANTED) {
5433 throw new SecurityException("Requires permission "
5434 + android.Manifest.permission.STOP_APP_SWITCHES);
5435 }
5436
5437 synchronized(this) {
5438 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5439 + APP_SWITCH_DELAY_TIME;
5440 mDidAppSwitch = false;
5441 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5442 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5443 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5444 }
5445 }
5446
5447 public void resumeAppSwitches() {
5448 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5449 != PackageManager.PERMISSION_GRANTED) {
5450 throw new SecurityException("Requires permission "
5451 + android.Manifest.permission.STOP_APP_SWITCHES);
5452 }
5453
5454 synchronized(this) {
5455 // Note that we don't execute any pending app switches... we will
5456 // let those wait until either the timeout, or the next start
5457 // activity request.
5458 mAppSwitchesAllowedTime = 0;
5459 }
5460 }
5461
5462 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5463 String name) {
5464 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5465 return true;
5466 }
5467
5468 final int perm = checkComponentPermission(
5469 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5470 callingUid, -1);
5471 if (perm == PackageManager.PERMISSION_GRANTED) {
5472 return true;
5473 }
5474
Joe Onorato8a9b2202010-02-26 18:56:32 -08005475 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005476 return false;
5477 }
5478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 public void setDebugApp(String packageName, boolean waitForDebugger,
5480 boolean persistent) {
5481 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5482 "setDebugApp()");
5483
5484 // Note that this is not really thread safe if there are multiple
5485 // callers into it at the same time, but that's not a situation we
5486 // care about.
5487 if (persistent) {
5488 final ContentResolver resolver = mContext.getContentResolver();
5489 Settings.System.putString(
5490 resolver, Settings.System.DEBUG_APP,
5491 packageName);
5492 Settings.System.putInt(
5493 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5494 waitForDebugger ? 1 : 0);
5495 }
5496
5497 synchronized (this) {
5498 if (!persistent) {
5499 mOrigDebugApp = mDebugApp;
5500 mOrigWaitForDebugger = mWaitForDebugger;
5501 }
5502 mDebugApp = packageName;
5503 mWaitForDebugger = waitForDebugger;
5504 mDebugTransient = !persistent;
5505 if (packageName != null) {
5506 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005507 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 Binder.restoreCallingIdentity(origId);
5509 }
5510 }
5511 }
5512
5513 public void setAlwaysFinish(boolean enabled) {
5514 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5515 "setAlwaysFinish()");
5516
5517 Settings.System.putInt(
5518 mContext.getContentResolver(),
5519 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5520
5521 synchronized (this) {
5522 mAlwaysFinishActivities = enabled;
5523 }
5524 }
5525
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005526 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005528 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005530 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005531 }
5532 }
5533
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005534 public boolean isUserAMonkey() {
5535 // For now the fact that there is a controller implies
5536 // we have a monkey.
5537 synchronized (this) {
5538 return mController != null;
5539 }
5540 }
5541
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005542 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005543 synchronized (this) {
5544 mWatchers.register(watcher);
5545 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005546 }
5547
5548 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005549 synchronized (this) {
5550 mWatchers.unregister(watcher);
5551 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005552 }
5553
Daniel Sandler69a48172010-06-23 16:29:36 -04005554 public void setImmersive(IBinder token, boolean immersive) {
5555 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005556 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005557 if (index < 0) {
5558 throw new IllegalArgumentException();
5559 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005560 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005561 r.immersive = immersive;
5562 }
5563 }
5564
5565 public boolean isImmersive(IBinder token) {
5566 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005567 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005568 if (index < 0) {
5569 throw new IllegalArgumentException();
5570 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005571 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005572 return r.immersive;
5573 }
5574 }
5575
5576 public boolean isTopActivityImmersive() {
5577 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005578 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005579 return (r != null) ? r.immersive : false;
5580 }
5581 }
5582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 public final void enterSafeMode() {
5584 synchronized(this) {
5585 // It only makes sense to do this before the system is ready
5586 // and started launching other packages.
5587 if (!mSystemReady) {
5588 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005589 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 } catch (RemoteException e) {
5591 }
5592
5593 View v = LayoutInflater.from(mContext).inflate(
5594 com.android.internal.R.layout.safe_mode, null);
5595 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5596 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5597 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5598 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5599 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5600 lp.format = v.getBackground().getOpacity();
5601 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5602 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5603 ((WindowManager)mContext.getSystemService(
5604 Context.WINDOW_SERVICE)).addView(v, lp);
5605 }
5606 }
5607 }
5608
5609 public void noteWakeupAlarm(IIntentSender sender) {
5610 if (!(sender instanceof PendingIntentRecord)) {
5611 return;
5612 }
5613 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5614 synchronized (stats) {
5615 if (mBatteryStatsService.isOnBattery()) {
5616 mBatteryStatsService.enforceCallingPermission();
5617 PendingIntentRecord rec = (PendingIntentRecord)sender;
5618 int MY_UID = Binder.getCallingUid();
5619 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5620 BatteryStatsImpl.Uid.Pkg pkg =
5621 stats.getPackageStatsLocked(uid, rec.key.packageName);
5622 pkg.incWakeupsLocked();
5623 }
5624 }
5625 }
5626
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005627 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005629 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005631 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 // XXX Note: don't acquire main activity lock here, because the window
5633 // manager calls in with its locks held.
5634
5635 boolean killed = false;
5636 synchronized (mPidsSelfLocked) {
5637 int[] types = new int[pids.length];
5638 int worstType = 0;
5639 for (int i=0; i<pids.length; i++) {
5640 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5641 if (proc != null) {
5642 int type = proc.setAdj;
5643 types[i] = type;
5644 if (type > worstType) {
5645 worstType = type;
5646 }
5647 }
5648 }
5649
5650 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5651 // then constrain it so we will kill all hidden procs.
5652 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5653 worstType = HIDDEN_APP_MIN_ADJ;
5654 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005655 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 for (int i=0; i<pids.length; i++) {
5657 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5658 if (proc == null) {
5659 continue;
5660 }
5661 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005662 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005663 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005664 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5665 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005667 proc.killedBackground = true;
5668 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 }
5670 }
5671 }
5672 return killed;
5673 }
5674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 public final void startRunning(String pkg, String cls, String action,
5676 String data) {
5677 synchronized(this) {
5678 if (mStartRunning) {
5679 return;
5680 }
5681 mStartRunning = true;
5682 mTopComponent = pkg != null && cls != null
5683 ? new ComponentName(pkg, cls) : null;
5684 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5685 mTopData = data;
5686 if (!mSystemReady) {
5687 return;
5688 }
5689 }
5690
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005691 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 }
5693
5694 private void retrieveSettings() {
5695 final ContentResolver resolver = mContext.getContentResolver();
5696 String debugApp = Settings.System.getString(
5697 resolver, Settings.System.DEBUG_APP);
5698 boolean waitForDebugger = Settings.System.getInt(
5699 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5700 boolean alwaysFinishActivities = Settings.System.getInt(
5701 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5702
5703 Configuration configuration = new Configuration();
5704 Settings.System.getConfiguration(resolver, configuration);
5705
5706 synchronized (this) {
5707 mDebugApp = mOrigDebugApp = debugApp;
5708 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5709 mAlwaysFinishActivities = alwaysFinishActivities;
5710 // This happens before any activities are started, so we can
5711 // change mConfiguration in-place.
5712 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005713 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005714 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 }
5716 }
5717
5718 public boolean testIsSystemReady() {
5719 // no need to synchronize(this) just to read & return the value
5720 return mSystemReady;
5721 }
5722
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005723 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 // In the simulator, startRunning will never have been called, which
5725 // normally sets a few crucial variables. Do it here instead.
5726 if (!Process.supportsProcesses()) {
5727 mStartRunning = true;
5728 mTopAction = Intent.ACTION_MAIN;
5729 }
5730
5731 synchronized(this) {
5732 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005733 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 return;
5735 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005736
5737 // Check to see if there are any update receivers to run.
5738 if (!mDidUpdate) {
5739 if (mWaitingUpdate) {
5740 return;
5741 }
5742 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5743 List<ResolveInfo> ris = null;
5744 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005745 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005746 intent, null, 0);
5747 } catch (RemoteException e) {
5748 }
5749 if (ris != null) {
5750 for (int i=ris.size()-1; i>=0; i--) {
5751 if ((ris.get(i).activityInfo.applicationInfo.flags
5752 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5753 ris.remove(i);
5754 }
5755 }
5756 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5757 for (int i=0; i<ris.size(); i++) {
5758 ActivityInfo ai = ris.get(i).activityInfo;
5759 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5760 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005761 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005762 finisher = new IIntentReceiver.Stub() {
5763 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005764 String data, Bundle extras, boolean ordered,
5765 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005766 throws RemoteException {
5767 synchronized (ActivityManagerService.this) {
5768 mDidUpdate = true;
5769 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005770 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005771 }
5772 };
5773 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005774 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005775 broadcastIntentLocked(null, null, intent, null, finisher,
5776 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005777 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005778 mWaitingUpdate = true;
5779 }
5780 }
5781 }
5782 if (mWaitingUpdate) {
5783 return;
5784 }
5785 mDidUpdate = true;
5786 }
5787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 mSystemReady = true;
5789 if (!mStartRunning) {
5790 return;
5791 }
5792 }
5793
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005794 ArrayList<ProcessRecord> procsToKill = null;
5795 synchronized(mPidsSelfLocked) {
5796 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5797 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5798 if (!isAllowedWhileBooting(proc.info)){
5799 if (procsToKill == null) {
5800 procsToKill = new ArrayList<ProcessRecord>();
5801 }
5802 procsToKill.add(proc);
5803 }
5804 }
5805 }
5806
5807 if (procsToKill != null) {
5808 synchronized(this) {
5809 for (int i=procsToKill.size()-1; i>=0; i--) {
5810 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005811 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005812 removeProcessLocked(proc, true);
5813 }
5814 }
5815 }
5816
Joe Onorato8a9b2202010-02-26 18:56:32 -08005817 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005818 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 SystemClock.uptimeMillis());
5820
5821 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005822 // Make sure we have no pre-ready processes sitting around.
5823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005824 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5825 ResolveInfo ri = mContext.getPackageManager()
5826 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005827 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 CharSequence errorMsg = null;
5829 if (ri != null) {
5830 ActivityInfo ai = ri.activityInfo;
5831 ApplicationInfo app = ai.applicationInfo;
5832 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5833 mTopAction = Intent.ACTION_FACTORY_TEST;
5834 mTopData = null;
5835 mTopComponent = new ComponentName(app.packageName,
5836 ai.name);
5837 } else {
5838 errorMsg = mContext.getResources().getText(
5839 com.android.internal.R.string.factorytest_not_system);
5840 }
5841 } else {
5842 errorMsg = mContext.getResources().getText(
5843 com.android.internal.R.string.factorytest_no_action);
5844 }
5845 if (errorMsg != null) {
5846 mTopAction = null;
5847 mTopData = null;
5848 mTopComponent = null;
5849 Message msg = Message.obtain();
5850 msg.what = SHOW_FACTORY_ERROR_MSG;
5851 msg.getData().putCharSequence("msg", errorMsg);
5852 mHandler.sendMessage(msg);
5853 }
5854 }
5855 }
5856
5857 retrieveSettings();
5858
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005859 if (goingCallback != null) goingCallback.run();
5860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 synchronized (this) {
5862 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5863 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005864 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005865 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 if (apps != null) {
5867 int N = apps.size();
5868 int i;
5869 for (i=0; i<N; i++) {
5870 ApplicationInfo info
5871 = (ApplicationInfo)apps.get(i);
5872 if (info != null &&
5873 !info.packageName.equals("android")) {
5874 addAppLocked(info);
5875 }
5876 }
5877 }
5878 } catch (RemoteException ex) {
5879 // pm is in same process, this will never happen.
5880 }
5881 }
5882
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005883 // Start up initial activity.
5884 mBooting = true;
5885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005887 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 Message msg = Message.obtain();
5889 msg.what = SHOW_UID_ERROR_MSG;
5890 mHandler.sendMessage(msg);
5891 }
5892 } catch (RemoteException e) {
5893 }
5894
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005895 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 }
5897 }
5898
Dan Egnorb7f03672009-12-09 16:22:32 -08005899 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005900 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005902 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005903 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 startAppProblemLocked(app);
5905 app.stopFreezingAllLocked();
5906 return handleAppCrashLocked(app);
5907 }
5908
Dan Egnorb7f03672009-12-09 16:22:32 -08005909 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005910 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005911 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005912 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005913 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5914 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 startAppProblemLocked(app);
5916 app.stopFreezingAllLocked();
5917 }
5918
5919 /**
5920 * Generate a process error record, suitable for attachment to a ProcessRecord.
5921 *
5922 * @param app The ProcessRecord in which the error occurred.
5923 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5924 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005925 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 * @param shortMsg Short message describing the crash.
5927 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005928 * @param stackTrace Full crash stack trace, may be null.
5929 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 * @return Returns a fully-formed AppErrorStateInfo record.
5931 */
5932 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005933 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005936 report.condition = condition;
5937 report.processName = app.processName;
5938 report.pid = app.pid;
5939 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005940 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 report.shortMsg = shortMsg;
5942 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005943 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944
5945 return report;
5946 }
5947
Dan Egnor42471dd2010-01-07 17:25:22 -08005948 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 synchronized (this) {
5950 app.crashing = false;
5951 app.crashingReport = null;
5952 app.notResponding = false;
5953 app.notRespondingReport = null;
5954 if (app.anrDialog == fromDialog) {
5955 app.anrDialog = null;
5956 }
5957 if (app.waitDialog == fromDialog) {
5958 app.waitDialog = null;
5959 }
5960 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005961 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07005962 Slog.i(ActivityManagerService.TAG, "Killing "
5963 + app.processName + " (pid=" + app.pid + "): user's request");
5964 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
5965 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 Process.killProcess(app.pid);
5967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 }
5969 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005970
Dan Egnorb7f03672009-12-09 16:22:32 -08005971 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 long now = SystemClock.uptimeMillis();
5973
5974 Long crashTime = mProcessCrashTimes.get(app.info.processName,
5975 app.info.uid);
5976 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
5977 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005978 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005980 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 app.info.processName, app.info.uid);
5982 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005983 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5984 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005986 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005988 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 }
5990 }
5991 if (!app.persistent) {
5992 // We don't want to start this process again until the user
5993 // explicitly does so... but for persistent process, we really
5994 // need to keep it running. If a persistent process is actually
5995 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08005996 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 app.info.processName);
5998 mBadProcesses.put(app.info.processName, app.info.uid, now);
5999 app.bad = true;
6000 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6001 app.removed = true;
6002 removeProcessLocked(app, false);
6003 return false;
6004 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006005 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006006 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006007 if (r.app == app) {
6008 // If the top running activity is from this crashing
6009 // process, then terminate it to avoid getting in a loop.
6010 Slog.w(TAG, " Force finishing activity "
6011 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006012 int index = mMainStack.indexOfTokenLocked(r);
6013 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006014 Activity.RESULT_CANCELED, null, "crashed");
6015 // Also terminate an activities below it that aren't yet
6016 // stopped, to avoid a situation where one will get
6017 // re-start our crashing activity once it gets resumed again.
6018 index--;
6019 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006020 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006021 if (r.state == ActivityState.RESUMED
6022 || r.state == ActivityState.PAUSING
6023 || r.state == ActivityState.PAUSED) {
6024 if (!r.isHomeActivity) {
6025 Slog.w(TAG, " Force finishing activity "
6026 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006027 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006028 Activity.RESULT_CANCELED, null, "crashed");
6029 }
6030 }
6031 }
6032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 }
6034
6035 // Bump up the crash count of any services currently running in the proc.
6036 if (app.services.size() != 0) {
6037 // Any services running in the application need to be placed
6038 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006039 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006040 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006041 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 sr.crashCount++;
6043 }
6044 }
6045
6046 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6047 return true;
6048 }
6049
6050 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006051 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6052 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 skipCurrentReceiverLocked(app);
6054 }
6055
6056 void skipCurrentReceiverLocked(ProcessRecord app) {
6057 boolean reschedule = false;
6058 BroadcastRecord r = app.curReceiver;
6059 if (r != null) {
6060 // The current broadcast is waiting for this app's receiver
6061 // to be finished. Looks like that's not going to happen, so
6062 // let the broadcast continue.
6063 logBroadcastReceiverDiscard(r);
6064 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6065 r.resultExtras, r.resultAbort, true);
6066 reschedule = true;
6067 }
6068 r = mPendingBroadcast;
6069 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006070 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 "skip & discard pending app " + r);
6072 logBroadcastReceiverDiscard(r);
6073 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6074 r.resultExtras, r.resultAbort, true);
6075 reschedule = true;
6076 }
6077 if (reschedule) {
6078 scheduleBroadcastsLocked();
6079 }
6080 }
6081
Dan Egnor60d87622009-12-16 16:32:58 -08006082 /**
6083 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6084 * The application process will exit immediately after this call returns.
6085 * @param app object of the crashing app, null for the system server
6086 * @param crashInfo describing the exception
6087 */
6088 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6089 ProcessRecord r = findAppProcess(app);
6090
6091 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6092 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006093 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006094 crashInfo.exceptionClassName,
6095 crashInfo.exceptionMessage,
6096 crashInfo.throwFileName,
6097 crashInfo.throwLineNumber);
6098
Dan Egnor42471dd2010-01-07 17:25:22 -08006099 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006100
6101 crashApplication(r, crashInfo);
6102 }
6103
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006104 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006105 IBinder app,
6106 int violationMask,
6107 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006108 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006109
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006110 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006111 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006112 boolean logIt = true;
6113 synchronized (mAlreadyLoggedViolatedStacks) {
6114 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6115 logIt = false;
6116 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006117 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006118 // the relative pain numbers, without logging all
6119 // the stack traces repeatedly. We'd want to do
6120 // likewise in the client code, which also does
6121 // dup suppression, before the Binder call.
6122 } else {
6123 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6124 mAlreadyLoggedViolatedStacks.clear();
6125 }
6126 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6127 }
6128 }
6129 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006130 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006131 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006132 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006133
6134 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6135 AppErrorResult result = new AppErrorResult();
6136 synchronized (this) {
6137 final long origId = Binder.clearCallingIdentity();
6138
6139 Message msg = Message.obtain();
6140 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6141 HashMap<String, Object> data = new HashMap<String, Object>();
6142 data.put("result", result);
6143 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006144 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006145 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006146 msg.obj = data;
6147 mHandler.sendMessage(msg);
6148
6149 Binder.restoreCallingIdentity(origId);
6150 }
6151 int res = result.get();
6152 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6153 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006154 }
6155
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006156 // Depending on the policy in effect, there could be a bunch of
6157 // these in quick succession so we try to batch these together to
6158 // minimize disk writes, number of dropbox entries, and maximize
6159 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006160 private void logStrictModeViolationToDropBox(
6161 ProcessRecord process,
6162 StrictMode.ViolationInfo info) {
6163 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006164 return;
6165 }
6166 final boolean isSystemApp = process == null ||
6167 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6168 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6169 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6170 final DropBoxManager dbox = (DropBoxManager)
6171 mContext.getSystemService(Context.DROPBOX_SERVICE);
6172
6173 // Exit early if the dropbox isn't configured to accept this report type.
6174 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6175
6176 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006177 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006178 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6179 synchronized (sb) {
6180 bufferWasEmpty = sb.length() == 0;
6181 appendDropBoxProcessHeaders(process, sb);
6182 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6183 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006184 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6185 if (info.violationNumThisLoop != 0) {
6186 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6187 }
6188 if (info != null && info.durationMillis != -1) {
6189 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006190 }
6191 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006192 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6193 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006194 }
6195 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006196
6197 // Only buffer up to ~64k. Various logging bits truncate
6198 // things at 128k.
6199 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006200 }
6201
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006202 // Flush immediately if the buffer's grown too large, or this
6203 // is a non-system app. Non-system apps are isolated with a
6204 // different tag & policy and not batched.
6205 //
6206 // Batching is useful during internal testing with
6207 // StrictMode settings turned up high. Without batching,
6208 // thousands of separate files could be created on boot.
6209 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006210 new Thread("Error dump: " + dropboxTag) {
6211 @Override
6212 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006213 String report;
6214 synchronized (sb) {
6215 report = sb.toString();
6216 sb.delete(0, sb.length());
6217 sb.trimToSize();
6218 }
6219 if (report.length() != 0) {
6220 dbox.addText(dropboxTag, report);
6221 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006222 }
6223 }.start();
6224 return;
6225 }
6226
6227 // System app batching:
6228 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006229 // An existing dropbox-writing thread is outstanding, so
6230 // we don't need to start it up. The existing thread will
6231 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006232 return;
6233 }
6234
6235 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6236 // (After this point, we shouldn't access AMS internal data structures.)
6237 new Thread("Error dump: " + dropboxTag) {
6238 @Override
6239 public void run() {
6240 // 5 second sleep to let stacks arrive and be batched together
6241 try {
6242 Thread.sleep(5000); // 5 seconds
6243 } catch (InterruptedException e) {}
6244
6245 String errorReport;
6246 synchronized (mStrictModeBuffer) {
6247 errorReport = mStrictModeBuffer.toString();
6248 if (errorReport.length() == 0) {
6249 return;
6250 }
6251 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6252 mStrictModeBuffer.trimToSize();
6253 }
6254 dbox.addText(dropboxTag, errorReport);
6255 }
6256 }.start();
6257 }
6258
Dan Egnor60d87622009-12-16 16:32:58 -08006259 /**
6260 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6261 * @param app object of the crashing app, null for the system server
6262 * @param tag reported by the caller
6263 * @param crashInfo describing the context of the error
6264 * @return true if the process should exit immediately (WTF is fatal)
6265 */
6266 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006267 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006268 ProcessRecord r = findAppProcess(app);
6269
6270 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6271 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006272 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006273 tag, crashInfo.exceptionMessage);
6274
Dan Egnor42471dd2010-01-07 17:25:22 -08006275 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006276
Doug Zongker43866e02010-01-07 12:09:54 -08006277 if (Settings.Secure.getInt(mContext.getContentResolver(),
6278 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006279 crashApplication(r, crashInfo);
6280 return true;
6281 } else {
6282 return false;
6283 }
6284 }
6285
6286 /**
6287 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6288 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6289 */
6290 private ProcessRecord findAppProcess(IBinder app) {
6291 if (app == null) {
6292 return null;
6293 }
6294
6295 synchronized (this) {
6296 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6297 final int NA = apps.size();
6298 for (int ia=0; ia<NA; ia++) {
6299 ProcessRecord p = apps.valueAt(ia);
6300 if (p.thread != null && p.thread.asBinder() == app) {
6301 return p;
6302 }
6303 }
6304 }
6305
Joe Onorato8a9b2202010-02-26 18:56:32 -08006306 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006307 return null;
6308 }
6309 }
6310
6311 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006312 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6313 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006314 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006315 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006316 if (process == null || process.pid == MY_PID) {
6317 sb.append("Process: system_server\n");
6318 } else {
6319 sb.append("Process: ").append(process.processName).append("\n");
6320 }
6321 if (process != null) {
6322 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006323 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006324 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6325 for (String pkg : process.pkgList) {
6326 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006327 try {
Dan Egnora455d192010-03-12 08:52:28 -08006328 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6329 if (pi != null) {
6330 sb.append(" v").append(pi.versionCode);
6331 if (pi.versionName != null) {
6332 sb.append(" (").append(pi.versionName).append(")");
6333 }
6334 }
6335 } catch (RemoteException e) {
6336 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006337 }
Dan Egnora455d192010-03-12 08:52:28 -08006338 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006339 }
Dan Egnora455d192010-03-12 08:52:28 -08006340 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006341 }
6342
6343 private static String processClass(ProcessRecord process) {
6344 if (process == null || process.pid == MY_PID) {
6345 return "system_server";
6346 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6347 return "system_app";
6348 } else {
6349 return "data_app";
6350 }
6351 }
6352
6353 /**
6354 * Write a description of an error (crash, WTF, ANR) to the drop box.
6355 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6356 * @param process which caused the error, null means the system server
6357 * @param activity which triggered the error, null if unknown
6358 * @param parent activity related to the error, null if unknown
6359 * @param subject line related to the error, null if absent
6360 * @param report in long form describing the error, null if absent
6361 * @param logFile to include in the report, null if none
6362 * @param crashInfo giving an application stack trace, null if absent
6363 */
6364 public void addErrorToDropBox(String eventType,
6365 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6366 final String report, final File logFile,
6367 final ApplicationErrorReport.CrashInfo crashInfo) {
6368 // NOTE -- this must never acquire the ActivityManagerService lock,
6369 // otherwise the watchdog may be prevented from resetting the system.
6370
6371 final String dropboxTag = processClass(process) + "_" + eventType;
6372 final DropBoxManager dbox = (DropBoxManager)
6373 mContext.getSystemService(Context.DROPBOX_SERVICE);
6374
6375 // Exit early if the dropbox isn't configured to accept this report type.
6376 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6377
6378 final StringBuilder sb = new StringBuilder(1024);
6379 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006380 if (activity != null) {
6381 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6382 }
6383 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6384 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6385 }
6386 if (parent != null && parent != activity) {
6387 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6388 }
6389 if (subject != null) {
6390 sb.append("Subject: ").append(subject).append("\n");
6391 }
6392 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6393 sb.append("\n");
6394
6395 // Do the rest in a worker thread to avoid blocking the caller on I/O
6396 // (After this point, we shouldn't access AMS internal data structures.)
6397 Thread worker = new Thread("Error dump: " + dropboxTag) {
6398 @Override
6399 public void run() {
6400 if (report != null) {
6401 sb.append(report);
6402 }
6403 if (logFile != null) {
6404 try {
6405 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6406 } catch (IOException e) {
6407 Slog.e(TAG, "Error reading " + logFile, e);
6408 }
6409 }
6410 if (crashInfo != null && crashInfo.stackTrace != null) {
6411 sb.append(crashInfo.stackTrace);
6412 }
6413
6414 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6415 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6416 if (lines > 0) {
6417 sb.append("\n");
6418
6419 // Merge several logcat streams, and take the last N lines
6420 InputStreamReader input = null;
6421 try {
6422 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6423 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6424 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6425
6426 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6427 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6428 input = new InputStreamReader(logcat.getInputStream());
6429
6430 int num;
6431 char[] buf = new char[8192];
6432 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6433 } catch (IOException e) {
6434 Slog.e(TAG, "Error running logcat", e);
6435 } finally {
6436 if (input != null) try { input.close(); } catch (IOException e) {}
6437 }
6438 }
6439
6440 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006441 }
Dan Egnora455d192010-03-12 08:52:28 -08006442 };
6443
6444 if (process == null || process.pid == MY_PID) {
6445 worker.run(); // We may be about to die -- need to run this synchronously
6446 } else {
6447 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006448 }
6449 }
6450
6451 /**
6452 * Bring up the "unexpected error" dialog box for a crashing app.
6453 * Deal with edge cases (intercepts from instrumented applications,
6454 * ActivityController, error intent receivers, that sort of thing).
6455 * @param r the application crashing
6456 * @param crashInfo describing the failure
6457 */
6458 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006459 long timeMillis = System.currentTimeMillis();
6460 String shortMsg = crashInfo.exceptionClassName;
6461 String longMsg = crashInfo.exceptionMessage;
6462 String stackTrace = crashInfo.stackTrace;
6463 if (shortMsg != null && longMsg != null) {
6464 longMsg = shortMsg + ": " + longMsg;
6465 } else if (shortMsg != null) {
6466 longMsg = shortMsg;
6467 }
6468
Dan Egnor60d87622009-12-16 16:32:58 -08006469 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006471 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006472 try {
6473 String name = r != null ? r.processName : null;
6474 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006475 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006476 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006477 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006478 + " at watcher's request");
6479 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006480 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 }
6482 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006483 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 }
6485 }
6486
6487 final long origId = Binder.clearCallingIdentity();
6488
6489 // If this process is running instrumentation, finish it.
6490 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006491 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006492 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006493 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6494 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006495 Bundle info = new Bundle();
6496 info.putString("shortMsg", shortMsg);
6497 info.putString("longMsg", longMsg);
6498 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6499 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006500 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 }
6502
Dan Egnor60d87622009-12-16 16:32:58 -08006503 // If we can't identify the process or it's already exceeded its crash quota,
6504 // quit right away without showing a crash dialog.
6505 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006507 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006508 }
6509
6510 Message msg = Message.obtain();
6511 msg.what = SHOW_ERROR_MSG;
6512 HashMap data = new HashMap();
6513 data.put("result", result);
6514 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 msg.obj = data;
6516 mHandler.sendMessage(msg);
6517
6518 Binder.restoreCallingIdentity(origId);
6519 }
6520
6521 int res = result.get();
6522
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006523 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 synchronized (this) {
6525 if (r != null) {
6526 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6527 SystemClock.uptimeMillis());
6528 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006529 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006530 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006531 }
6532 }
6533
6534 if (appErrorIntent != null) {
6535 try {
6536 mContext.startActivity(appErrorIntent);
6537 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006538 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006541 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006542
6543 Intent createAppErrorIntentLocked(ProcessRecord r,
6544 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6545 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006546 if (report == null) {
6547 return null;
6548 }
6549 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6550 result.setComponent(r.errorReportReceiver);
6551 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6552 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6553 return result;
6554 }
6555
Dan Egnorb7f03672009-12-09 16:22:32 -08006556 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6557 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006558 if (r.errorReportReceiver == null) {
6559 return null;
6560 }
6561
6562 if (!r.crashing && !r.notResponding) {
6563 return null;
6564 }
6565
Dan Egnorb7f03672009-12-09 16:22:32 -08006566 ApplicationErrorReport report = new ApplicationErrorReport();
6567 report.packageName = r.info.packageName;
6568 report.installerPackageName = r.errorReportReceiver.getPackageName();
6569 report.processName = r.processName;
6570 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006571 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006572
Dan Egnorb7f03672009-12-09 16:22:32 -08006573 if (r.crashing) {
6574 report.type = ApplicationErrorReport.TYPE_CRASH;
6575 report.crashInfo = crashInfo;
6576 } else if (r.notResponding) {
6577 report.type = ApplicationErrorReport.TYPE_ANR;
6578 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006579
Dan Egnorb7f03672009-12-09 16:22:32 -08006580 report.anrInfo.activity = r.notRespondingReport.tag;
6581 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6582 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006583 }
6584
Dan Egnorb7f03672009-12-09 16:22:32 -08006585 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006586 }
6587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006588 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6589 // assume our apps are happy - lazy create the list
6590 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6591
6592 synchronized (this) {
6593
6594 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006595 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6596 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006597 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6598 // This one's in trouble, so we'll generate a report for it
6599 // crashes are higher priority (in case there's a crash *and* an anr)
6600 ActivityManager.ProcessErrorStateInfo report = null;
6601 if (app.crashing) {
6602 report = app.crashingReport;
6603 } else if (app.notResponding) {
6604 report = app.notRespondingReport;
6605 }
6606
6607 if (report != null) {
6608 if (errList == null) {
6609 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6610 }
6611 errList.add(report);
6612 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006613 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 " crashing = " + app.crashing +
6615 " notResponding = " + app.notResponding);
6616 }
6617 }
6618 }
6619 }
6620
6621 return errList;
6622 }
6623
6624 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6625 // Lazy instantiation of list
6626 List<ActivityManager.RunningAppProcessInfo> runList = null;
6627 synchronized (this) {
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 // Generate process state info for running application
6633 ActivityManager.RunningAppProcessInfo currApp =
6634 new ActivityManager.RunningAppProcessInfo(app.processName,
6635 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006636 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006637 if (mHeavyWeightProcess == app) {
6638 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006640 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006641 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006642 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6643 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6644 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006645 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6646 } else if (adj >= HOME_APP_ADJ) {
6647 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6648 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 } else if (adj >= SECONDARY_SERVER_ADJ) {
6650 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006651 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6652 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6653 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6654 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006655 } else if (adj >= VISIBLE_APP_ADJ) {
6656 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6657 } else {
6658 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6659 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006660 currApp.importanceReasonCode = app.adjTypeCode;
6661 if (app.adjSource instanceof ProcessRecord) {
6662 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006663 } else if (app.adjSource instanceof ActivityRecord) {
6664 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006665 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6666 }
6667 if (app.adjTarget instanceof ComponentName) {
6668 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6669 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006670 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006671 // + " lru=" + currApp.lru);
6672 if (runList == null) {
6673 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6674 }
6675 runList.add(currApp);
6676 }
6677 }
6678 }
6679 return runList;
6680 }
6681
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006682 public List<ApplicationInfo> getRunningExternalApplications() {
6683 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6684 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6685 if (runningApps != null && runningApps.size() > 0) {
6686 Set<String> extList = new HashSet<String>();
6687 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6688 if (app.pkgList != null) {
6689 for (String pkg : app.pkgList) {
6690 extList.add(pkg);
6691 }
6692 }
6693 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006694 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006695 for (String pkg : extList) {
6696 try {
6697 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6698 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6699 retList.add(info);
6700 }
6701 } catch (RemoteException e) {
6702 }
6703 }
6704 }
6705 return retList;
6706 }
6707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006708 @Override
6709 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006710 if (checkCallingPermission(android.Manifest.permission.DUMP)
6711 != PackageManager.PERMISSION_GRANTED) {
6712 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6713 + Binder.getCallingPid()
6714 + ", uid=" + Binder.getCallingUid()
6715 + " without permission "
6716 + android.Manifest.permission.DUMP);
6717 return;
6718 }
6719
6720 boolean dumpAll = false;
6721
6722 int opti = 0;
6723 while (opti < args.length) {
6724 String opt = args[opti];
6725 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6726 break;
6727 }
6728 opti++;
6729 if ("-a".equals(opt)) {
6730 dumpAll = true;
6731 } else if ("-h".equals(opt)) {
6732 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006733 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006734 pw.println(" cmd may be one of:");
6735 pw.println(" activities: activity stack state");
6736 pw.println(" broadcasts: broadcast state");
6737 pw.println(" intents: pending intent state");
6738 pw.println(" processes: process state");
6739 pw.println(" providers: content provider state");
6740 pw.println(" services: service state");
6741 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006743 } else {
6744 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006746 }
6747
6748 // Is the caller requesting to dump a particular piece of data?
6749 if (opti < args.length) {
6750 String cmd = args[opti];
6751 opti++;
6752 if ("activities".equals(cmd) || "a".equals(cmd)) {
6753 synchronized (this) {
6754 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006756 return;
6757 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6758 synchronized (this) {
6759 dumpBroadcastsLocked(fd, pw, args, opti, true);
6760 }
6761 return;
6762 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6763 synchronized (this) {
6764 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6765 }
6766 return;
6767 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6768 synchronized (this) {
6769 dumpProcessesLocked(fd, pw, args, opti, true);
6770 }
6771 return;
6772 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6773 synchronized (this) {
6774 dumpProvidersLocked(fd, pw, args, opti, true);
6775 }
6776 return;
6777 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006778 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006779 return;
6780 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6781 synchronized (this) {
6782 dumpServicesLocked(fd, pw, args, opti, true);
6783 }
6784 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006786 }
6787
6788 // No piece of data specified, dump everything.
6789 synchronized (this) {
6790 boolean needSep;
6791 if (dumpAll) {
6792 pw.println("Providers in Current Activity Manager State:");
6793 }
6794 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6795 if (needSep) {
6796 pw.println(" ");
6797 }
6798 if (dumpAll) {
6799 pw.println("-------------------------------------------------------------------------------");
6800 pw.println("Broadcasts in Current Activity Manager State:");
6801 }
6802 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6803 if (needSep) {
6804 pw.println(" ");
6805 }
6806 if (dumpAll) {
6807 pw.println("-------------------------------------------------------------------------------");
6808 pw.println("Services in Current Activity Manager State:");
6809 }
6810 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6811 if (needSep) {
6812 pw.println(" ");
6813 }
6814 if (dumpAll) {
6815 pw.println("-------------------------------------------------------------------------------");
6816 pw.println("PendingIntents in Current Activity Manager State:");
6817 }
6818 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6819 if (needSep) {
6820 pw.println(" ");
6821 }
6822 if (dumpAll) {
6823 pw.println("-------------------------------------------------------------------------------");
6824 pw.println("Activities in Current Activity Manager State:");
6825 }
6826 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6827 if (needSep) {
6828 pw.println(" ");
6829 }
6830 if (dumpAll) {
6831 pw.println("-------------------------------------------------------------------------------");
6832 pw.println("Processes in Current Activity Manager State:");
6833 }
6834 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6835 }
6836 }
6837
6838 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6839 int opti, boolean dumpAll, boolean needHeader) {
6840 if (needHeader) {
6841 pw.println(" Activity stack:");
6842 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006843 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006844 pw.println(" ");
6845 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006846 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6847 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006848 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006849 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006850 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006851 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006852 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006853 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006854 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006855 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006856 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006857 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006858 pw.println(" ");
6859 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006860 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006862
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006863 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006864 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6865 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006866 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006867 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006868
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006869 if (dumpAll && mRecentTasks.size() > 0) {
6870 pw.println(" ");
6871 pw.println("Recent tasks in Current Activity Manager State:");
6872
6873 final int N = mRecentTasks.size();
6874 for (int i=0; i<N; i++) {
6875 TaskRecord tr = mRecentTasks.get(i);
6876 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6877 pw.println(tr);
6878 mRecentTasks.get(i).dump(pw, " ");
6879 }
6880 }
6881
6882 pw.println(" ");
6883 pw.println(" mCurTask: " + mCurTask);
6884
6885 return true;
6886 }
6887
6888 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6889 int opti, boolean dumpAll) {
6890 boolean needSep = false;
6891 int numPers = 0;
6892
6893 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006894 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6895 final int NA = procs.size();
6896 for (int ia=0; ia<NA; ia++) {
6897 if (!needSep) {
6898 pw.println(" All known processes:");
6899 needSep = true;
6900 }
6901 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006902 pw.print(r.persistent ? " *PERS*" : " *APP*");
6903 pw.print(" UID "); pw.print(procs.keyAt(ia));
6904 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 r.dump(pw, " ");
6906 if (r.persistent) {
6907 numPers++;
6908 }
6909 }
6910 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006911 }
6912
6913 if (mLruProcesses.size() > 0) {
6914 if (needSep) pw.println(" ");
6915 needSep = true;
6916 pw.println(" Running processes (most recent first):");
6917 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006918 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006919 needSep = true;
6920 }
6921
6922 synchronized (mPidsSelfLocked) {
6923 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 if (needSep) pw.println(" ");
6925 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006926 pw.println(" PID mappings:");
6927 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6928 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6929 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 }
6931 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006932 }
6933
6934 if (mForegroundProcesses.size() > 0) {
6935 if (needSep) pw.println(" ");
6936 needSep = true;
6937 pw.println(" Foreground Processes:");
6938 for (int i=0; i<mForegroundProcesses.size(); i++) {
6939 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6940 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006942 }
6943
6944 if (mPersistentStartingProcesses.size() > 0) {
6945 if (needSep) pw.println(" ");
6946 needSep = true;
6947 pw.println(" Persisent processes that are starting:");
6948 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6949 "Starting Norm", "Restarting PERS", false);
6950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006952 if (mStartingProcesses.size() > 0) {
6953 if (needSep) pw.println(" ");
6954 needSep = true;
6955 pw.println(" Processes that are starting:");
6956 dumpProcessList(pw, this, mStartingProcesses, " ",
6957 "Starting Norm", "Starting PERS", false);
6958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006960 if (mRemovedProcesses.size() > 0) {
6961 if (needSep) pw.println(" ");
6962 needSep = true;
6963 pw.println(" Processes that are being removed:");
6964 dumpProcessList(pw, this, mRemovedProcesses, " ",
6965 "Removed Norm", "Removed PERS", false);
6966 }
6967
6968 if (mProcessesOnHold.size() > 0) {
6969 if (needSep) pw.println(" ");
6970 needSep = true;
6971 pw.println(" Processes that are on old until the system is ready:");
6972 dumpProcessList(pw, this, mProcessesOnHold, " ",
6973 "OnHold Norm", "OnHold PERS", false);
6974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006975
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006976 if (mProcessesToGc.size() > 0) {
6977 if (needSep) pw.println(" ");
6978 needSep = true;
6979 pw.println(" Processes that are waiting to GC:");
6980 long now = SystemClock.uptimeMillis();
6981 for (int i=0; i<mProcessesToGc.size(); i++) {
6982 ProcessRecord proc = mProcessesToGc.get(i);
6983 pw.print(" Process "); pw.println(proc);
6984 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
6985 pw.print(", last gced=");
6986 pw.print(now-proc.lastRequestedGc);
6987 pw.print(" ms ago, last lowMem=");
6988 pw.print(now-proc.lastLowMemory);
6989 pw.println(" ms ago");
6990
6991 }
6992 }
6993
6994 if (mProcessCrashTimes.getMap().size() > 0) {
6995 if (needSep) pw.println(" ");
6996 needSep = true;
6997 pw.println(" Time since processes crashed:");
6998 long now = SystemClock.uptimeMillis();
6999 for (Map.Entry<String, SparseArray<Long>> procs
7000 : mProcessCrashTimes.getMap().entrySet()) {
7001 SparseArray<Long> uids = procs.getValue();
7002 final int N = uids.size();
7003 for (int i=0; i<N; i++) {
7004 pw.print(" Process "); pw.print(procs.getKey());
7005 pw.print(" uid "); pw.print(uids.keyAt(i));
7006 pw.print(": last crashed ");
7007 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007008 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007009 }
7010 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007013 if (mBadProcesses.getMap().size() > 0) {
7014 if (needSep) pw.println(" ");
7015 needSep = true;
7016 pw.println(" Bad processes:");
7017 for (Map.Entry<String, SparseArray<Long>> procs
7018 : mBadProcesses.getMap().entrySet()) {
7019 SparseArray<Long> uids = procs.getValue();
7020 final int N = uids.size();
7021 for (int i=0; i<N; i++) {
7022 pw.print(" Bad process "); pw.print(procs.getKey());
7023 pw.print(" uid "); pw.print(uids.keyAt(i));
7024 pw.print(": crashed at time ");
7025 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 }
7027 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007030 pw.println(" ");
7031 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007032 if (mHeavyWeightProcess != null) {
7033 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7034 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007035 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007036 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007037 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7038 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7039 || mOrigWaitForDebugger) {
7040 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7041 + " mDebugTransient=" + mDebugTransient
7042 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7043 }
7044 if (mAlwaysFinishActivities || mController != null) {
7045 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7046 + " mController=" + mController);
7047 }
7048 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007050 pw.println(" mStartRunning=" + mStartRunning
7051 + " mSystemReady=" + mSystemReady
7052 + " mBooting=" + mBooting
7053 + " mBooted=" + mBooted
7054 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007055 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7056 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007057 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007059
7060 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007061 }
7062
7063 /**
7064 * There are three ways to call this:
7065 * - no service specified: dump all the services
7066 * - a flattened component name that matched an existing service was specified as the
7067 * first arg: dump that one service
7068 * - the first arg isn't the flattened component name of an existing service:
7069 * dump all services whose component contains the first arg as a substring
7070 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007071 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7072 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073 String[] newArgs;
7074 String componentNameString;
7075 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007076 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 componentNameString = null;
7078 newArgs = EMPTY_STRING_ARRAY;
7079 r = null;
7080 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007081 componentNameString = args[opti];
7082 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007084 synchronized (this) {
7085 r = componentName != null ? mServices.get(componentName) : null;
7086 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007087 newArgs = new String[args.length - opti];
7088 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 }
7090
7091 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007092 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007094 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7095 synchronized (this) {
7096 for (ServiceRecord r1 : mServices.values()) {
7097 if (componentNameString == null
7098 || r1.name.flattenToString().contains(componentNameString)) {
7099 services.add(r1);
7100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007101 }
7102 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007103 for (int i=0; i<services.size(); i++) {
7104 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007106 }
7107 }
7108
7109 /**
7110 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7111 * there is a thread associated with the service.
7112 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007113 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7114 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007116 if (dumpAll) {
7117 synchronized (this) {
7118 pw.print(" * "); pw.println(r);
7119 r.dump(pw, " ");
7120 }
7121 pw.println("");
7122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 if (r.app != null && r.app.thread != null) {
7124 try {
7125 // flush anything that is already in the PrintWriter since the thread is going
7126 // to write to the file descriptor directly
7127 pw.flush();
7128 r.app.thread.dumpService(fd, r, args);
7129 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007130 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 } catch (RemoteException e) {
7132 pw.println("got a RemoteException while dumping the service");
7133 }
7134 }
7135 }
7136
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007137 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7138 int opti, boolean dumpAll) {
7139 boolean needSep = false;
7140
7141 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 if (mRegisteredReceivers.size() > 0) {
7143 pw.println(" ");
7144 pw.println(" Registered Receivers:");
7145 Iterator it = mRegisteredReceivers.values().iterator();
7146 while (it.hasNext()) {
7147 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007148 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 r.dump(pw, " ");
7150 }
7151 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 pw.println(" ");
7154 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007155 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007156 needSep = true;
7157 }
7158
7159 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7160 || mPendingBroadcast != null) {
7161 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007163 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007165 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7166 pw.println(" Broadcast #" + i + ":");
7167 mParallelBroadcasts.get(i).dump(pw, " ");
7168 }
7169 if (mOrderedBroadcasts.size() > 0) {
7170 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007171 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007172 }
7173 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7174 pw.println(" Serialized Broadcast #" + i + ":");
7175 mOrderedBroadcasts.get(i).dump(pw, " ");
7176 }
7177 pw.println(" ");
7178 pw.println(" Pending broadcast:");
7179 if (mPendingBroadcast != null) {
7180 mPendingBroadcast.dump(pw, " ");
7181 } else {
7182 pw.println(" (null)");
7183 }
7184 needSep = true;
7185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007187 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007189 pw.println(" Historical broadcasts:");
7190 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7191 BroadcastRecord r = mBroadcastHistory[i];
7192 if (r == null) {
7193 break;
7194 }
7195 pw.println(" Historical Broadcast #" + i + ":");
7196 r.dump(pw, " ");
7197 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007198 needSep = true;
7199 }
7200
7201 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007202 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007203 pw.println(" Sticky broadcasts:");
7204 StringBuilder sb = new StringBuilder(128);
7205 for (Map.Entry<String, ArrayList<Intent>> ent
7206 : mStickyBroadcasts.entrySet()) {
7207 pw.print(" * Sticky action "); pw.print(ent.getKey());
7208 pw.println(":");
7209 ArrayList<Intent> intents = ent.getValue();
7210 final int N = intents.size();
7211 for (int i=0; i<N; i++) {
7212 sb.setLength(0);
7213 sb.append(" Intent: ");
7214 intents.get(i).toShortString(sb, true, false);
7215 pw.println(sb.toString());
7216 Bundle bundle = intents.get(i).getExtras();
7217 if (bundle != null) {
7218 pw.print(" ");
7219 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007220 }
7221 }
7222 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007223 needSep = true;
7224 }
7225
7226 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007228 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007229 pw.println(" mHandler:");
7230 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007231 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007233
7234 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 }
7236
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007237 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7238 int opti, boolean dumpAll) {
7239 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007241 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 if (mServices.size() > 0) {
7243 pw.println(" Active services:");
7244 Iterator<ServiceRecord> it = mServices.values().iterator();
7245 while (it.hasNext()) {
7246 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007247 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007248 r.dump(pw, " ");
7249 }
7250 needSep = true;
7251 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007254 if (mPendingServices.size() > 0) {
7255 if (needSep) pw.println(" ");
7256 pw.println(" Pending services:");
7257 for (int i=0; i<mPendingServices.size(); i++) {
7258 ServiceRecord r = mPendingServices.get(i);
7259 pw.print(" * Pending "); pw.println(r);
7260 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007262 needSep = true;
7263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007265 if (mRestartingServices.size() > 0) {
7266 if (needSep) pw.println(" ");
7267 pw.println(" Restarting services:");
7268 for (int i=0; i<mRestartingServices.size(); i++) {
7269 ServiceRecord r = mRestartingServices.get(i);
7270 pw.print(" * Restarting "); pw.println(r);
7271 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007273 needSep = true;
7274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007276 if (mStoppingServices.size() > 0) {
7277 if (needSep) pw.println(" ");
7278 pw.println(" Stopping services:");
7279 for (int i=0; i<mStoppingServices.size(); i++) {
7280 ServiceRecord r = mStoppingServices.get(i);
7281 pw.print(" * Stopping "); pw.println(r);
7282 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007284 needSep = true;
7285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007286
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007287 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007288 if (mServiceConnections.size() > 0) {
7289 if (needSep) pw.println(" ");
7290 pw.println(" Connection bindings to services:");
7291 Iterator<ConnectionRecord> it
7292 = mServiceConnections.values().iterator();
7293 while (it.hasNext()) {
7294 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007295 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 r.dump(pw, " ");
7297 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007298 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 }
7300 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007301
7302 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 }
7304
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007305 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7306 int opti, boolean dumpAll) {
7307 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007309 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 if (mProvidersByClass.size() > 0) {
7311 if (needSep) pw.println(" ");
7312 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007313 Iterator<Map.Entry<String, ContentProviderRecord>> it
7314 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007316 Map.Entry<String, ContentProviderRecord> e = it.next();
7317 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007318 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 r.dump(pw, " ");
7320 }
7321 needSep = true;
7322 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007323
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007324 if (mProvidersByName.size() > 0) {
7325 pw.println(" ");
7326 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007327 Iterator<Map.Entry<String, ContentProviderRecord>> it
7328 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007329 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007330 Map.Entry<String, ContentProviderRecord> e = it.next();
7331 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007332 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7333 pw.println(r);
7334 }
7335 needSep = true;
7336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007337 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007338
7339 if (mLaunchingProviders.size() > 0) {
7340 if (needSep) pw.println(" ");
7341 pw.println(" Launching content providers:");
7342 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7343 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7344 pw.println(mLaunchingProviders.get(i));
7345 }
7346 needSep = true;
7347 }
7348
7349 if (mGrantedUriPermissions.size() > 0) {
7350 pw.println();
7351 pw.println("Granted Uri Permissions:");
7352 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7353 int uid = mGrantedUriPermissions.keyAt(i);
7354 HashMap<Uri, UriPermission> perms
7355 = mGrantedUriPermissions.valueAt(i);
7356 pw.print(" * UID "); pw.print(uid);
7357 pw.println(" holds:");
7358 for (UriPermission perm : perms.values()) {
7359 pw.print(" "); pw.println(perm);
7360 perm.dump(pw, " ");
7361 }
7362 }
7363 needSep = true;
7364 }
7365
7366 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007367 }
7368
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7370 int opti, boolean dumpAll) {
7371 boolean needSep = false;
7372
7373 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374 if (this.mIntentSenderRecords.size() > 0) {
7375 Iterator<WeakReference<PendingIntentRecord>> it
7376 = mIntentSenderRecords.values().iterator();
7377 while (it.hasNext()) {
7378 WeakReference<PendingIntentRecord> ref = it.next();
7379 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007380 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007382 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 rec.dump(pw, " ");
7384 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007385 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 }
7387 }
7388 }
7389 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390
7391 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 }
7393
7394 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007395 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007396 TaskRecord lastTask = null;
7397 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007398 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007399 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 if (lastTask != r.task) {
7401 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007402 pw.print(prefix);
7403 pw.print(full ? "* " : " ");
7404 pw.println(lastTask);
7405 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007406 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007409 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7410 pw.print(" #"); pw.print(i); pw.print(": ");
7411 pw.println(r);
7412 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007413 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 }
7416 }
7417
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007418 private static String buildOomTag(String prefix, String space, int val, int base) {
7419 if (val == base) {
7420 if (space == null) return prefix;
7421 return prefix + " ";
7422 }
7423 return prefix + "+" + Integer.toString(val-base);
7424 }
7425
7426 private static final int dumpProcessList(PrintWriter pw,
7427 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 String prefix, String normalLabel, String persistentLabel,
7429 boolean inclOomAdj) {
7430 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007431 final int N = list.size()-1;
7432 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 ProcessRecord r = (ProcessRecord)list.get(i);
7434 if (false) {
7435 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7436 + " #" + i + ":");
7437 r.dump(pw, prefix + " ");
7438 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007439 String oomAdj;
7440 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007441 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007442 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007443 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7444 } else if (r.setAdj >= HOME_APP_ADJ) {
7445 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7446 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7447 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7448 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7449 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007450 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7451 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7452 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7453 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007454 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7455 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7456 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7457 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007458 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007459 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007460 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007461 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007462 } else {
7463 oomAdj = Integer.toString(r.setAdj);
7464 }
7465 String schedGroup;
7466 switch (r.setSchedGroup) {
7467 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7468 schedGroup = "B";
7469 break;
7470 case Process.THREAD_GROUP_DEFAULT:
7471 schedGroup = "F";
7472 break;
7473 default:
7474 schedGroup = Integer.toString(r.setSchedGroup);
7475 break;
7476 }
7477 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007478 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007479 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007480 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007481 pw.print(prefix);
7482 pw.print(" ");
7483 if (r.adjTarget instanceof ComponentName) {
7484 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7485 } else if (r.adjTarget != null) {
7486 pw.print(r.adjTarget.toString());
7487 } else {
7488 pw.print("{null}");
7489 }
7490 pw.print("<=");
7491 if (r.adjSource instanceof ProcessRecord) {
7492 pw.print("Proc{");
7493 pw.print(((ProcessRecord)r.adjSource).toShortString());
7494 pw.println("}");
7495 } else if (r.adjSource != null) {
7496 pw.println(r.adjSource.toString());
7497 } else {
7498 pw.println("{null}");
7499 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007501 } else {
7502 pw.println(String.format("%s%s #%2d: %s",
7503 prefix, (r.persistent ? persistentLabel : normalLabel),
7504 i, r.toString()));
7505 }
7506 if (r.persistent) {
7507 numPers++;
7508 }
7509 }
7510 return numPers;
7511 }
7512
Dianne Hackborn472ad872010-04-07 17:31:48 -07007513 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007515 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 long uptime = SystemClock.uptimeMillis();
7517 long realtime = SystemClock.elapsedRealtime();
7518
7519 if (isCheckinRequest) {
7520 // short checkin version
7521 pw.println(uptime + "," + realtime);
7522 pw.flush();
7523 } else {
7524 pw.println("Applications Memory Usage (kB):");
7525 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7526 }
7527 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7528 ProcessRecord r = (ProcessRecord)list.get(i);
7529 if (r.thread != null) {
7530 if (!isCheckinRequest) {
7531 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7532 pw.flush();
7533 }
7534 try {
7535 r.thread.asBinder().dump(fd, args);
7536 } catch (RemoteException e) {
7537 if (!isCheckinRequest) {
7538 pw.println("Got RemoteException!");
7539 pw.flush();
7540 }
7541 }
7542 }
7543 }
7544 }
7545
7546 /**
7547 * Searches array of arguments for the specified string
7548 * @param args array of argument strings
7549 * @param value value to search for
7550 * @return true if the value is contained in the array
7551 */
7552 private static boolean scanArgs(String[] args, String value) {
7553 if (args != null) {
7554 for (String arg : args) {
7555 if (value.equals(arg)) {
7556 return true;
7557 }
7558 }
7559 }
7560 return false;
7561 }
7562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 private final void killServicesLocked(ProcessRecord app,
7564 boolean allowRestart) {
7565 // Report disconnected services.
7566 if (false) {
7567 // XXX we are letting the client link to the service for
7568 // death notifications.
7569 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007570 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007572 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 if (r.connections.size() > 0) {
7574 Iterator<ConnectionRecord> jt
7575 = r.connections.values().iterator();
7576 while (jt.hasNext()) {
7577 ConnectionRecord c = jt.next();
7578 if (c.binding.client != app) {
7579 try {
7580 //c.conn.connected(r.className, null);
7581 } catch (Exception e) {
7582 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007583 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 + r.shortName
7585 + " from app " + app.processName, e);
7586 }
7587 }
7588 }
7589 }
7590 }
7591 }
7592 }
7593
7594 // Clean up any connections this application has to other services.
7595 if (app.connections.size() > 0) {
7596 Iterator<ConnectionRecord> it = app.connections.iterator();
7597 while (it.hasNext()) {
7598 ConnectionRecord r = it.next();
7599 removeConnectionLocked(r, app, null);
7600 }
7601 }
7602 app.connections.clear();
7603
7604 if (app.services.size() != 0) {
7605 // Any services running in the application need to be placed
7606 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007607 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007609 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007610 synchronized (sr.stats.getBatteryStats()) {
7611 sr.stats.stopLaunchedLocked();
7612 }
7613 sr.app = null;
7614 sr.executeNesting = 0;
7615 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007616
7617 boolean hasClients = sr.bindings.size() > 0;
7618 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 Iterator<IntentBindRecord> bindings
7620 = sr.bindings.values().iterator();
7621 while (bindings.hasNext()) {
7622 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007623 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624 + ": shouldUnbind=" + b.hasBound);
7625 b.binder = null;
7626 b.requested = b.received = b.hasBound = false;
7627 }
7628 }
7629
7630 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007631 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007633 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007634 sr.crashCount, sr.shortName, app.pid);
7635 bringDownServiceLocked(sr, true);
7636 } else if (!allowRestart) {
7637 bringDownServiceLocked(sr, true);
7638 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007639 boolean canceled = scheduleServiceRestartLocked(sr, true);
7640
7641 // Should the service remain running? Note that in the
7642 // extreme case of so many attempts to deliver a command
7643 // that it failed, that we also will stop it here.
7644 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7645 if (sr.pendingStarts.size() == 0) {
7646 sr.startRequested = false;
7647 if (!hasClients) {
7648 // Whoops, no reason to restart!
7649 bringDownServiceLocked(sr, true);
7650 }
7651 }
7652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 }
7654 }
7655
7656 if (!allowRestart) {
7657 app.services.clear();
7658 }
7659 }
7660
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007661 // Make sure we have no more records on the stopping list.
7662 int i = mStoppingServices.size();
7663 while (i > 0) {
7664 i--;
7665 ServiceRecord sr = mStoppingServices.get(i);
7666 if (sr.app == app) {
7667 mStoppingServices.remove(i);
7668 }
7669 }
7670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671 app.executingServices.clear();
7672 }
7673
7674 private final void removeDyingProviderLocked(ProcessRecord proc,
7675 ContentProviderRecord cpr) {
7676 synchronized (cpr) {
7677 cpr.launchingApp = null;
7678 cpr.notifyAll();
7679 }
7680
7681 mProvidersByClass.remove(cpr.info.name);
7682 String names[] = cpr.info.authority.split(";");
7683 for (int j = 0; j < names.length; j++) {
7684 mProvidersByName.remove(names[j]);
7685 }
7686
7687 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7688 while (cit.hasNext()) {
7689 ProcessRecord capp = cit.next();
7690 if (!capp.persistent && capp.thread != null
7691 && capp.pid != 0
7692 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007693 Slog.i(TAG, "Kill " + capp.processName
7694 + " (pid " + capp.pid + "): provider " + cpr.info.name
7695 + " in dying process " + proc.processName);
7696 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7697 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 Process.killProcess(capp.pid);
7699 }
7700 }
7701
7702 mLaunchingProviders.remove(cpr);
7703 }
7704
7705 /**
7706 * Main code for cleaning up a process when it has gone away. This is
7707 * called both as a result of the process dying, or directly when stopping
7708 * a process when running in single process mode.
7709 */
7710 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7711 boolean restarting, int index) {
7712 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007713 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 }
7715
Dianne Hackborn36124872009-10-08 16:22:03 -07007716 mProcessesToGc.remove(app);
7717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 // Dismiss any open dialogs.
7719 if (app.crashDialog != null) {
7720 app.crashDialog.dismiss();
7721 app.crashDialog = null;
7722 }
7723 if (app.anrDialog != null) {
7724 app.anrDialog.dismiss();
7725 app.anrDialog = null;
7726 }
7727 if (app.waitDialog != null) {
7728 app.waitDialog.dismiss();
7729 app.waitDialog = null;
7730 }
7731
7732 app.crashing = false;
7733 app.notResponding = false;
7734
7735 app.resetPackageList();
7736 app.thread = null;
7737 app.forcingToForeground = null;
7738 app.foregroundServices = false;
7739
7740 killServicesLocked(app, true);
7741
7742 boolean restart = false;
7743
7744 int NL = mLaunchingProviders.size();
7745
7746 // Remove published content providers.
7747 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007748 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007750 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 cpr.provider = null;
7752 cpr.app = null;
7753
7754 // See if someone is waiting for this provider... in which
7755 // case we don't remove it, but just let it restart.
7756 int i = 0;
7757 if (!app.bad) {
7758 for (; i<NL; i++) {
7759 if (mLaunchingProviders.get(i) == cpr) {
7760 restart = true;
7761 break;
7762 }
7763 }
7764 } else {
7765 i = NL;
7766 }
7767
7768 if (i >= NL) {
7769 removeDyingProviderLocked(app, cpr);
7770 NL = mLaunchingProviders.size();
7771 }
7772 }
7773 app.pubProviders.clear();
7774 }
7775
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007776 // Take care of any launching providers waiting for this process.
7777 if (checkAppInLaunchingProvidersLocked(app, false)) {
7778 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 // Unregister from connected content providers.
7782 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007783 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007784 while (it.hasNext()) {
7785 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7786 cpr.clients.remove(app);
7787 }
7788 app.conProviders.clear();
7789 }
7790
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007791 // At this point there may be remaining entries in mLaunchingProviders
7792 // where we were the only one waiting, so they are no longer of use.
7793 // Look for these and clean up if found.
7794 // XXX Commented out for now. Trying to figure out a way to reproduce
7795 // the actual situation to identify what is actually going on.
7796 if (false) {
7797 for (int i=0; i<NL; i++) {
7798 ContentProviderRecord cpr = (ContentProviderRecord)
7799 mLaunchingProviders.get(i);
7800 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7801 synchronized (cpr) {
7802 cpr.launchingApp = null;
7803 cpr.notifyAll();
7804 }
7805 }
7806 }
7807 }
7808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809 skipCurrentReceiverLocked(app);
7810
7811 // Unregister any receivers.
7812 if (app.receivers.size() > 0) {
7813 Iterator<ReceiverList> it = app.receivers.iterator();
7814 while (it.hasNext()) {
7815 removeReceiverLocked(it.next());
7816 }
7817 app.receivers.clear();
7818 }
7819
Christopher Tate181fafa2009-05-14 11:12:14 -07007820 // If the app is undergoing backup, tell the backup manager about it
7821 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007822 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007823 try {
7824 IBackupManager bm = IBackupManager.Stub.asInterface(
7825 ServiceManager.getService(Context.BACKUP_SERVICE));
7826 bm.agentDisconnected(app.info.packageName);
7827 } catch (RemoteException e) {
7828 // can't happen; backup manager is local
7829 }
7830 }
7831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 // If the caller is restarting this app, then leave it in its
7833 // current lists and let the caller take care of it.
7834 if (restarting) {
7835 return;
7836 }
7837
7838 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007839 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 "Removing non-persistent process during cleanup: " + app);
7841 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007842 if (mHeavyWeightProcess == app) {
7843 mHeavyWeightProcess = null;
7844 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 } else if (!app.removed) {
7847 // This app is persistent, so we need to keep its record around.
7848 // If it is not already on the pending app list, add it there
7849 // and start a new process for it.
7850 app.thread = null;
7851 app.forcingToForeground = null;
7852 app.foregroundServices = false;
7853 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7854 mPersistentStartingProcesses.add(app);
7855 restart = true;
7856 }
7857 }
7858 mProcessesOnHold.remove(app);
7859
The Android Open Source Project4df24232009-03-05 14:34:35 -08007860 if (app == mHomeProcess) {
7861 mHomeProcess = null;
7862 }
7863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007864 if (restart) {
7865 // We have components that still need to be running in the
7866 // process, so re-launch it.
7867 mProcessNames.put(app.processName, app.info.uid, app);
7868 startProcessLocked(app, "restart", app.processName);
7869 } else if (app.pid > 0 && app.pid != MY_PID) {
7870 // Goodbye!
7871 synchronized (mPidsSelfLocked) {
7872 mPidsSelfLocked.remove(app.pid);
7873 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7874 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007875 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 }
7877 }
7878
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007879 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7880 // Look through the content providers we are waiting to have launched,
7881 // and if any run in this process then either schedule a restart of
7882 // the process or kill the client waiting for it if this process has
7883 // gone bad.
7884 int NL = mLaunchingProviders.size();
7885 boolean restart = false;
7886 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007887 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007888 if (cpr.launchingApp == app) {
7889 if (!alwaysBad && !app.bad) {
7890 restart = true;
7891 } else {
7892 removeDyingProviderLocked(app, cpr);
7893 NL = mLaunchingProviders.size();
7894 }
7895 }
7896 }
7897 return restart;
7898 }
7899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 // =========================================================
7901 // SERVICES
7902 // =========================================================
7903
7904 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7905 ActivityManager.RunningServiceInfo info =
7906 new ActivityManager.RunningServiceInfo();
7907 info.service = r.name;
7908 if (r.app != null) {
7909 info.pid = r.app.pid;
7910 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007911 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 info.process = r.processName;
7913 info.foreground = r.isForeground;
7914 info.activeSince = r.createTime;
7915 info.started = r.startRequested;
7916 info.clientCount = r.connections.size();
7917 info.crashCount = r.crashCount;
7918 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007919 if (r.isForeground) {
7920 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7921 }
7922 if (r.startRequested) {
7923 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7924 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007925 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007926 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7927 }
7928 if (r.app != null && r.app.persistent) {
7929 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7930 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007931 for (ConnectionRecord conn : r.connections.values()) {
7932 if (conn.clientLabel != 0) {
7933 info.clientPackage = conn.binding.client.info.packageName;
7934 info.clientLabel = conn.clientLabel;
7935 break;
7936 }
7937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 return info;
7939 }
7940
7941 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7942 int flags) {
7943 synchronized (this) {
7944 ArrayList<ActivityManager.RunningServiceInfo> res
7945 = new ArrayList<ActivityManager.RunningServiceInfo>();
7946
7947 if (mServices.size() > 0) {
7948 Iterator<ServiceRecord> it = mServices.values().iterator();
7949 while (it.hasNext() && res.size() < maxNum) {
7950 res.add(makeRunningServiceInfoLocked(it.next()));
7951 }
7952 }
7953
7954 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7955 ServiceRecord r = mRestartingServices.get(i);
7956 ActivityManager.RunningServiceInfo info =
7957 makeRunningServiceInfoLocked(r);
7958 info.restarting = r.nextRestartTime;
7959 res.add(info);
7960 }
7961
7962 return res;
7963 }
7964 }
7965
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007966 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
7967 synchronized (this) {
7968 ServiceRecord r = mServices.get(name);
7969 if (r != null) {
7970 for (ConnectionRecord conn : r.connections.values()) {
7971 if (conn.clientIntent != null) {
7972 return conn.clientIntent;
7973 }
7974 }
7975 }
7976 }
7977 return null;
7978 }
7979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 private final ServiceRecord findServiceLocked(ComponentName name,
7981 IBinder token) {
7982 ServiceRecord r = mServices.get(name);
7983 return r == token ? r : null;
7984 }
7985
7986 private final class ServiceLookupResult {
7987 final ServiceRecord record;
7988 final String permission;
7989
7990 ServiceLookupResult(ServiceRecord _record, String _permission) {
7991 record = _record;
7992 permission = _permission;
7993 }
7994 };
7995
7996 private ServiceLookupResult findServiceLocked(Intent service,
7997 String resolvedType) {
7998 ServiceRecord r = null;
7999 if (service.getComponent() != null) {
8000 r = mServices.get(service.getComponent());
8001 }
8002 if (r == null) {
8003 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8004 r = mServicesByIntent.get(filter);
8005 }
8006
8007 if (r == null) {
8008 try {
8009 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008010 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 service, resolvedType, 0);
8012 ServiceInfo sInfo =
8013 rInfo != null ? rInfo.serviceInfo : null;
8014 if (sInfo == null) {
8015 return null;
8016 }
8017
8018 ComponentName name = new ComponentName(
8019 sInfo.applicationInfo.packageName, sInfo.name);
8020 r = mServices.get(name);
8021 } catch (RemoteException ex) {
8022 // pm is in same process, this will never happen.
8023 }
8024 }
8025 if (r != null) {
8026 int callingPid = Binder.getCallingPid();
8027 int callingUid = Binder.getCallingUid();
8028 if (checkComponentPermission(r.permission,
8029 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8030 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008031 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 + " from pid=" + callingPid
8033 + ", uid=" + callingUid
8034 + " requires " + r.permission);
8035 return new ServiceLookupResult(null, r.permission);
8036 }
8037 return new ServiceLookupResult(r, null);
8038 }
8039 return null;
8040 }
8041
8042 private class ServiceRestarter implements Runnable {
8043 private ServiceRecord mService;
8044
8045 void setService(ServiceRecord service) {
8046 mService = service;
8047 }
8048
8049 public void run() {
8050 synchronized(ActivityManagerService.this) {
8051 performServiceRestartLocked(mService);
8052 }
8053 }
8054 }
8055
8056 private ServiceLookupResult retrieveServiceLocked(Intent service,
8057 String resolvedType, int callingPid, int callingUid) {
8058 ServiceRecord r = null;
8059 if (service.getComponent() != null) {
8060 r = mServices.get(service.getComponent());
8061 }
8062 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8063 r = mServicesByIntent.get(filter);
8064 if (r == null) {
8065 try {
8066 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008067 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008068 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 ServiceInfo sInfo =
8070 rInfo != null ? rInfo.serviceInfo : null;
8071 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008072 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 ": not found");
8074 return null;
8075 }
8076
8077 ComponentName name = new ComponentName(
8078 sInfo.applicationInfo.packageName, sInfo.name);
8079 r = mServices.get(name);
8080 if (r == null) {
8081 filter = new Intent.FilterComparison(service.cloneFilter());
8082 ServiceRestarter res = new ServiceRestarter();
8083 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8084 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8085 synchronized (stats) {
8086 ss = stats.getServiceStatsLocked(
8087 sInfo.applicationInfo.uid, sInfo.packageName,
8088 sInfo.name);
8089 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008090 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091 res.setService(r);
8092 mServices.put(name, r);
8093 mServicesByIntent.put(filter, r);
8094
8095 // Make sure this component isn't in the pending list.
8096 int N = mPendingServices.size();
8097 for (int i=0; i<N; i++) {
8098 ServiceRecord pr = mPendingServices.get(i);
8099 if (pr.name.equals(name)) {
8100 mPendingServices.remove(i);
8101 i--;
8102 N--;
8103 }
8104 }
8105 }
8106 } catch (RemoteException ex) {
8107 // pm is in same process, this will never happen.
8108 }
8109 }
8110 if (r != null) {
8111 if (checkComponentPermission(r.permission,
8112 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8113 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008114 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 + " from pid=" + Binder.getCallingPid()
8116 + ", uid=" + Binder.getCallingUid()
8117 + " requires " + r.permission);
8118 return new ServiceLookupResult(null, r.permission);
8119 }
8120 return new ServiceLookupResult(r, null);
8121 }
8122 return null;
8123 }
8124
8125 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8126 long now = SystemClock.uptimeMillis();
8127 if (r.executeNesting == 0 && r.app != null) {
8128 if (r.app.executingServices.size() == 0) {
8129 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8130 msg.obj = r.app;
8131 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8132 }
8133 r.app.executingServices.add(r);
8134 }
8135 r.executeNesting++;
8136 r.executingStart = now;
8137 }
8138
8139 private final void sendServiceArgsLocked(ServiceRecord r,
8140 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008141 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 if (N == 0) {
8143 return;
8144 }
8145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008146 int i = 0;
8147 while (i < N) {
8148 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008149 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008150 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008151 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008152 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008153 // If somehow we got a dummy start at the front, then
8154 // just drop it here.
8155 i++;
8156 continue;
8157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008158 bumpServiceExecutingLocked(r);
8159 if (!oomAdjusted) {
8160 oomAdjusted = true;
8161 updateOomAdjLocked(r.app);
8162 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008163 int flags = 0;
8164 if (si.deliveryCount > 0) {
8165 flags |= Service.START_FLAG_RETRY;
8166 }
8167 if (si.doneExecutingCount > 0) {
8168 flags |= Service.START_FLAG_REDELIVERY;
8169 }
8170 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8171 si.deliveredTime = SystemClock.uptimeMillis();
8172 r.deliveredStarts.add(si);
8173 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008175 } catch (RemoteException e) {
8176 // Remote process gone... we'll let the normal cleanup take
8177 // care of this.
8178 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008180 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181 break;
8182 }
8183 }
8184 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008185 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 } else {
8187 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008188 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008189 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 }
8191 }
8192 }
8193
8194 private final boolean requestServiceBindingLocked(ServiceRecord r,
8195 IntentBindRecord i, boolean rebind) {
8196 if (r.app == null || r.app.thread == null) {
8197 // If service is not currently running, can't yet bind.
8198 return false;
8199 }
8200 if ((!i.requested || rebind) && i.apps.size() > 0) {
8201 try {
8202 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008203 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 + ": shouldUnbind=" + i.hasBound);
8205 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8206 if (!rebind) {
8207 i.requested = true;
8208 }
8209 i.hasBound = true;
8210 i.doRebind = false;
8211 } catch (RemoteException e) {
8212 return false;
8213 }
8214 }
8215 return true;
8216 }
8217
8218 private final void requestServiceBindingsLocked(ServiceRecord r) {
8219 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8220 while (bindings.hasNext()) {
8221 IntentBindRecord i = bindings.next();
8222 if (!requestServiceBindingLocked(r, i, false)) {
8223 break;
8224 }
8225 }
8226 }
8227
8228 private final void realStartServiceLocked(ServiceRecord r,
8229 ProcessRecord app) throws RemoteException {
8230 if (app.thread == null) {
8231 throw new RemoteException();
8232 }
8233
8234 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008235 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236
8237 app.services.add(r);
8238 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008239 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240
8241 boolean created = false;
8242 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008243 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008244 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008245 mStringBuilder.setLength(0);
8246 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008247 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008248 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008249 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008250 synchronized (r.stats.getBatteryStats()) {
8251 r.stats.startLaunchedLocked();
8252 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008253 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008255 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 created = true;
8257 } finally {
8258 if (!created) {
8259 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008260 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 }
8262 }
8263
8264 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008265
8266 // If the service is in the started state, and there are no
8267 // pending arguments, then fake up one so its onStartCommand() will
8268 // be called.
8269 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8270 r.lastStartId++;
8271 if (r.lastStartId < 1) {
8272 r.lastStartId = 1;
8273 }
8274 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8275 }
8276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 sendServiceArgsLocked(r, true);
8278 }
8279
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008280 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8281 boolean allowCancel) {
8282 boolean canceled = false;
8283
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008284 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008285 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008286 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008287
8288 // Any delivered but not yet finished starts should be put back
8289 // on the pending list.
8290 final int N = r.deliveredStarts.size();
8291 if (N > 0) {
8292 for (int i=N-1; i>=0; i--) {
8293 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8294 if (si.intent == null) {
8295 // We'll generate this again if needed.
8296 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8297 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8298 r.pendingStarts.add(0, si);
8299 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8300 dur *= 2;
8301 if (minDuration < dur) minDuration = dur;
8302 if (resetTime < dur) resetTime = dur;
8303 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008304 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008305 + r.name);
8306 canceled = true;
8307 }
8308 }
8309 r.deliveredStarts.clear();
8310 }
8311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 r.totalRestartCount++;
8313 if (r.restartDelay == 0) {
8314 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008315 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 } else {
8317 // If it has been a "reasonably long time" since the service
8318 // was started, then reset our restart duration back to
8319 // the beginning, so we don't infinitely increase the duration
8320 // on a service that just occasionally gets killed (which is
8321 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008322 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008324 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008325 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008326 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008327 if (r.restartDelay < minDuration) {
8328 r.restartDelay = minDuration;
8329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008330 }
8331 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008332
8333 r.nextRestartTime = now + r.restartDelay;
8334
8335 // Make sure that we don't end up restarting a bunch of services
8336 // all at the same time.
8337 boolean repeat;
8338 do {
8339 repeat = false;
8340 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8341 ServiceRecord r2 = mRestartingServices.get(i);
8342 if (r2 != r && r.nextRestartTime
8343 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8344 && r.nextRestartTime
8345 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8346 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8347 r.restartDelay = r.nextRestartTime - now;
8348 repeat = true;
8349 break;
8350 }
8351 }
8352 } while (repeat);
8353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008354 if (!mRestartingServices.contains(r)) {
8355 mRestartingServices.add(r);
8356 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008357
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008358 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008361 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008363 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008365 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366 r.shortName, r.restartDelay);
8367
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008368 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 }
8370
8371 final void performServiceRestartLocked(ServiceRecord r) {
8372 if (!mRestartingServices.contains(r)) {
8373 return;
8374 }
8375 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8376 }
8377
8378 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8379 if (r.restartDelay == 0) {
8380 return false;
8381 }
8382 r.resetRestartCounter();
8383 mRestartingServices.remove(r);
8384 mHandler.removeCallbacks(r.restarter);
8385 return true;
8386 }
8387
8388 private final boolean bringUpServiceLocked(ServiceRecord r,
8389 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008390 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 //r.dump(" ");
8392
Dianne Hackborn36124872009-10-08 16:22:03 -07008393 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 sendServiceArgsLocked(r, false);
8395 return true;
8396 }
8397
8398 if (!whileRestarting && r.restartDelay > 0) {
8399 // If waiting for a restart, then do nothing.
8400 return true;
8401 }
8402
Joe Onorato8a9b2202010-02-26 18:56:32 -08008403 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008404 + " " + r.intent);
8405
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008406 // We are now bringing the service up, so no longer in the
8407 // restarting state.
8408 mRestartingServices.remove(r);
8409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 final String appName = r.processName;
8411 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8412 if (app != null && app.thread != null) {
8413 try {
8414 realStartServiceLocked(r, app);
8415 return true;
8416 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008417 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008418 }
8419
8420 // If a dead object exception was thrown -- fall through to
8421 // restart the application.
8422 }
8423
Dianne Hackborn36124872009-10-08 16:22:03 -07008424 // Not running -- get it started, and enqueue this service record
8425 // to be executed when the app comes up.
8426 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8427 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008428 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008429 + r.appInfo.packageName + "/"
8430 + r.appInfo.uid + " for service "
8431 + r.intent.getIntent() + ": process is bad");
8432 bringDownServiceLocked(r, true);
8433 return false;
8434 }
8435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 mPendingServices.add(r);
8438 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008440 return true;
8441 }
8442
8443 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008444 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 //r.dump(" ");
8446
8447 // Does it still need to run?
8448 if (!force && r.startRequested) {
8449 return;
8450 }
8451 if (r.connections.size() > 0) {
8452 if (!force) {
8453 // XXX should probably keep a count of the number of auto-create
8454 // connections directly in the service.
8455 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8456 while (it.hasNext()) {
8457 ConnectionRecord cr = it.next();
8458 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8459 return;
8460 }
8461 }
8462 }
8463
8464 // Report to all of the connections that the service is no longer
8465 // available.
8466 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8467 while (it.hasNext()) {
8468 ConnectionRecord c = it.next();
8469 try {
8470 // todo: shouldn't be a synchronous call!
8471 c.conn.connected(r.name, null);
8472 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008473 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008474 " to connection " + c.conn.asBinder() +
8475 " (in " + c.binding.client.processName + ")", e);
8476 }
8477 }
8478 }
8479
8480 // Tell the service that it has been unbound.
8481 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8482 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8483 while (it.hasNext()) {
8484 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008485 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 + ": hasBound=" + ibr.hasBound);
8487 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8488 try {
8489 bumpServiceExecutingLocked(r);
8490 updateOomAdjLocked(r.app);
8491 ibr.hasBound = false;
8492 r.app.thread.scheduleUnbindService(r,
8493 ibr.intent.getIntent());
8494 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008495 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 + r.shortName, e);
8497 serviceDoneExecutingLocked(r, true);
8498 }
8499 }
8500 }
8501 }
8502
Joe Onorato8a9b2202010-02-26 18:56:32 -08008503 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008505 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 System.identityHashCode(r), r.shortName,
8507 (r.app != null) ? r.app.pid : -1);
8508
8509 mServices.remove(r.name);
8510 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008511 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 r.totalRestartCount = 0;
8513 unscheduleServiceRestartLocked(r);
8514
8515 // Also make sure it is not on the pending list.
8516 int N = mPendingServices.size();
8517 for (int i=0; i<N; i++) {
8518 if (mPendingServices.get(i) == r) {
8519 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008520 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 TAG, "Removed pending service: " + r.shortName);
8522 i--;
8523 N--;
8524 }
8525 }
8526
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008527 r.cancelNotification();
8528 r.isForeground = false;
8529 r.foregroundId = 0;
8530 r.foregroundNoti = null;
8531
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008532 // Clear start entries.
8533 r.deliveredStarts.clear();
8534 r.pendingStarts.clear();
8535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 if (r.app != null) {
8537 synchronized (r.stats.getBatteryStats()) {
8538 r.stats.stopLaunchedLocked();
8539 }
8540 r.app.services.remove(r);
8541 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008543 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008544 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 bumpServiceExecutingLocked(r);
8546 mStoppingServices.add(r);
8547 updateOomAdjLocked(r.app);
8548 r.app.thread.scheduleStopService(r);
8549 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008550 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 + r.shortName, e);
8552 serviceDoneExecutingLocked(r, true);
8553 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008554 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008556 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557 TAG, "Removed service that has no process: " + r.shortName);
8558 }
8559 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008560 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 TAG, "Removed service that is not running: " + r.shortName);
8562 }
8563 }
8564
8565 ComponentName startServiceLocked(IApplicationThread caller,
8566 Intent service, String resolvedType,
8567 int callingPid, int callingUid) {
8568 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008569 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 + " type=" + resolvedType + " args=" + service.getExtras());
8571
8572 if (caller != null) {
8573 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8574 if (callerApp == null) {
8575 throw new SecurityException(
8576 "Unable to find app for caller " + caller
8577 + " (pid=" + Binder.getCallingPid()
8578 + ") when starting service " + service);
8579 }
8580 }
8581
8582 ServiceLookupResult res =
8583 retrieveServiceLocked(service, resolvedType,
8584 callingPid, callingUid);
8585 if (res == null) {
8586 return null;
8587 }
8588 if (res.record == null) {
8589 return new ComponentName("!", res.permission != null
8590 ? res.permission : "private to package");
8591 }
8592 ServiceRecord r = res.record;
8593 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008594 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 + r.shortName);
8596 }
8597 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008598 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 r.lastStartId++;
8600 if (r.lastStartId < 1) {
8601 r.lastStartId = 1;
8602 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008603 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008604 r.lastActivity = SystemClock.uptimeMillis();
8605 synchronized (r.stats.getBatteryStats()) {
8606 r.stats.startRunningLocked();
8607 }
8608 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8609 return new ComponentName("!", "Service process is bad");
8610 }
8611 return r.name;
8612 }
8613 }
8614
8615 public ComponentName startService(IApplicationThread caller, Intent service,
8616 String resolvedType) {
8617 // Refuse possible leaked file descriptors
8618 if (service != null && service.hasFileDescriptors() == true) {
8619 throw new IllegalArgumentException("File descriptors passed in Intent");
8620 }
8621
8622 synchronized(this) {
8623 final int callingPid = Binder.getCallingPid();
8624 final int callingUid = Binder.getCallingUid();
8625 final long origId = Binder.clearCallingIdentity();
8626 ComponentName res = startServiceLocked(caller, service,
8627 resolvedType, callingPid, callingUid);
8628 Binder.restoreCallingIdentity(origId);
8629 return res;
8630 }
8631 }
8632
8633 ComponentName startServiceInPackage(int uid,
8634 Intent service, String resolvedType) {
8635 synchronized(this) {
8636 final long origId = Binder.clearCallingIdentity();
8637 ComponentName res = startServiceLocked(null, service,
8638 resolvedType, -1, uid);
8639 Binder.restoreCallingIdentity(origId);
8640 return res;
8641 }
8642 }
8643
8644 public int stopService(IApplicationThread caller, Intent service,
8645 String resolvedType) {
8646 // Refuse possible leaked file descriptors
8647 if (service != null && service.hasFileDescriptors() == true) {
8648 throw new IllegalArgumentException("File descriptors passed in Intent");
8649 }
8650
8651 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008652 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 + " type=" + resolvedType);
8654
8655 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8656 if (caller != null && callerApp == null) {
8657 throw new SecurityException(
8658 "Unable to find app for caller " + caller
8659 + " (pid=" + Binder.getCallingPid()
8660 + ") when stopping service " + service);
8661 }
8662
8663 // If this service is active, make sure it is stopped.
8664 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8665 if (r != null) {
8666 if (r.record != null) {
8667 synchronized (r.record.stats.getBatteryStats()) {
8668 r.record.stats.stopRunningLocked();
8669 }
8670 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008671 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 final long origId = Binder.clearCallingIdentity();
8673 bringDownServiceLocked(r.record, false);
8674 Binder.restoreCallingIdentity(origId);
8675 return 1;
8676 }
8677 return -1;
8678 }
8679 }
8680
8681 return 0;
8682 }
8683
8684 public IBinder peekService(Intent service, String resolvedType) {
8685 // Refuse possible leaked file descriptors
8686 if (service != null && service.hasFileDescriptors() == true) {
8687 throw new IllegalArgumentException("File descriptors passed in Intent");
8688 }
8689
8690 IBinder ret = null;
8691
8692 synchronized(this) {
8693 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8694
8695 if (r != null) {
8696 // r.record is null if findServiceLocked() failed the caller permission check
8697 if (r.record == null) {
8698 throw new SecurityException(
8699 "Permission Denial: Accessing service " + r.record.name
8700 + " from pid=" + Binder.getCallingPid()
8701 + ", uid=" + Binder.getCallingUid()
8702 + " requires " + r.permission);
8703 }
8704 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8705 if (ib != null) {
8706 ret = ib.binder;
8707 }
8708 }
8709 }
8710
8711 return ret;
8712 }
8713
8714 public boolean stopServiceToken(ComponentName className, IBinder token,
8715 int startId) {
8716 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008717 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 + " " + token + " startId=" + startId);
8719 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008720 if (r != null) {
8721 if (startId >= 0) {
8722 // Asked to only stop if done with all work. Note that
8723 // to avoid leaks, we will take this as dropping all
8724 // start items up to and including this one.
8725 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8726 if (si != null) {
8727 while (r.deliveredStarts.size() > 0) {
8728 if (r.deliveredStarts.remove(0) == si) {
8729 break;
8730 }
8731 }
8732 }
8733
8734 if (r.lastStartId != startId) {
8735 return false;
8736 }
8737
8738 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008739 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008740 + " is last, but have " + r.deliveredStarts.size()
8741 + " remaining args");
8742 }
8743 }
8744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 synchronized (r.stats.getBatteryStats()) {
8746 r.stats.stopRunningLocked();
8747 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008748 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 }
8750 final long origId = Binder.clearCallingIdentity();
8751 bringDownServiceLocked(r, false);
8752 Binder.restoreCallingIdentity(origId);
8753 return true;
8754 }
8755 }
8756 return false;
8757 }
8758
8759 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008760 int id, Notification notification, boolean removeNotification) {
8761 final long origId = Binder.clearCallingIdentity();
8762 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008763 synchronized(this) {
8764 ServiceRecord r = findServiceLocked(className, token);
8765 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008766 if (id != 0) {
8767 if (notification == null) {
8768 throw new IllegalArgumentException("null notification");
8769 }
8770 if (r.foregroundId != id) {
8771 r.cancelNotification();
8772 r.foregroundId = id;
8773 }
8774 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8775 r.foregroundNoti = notification;
8776 r.isForeground = true;
8777 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778 if (r.app != null) {
8779 updateServiceForegroundLocked(r.app, true);
8780 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008781 } else {
8782 if (r.isForeground) {
8783 r.isForeground = false;
8784 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008785 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008786 updateServiceForegroundLocked(r.app, true);
8787 }
8788 }
8789 if (removeNotification) {
8790 r.cancelNotification();
8791 r.foregroundId = 0;
8792 r.foregroundNoti = null;
8793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 }
8795 }
8796 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008797 } finally {
8798 Binder.restoreCallingIdentity(origId);
8799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008800 }
8801
8802 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8803 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008804 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 if (sr.isForeground) {
8806 anyForeground = true;
8807 break;
8808 }
8809 }
8810 if (anyForeground != proc.foregroundServices) {
8811 proc.foregroundServices = anyForeground;
8812 if (oomAdj) {
8813 updateOomAdjLocked();
8814 }
8815 }
8816 }
8817
8818 public int bindService(IApplicationThread caller, IBinder token,
8819 Intent service, String resolvedType,
8820 IServiceConnection connection, int flags) {
8821 // Refuse possible leaked file descriptors
8822 if (service != null && service.hasFileDescriptors() == true) {
8823 throw new IllegalArgumentException("File descriptors passed in Intent");
8824 }
8825
8826 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008827 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008828 + " type=" + resolvedType + " conn=" + connection.asBinder()
8829 + " flags=0x" + Integer.toHexString(flags));
8830 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8831 if (callerApp == null) {
8832 throw new SecurityException(
8833 "Unable to find app for caller " + caller
8834 + " (pid=" + Binder.getCallingPid()
8835 + ") when binding service " + service);
8836 }
8837
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008838 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008839 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008840 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008841 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008842 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 return 0;
8844 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008845 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 }
8847
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008848 int clientLabel = 0;
8849 PendingIntent clientIntent = null;
8850
8851 if (callerApp.info.uid == Process.SYSTEM_UID) {
8852 // Hacky kind of thing -- allow system stuff to tell us
8853 // what they are, so we can report this elsewhere for
8854 // others to know why certain services are running.
8855 try {
8856 clientIntent = (PendingIntent)service.getParcelableExtra(
8857 Intent.EXTRA_CLIENT_INTENT);
8858 } catch (RuntimeException e) {
8859 }
8860 if (clientIntent != null) {
8861 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8862 if (clientLabel != 0) {
8863 // There are no useful extras in the intent, trash them.
8864 // System code calling with this stuff just needs to know
8865 // this will happen.
8866 service = service.cloneFilter();
8867 }
8868 }
8869 }
8870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871 ServiceLookupResult res =
8872 retrieveServiceLocked(service, resolvedType,
8873 Binder.getCallingPid(), Binder.getCallingUid());
8874 if (res == null) {
8875 return 0;
8876 }
8877 if (res.record == null) {
8878 return -1;
8879 }
8880 ServiceRecord s = res.record;
8881
8882 final long origId = Binder.clearCallingIdentity();
8883
8884 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008885 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 + s.shortName);
8887 }
8888
8889 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8890 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008891 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008892
8893 IBinder binder = connection.asBinder();
8894 s.connections.put(binder, c);
8895 b.connections.add(c);
8896 if (activity != null) {
8897 if (activity.connections == null) {
8898 activity.connections = new HashSet<ConnectionRecord>();
8899 }
8900 activity.connections.add(c);
8901 }
8902 b.client.connections.add(c);
8903 mServiceConnections.put(binder, c);
8904
8905 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8906 s.lastActivity = SystemClock.uptimeMillis();
8907 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8908 return 0;
8909 }
8910 }
8911
8912 if (s.app != null) {
8913 // This could have made the service more important.
8914 updateOomAdjLocked(s.app);
8915 }
8916
Joe Onorato8a9b2202010-02-26 18:56:32 -08008917 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008918 + ": received=" + b.intent.received
8919 + " apps=" + b.intent.apps.size()
8920 + " doRebind=" + b.intent.doRebind);
8921
8922 if (s.app != null && b.intent.received) {
8923 // Service is already running, so we can immediately
8924 // publish the connection.
8925 try {
8926 c.conn.connected(s.name, b.intent.binder);
8927 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008928 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008929 + " to connection " + c.conn.asBinder()
8930 + " (in " + c.binding.client.processName + ")", e);
8931 }
8932
8933 // If this is the first app connected back to this binding,
8934 // and the service had previously asked to be told when
8935 // rebound, then do so.
8936 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8937 requestServiceBindingLocked(s, b.intent, true);
8938 }
8939 } else if (!b.intent.requested) {
8940 requestServiceBindingLocked(s, b.intent, false);
8941 }
8942
8943 Binder.restoreCallingIdentity(origId);
8944 }
8945
8946 return 1;
8947 }
8948
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008949 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008950 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008951 IBinder binder = c.conn.asBinder();
8952 AppBindRecord b = c.binding;
8953 ServiceRecord s = b.service;
8954 s.connections.remove(binder);
8955 b.connections.remove(c);
8956 if (c.activity != null && c.activity != skipAct) {
8957 if (c.activity.connections != null) {
8958 c.activity.connections.remove(c);
8959 }
8960 }
8961 if (b.client != skipApp) {
8962 b.client.connections.remove(c);
8963 }
8964 mServiceConnections.remove(binder);
8965
8966 if (b.connections.size() == 0) {
8967 b.intent.apps.remove(b.client);
8968 }
8969
Joe Onorato8a9b2202010-02-26 18:56:32 -08008970 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008971 + ": shouldUnbind=" + b.intent.hasBound);
8972 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
8973 && b.intent.hasBound) {
8974 try {
8975 bumpServiceExecutingLocked(s);
8976 updateOomAdjLocked(s.app);
8977 b.intent.hasBound = false;
8978 // Assume the client doesn't want to know about a rebind;
8979 // we will deal with that later if it asks for one.
8980 b.intent.doRebind = false;
8981 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
8982 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008983 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 serviceDoneExecutingLocked(s, true);
8985 }
8986 }
8987
8988 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
8989 bringDownServiceLocked(s, false);
8990 }
8991 }
8992
8993 public boolean unbindService(IServiceConnection connection) {
8994 synchronized (this) {
8995 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008996 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 ConnectionRecord r = mServiceConnections.get(binder);
8998 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008999 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 + connection.asBinder());
9001 return false;
9002 }
9003
9004 final long origId = Binder.clearCallingIdentity();
9005
9006 removeConnectionLocked(r, null, null);
9007
9008 if (r.binding.service.app != null) {
9009 // This could have made the service less important.
9010 updateOomAdjLocked(r.binding.service.app);
9011 }
9012
9013 Binder.restoreCallingIdentity(origId);
9014 }
9015
9016 return true;
9017 }
9018
9019 public void publishService(IBinder token, Intent intent, IBinder service) {
9020 // Refuse possible leaked file descriptors
9021 if (intent != null && intent.hasFileDescriptors() == true) {
9022 throw new IllegalArgumentException("File descriptors passed in Intent");
9023 }
9024
9025 synchronized(this) {
9026 if (!(token instanceof ServiceRecord)) {
9027 throw new IllegalArgumentException("Invalid service token");
9028 }
9029 ServiceRecord r = (ServiceRecord)token;
9030
9031 final long origId = Binder.clearCallingIdentity();
9032
Joe Onorato8a9b2202010-02-26 18:56:32 -08009033 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 + " " + intent + ": " + service);
9035 if (r != null) {
9036 Intent.FilterComparison filter
9037 = new Intent.FilterComparison(intent);
9038 IntentBindRecord b = r.bindings.get(filter);
9039 if (b != null && !b.received) {
9040 b.binder = service;
9041 b.requested = true;
9042 b.received = true;
9043 if (r.connections.size() > 0) {
9044 Iterator<ConnectionRecord> it
9045 = r.connections.values().iterator();
9046 while (it.hasNext()) {
9047 ConnectionRecord c = it.next();
9048 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009049 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009051 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009052 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009053 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 TAG, "Published intent: " + intent);
9055 continue;
9056 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009057 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 try {
9059 c.conn.connected(r.name, service);
9060 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009061 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 " to connection " + c.conn.asBinder() +
9063 " (in " + c.binding.client.processName + ")", e);
9064 }
9065 }
9066 }
9067 }
9068
9069 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9070
9071 Binder.restoreCallingIdentity(origId);
9072 }
9073 }
9074 }
9075
9076 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9077 // Refuse possible leaked file descriptors
9078 if (intent != null && intent.hasFileDescriptors() == true) {
9079 throw new IllegalArgumentException("File descriptors passed in Intent");
9080 }
9081
9082 synchronized(this) {
9083 if (!(token instanceof ServiceRecord)) {
9084 throw new IllegalArgumentException("Invalid service token");
9085 }
9086 ServiceRecord r = (ServiceRecord)token;
9087
9088 final long origId = Binder.clearCallingIdentity();
9089
9090 if (r != null) {
9091 Intent.FilterComparison filter
9092 = new Intent.FilterComparison(intent);
9093 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009094 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009095 + " at " + b + ": apps="
9096 + (b != null ? b.apps.size() : 0));
9097 if (b != null) {
9098 if (b.apps.size() > 0) {
9099 // Applications have already bound since the last
9100 // unbind, so just rebind right here.
9101 requestServiceBindingLocked(r, b, true);
9102 } else {
9103 // Note to tell the service the next time there is
9104 // a new client.
9105 b.doRebind = true;
9106 }
9107 }
9108
9109 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9110
9111 Binder.restoreCallingIdentity(origId);
9112 }
9113 }
9114 }
9115
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009116 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009117 synchronized(this) {
9118 if (!(token instanceof ServiceRecord)) {
9119 throw new IllegalArgumentException("Invalid service token");
9120 }
9121 ServiceRecord r = (ServiceRecord)token;
9122 boolean inStopping = mStoppingServices.contains(token);
9123 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009124 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 + ": nesting=" + r.executeNesting
9126 + ", inStopping=" + inStopping);
9127 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009128 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 + " with incorrect token: given " + token
9130 + ", expected " + r);
9131 return;
9132 }
9133
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009134 if (type == 1) {
9135 // This is a call from a service start... take care of
9136 // book-keeping.
9137 r.callStart = true;
9138 switch (res) {
9139 case Service.START_STICKY_COMPATIBILITY:
9140 case Service.START_STICKY: {
9141 // We are done with the associated start arguments.
9142 r.findDeliveredStart(startId, true);
9143 // Don't stop if killed.
9144 r.stopIfKilled = false;
9145 break;
9146 }
9147 case Service.START_NOT_STICKY: {
9148 // We are done with the associated start arguments.
9149 r.findDeliveredStart(startId, true);
9150 if (r.lastStartId == startId) {
9151 // There is no more work, and this service
9152 // doesn't want to hang around if killed.
9153 r.stopIfKilled = true;
9154 }
9155 break;
9156 }
9157 case Service.START_REDELIVER_INTENT: {
9158 // We'll keep this item until they explicitly
9159 // call stop for it, but keep track of the fact
9160 // that it was delivered.
9161 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9162 if (si != null) {
9163 si.deliveryCount = 0;
9164 si.doneExecutingCount++;
9165 // Don't stop if killed.
9166 r.stopIfKilled = true;
9167 }
9168 break;
9169 }
9170 default:
9171 throw new IllegalArgumentException(
9172 "Unknown service start result: " + res);
9173 }
9174 if (res == Service.START_STICKY_COMPATIBILITY) {
9175 r.callStart = false;
9176 }
9177 }
9178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 final long origId = Binder.clearCallingIdentity();
9180 serviceDoneExecutingLocked(r, inStopping);
9181 Binder.restoreCallingIdentity(origId);
9182 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009183 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009184 + " with token " + token);
9185 }
9186 }
9187 }
9188
9189 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9190 r.executeNesting--;
9191 if (r.executeNesting <= 0 && r.app != null) {
9192 r.app.executingServices.remove(r);
9193 if (r.app.executingServices.size() == 0) {
9194 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9195 }
9196 if (inStopping) {
9197 mStoppingServices.remove(r);
9198 }
9199 updateOomAdjLocked(r.app);
9200 }
9201 }
9202
9203 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009204 String anrMessage = null;
9205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 synchronized(this) {
9207 if (proc.executingServices.size() == 0 || proc.thread == null) {
9208 return;
9209 }
9210 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9211 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9212 ServiceRecord timeout = null;
9213 long nextTime = 0;
9214 while (it.hasNext()) {
9215 ServiceRecord sr = it.next();
9216 if (sr.executingStart < maxTime) {
9217 timeout = sr;
9218 break;
9219 }
9220 if (sr.executingStart > nextTime) {
9221 nextTime = sr.executingStart;
9222 }
9223 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009224 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009225 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009226 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 } else {
9228 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9229 msg.obj = proc;
9230 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9231 }
9232 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009233
9234 if (anrMessage != null) {
9235 appNotResponding(proc, null, null, anrMessage);
9236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 }
9238
9239 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009240 // BACKUP AND RESTORE
9241 // =========================================================
9242
9243 // Cause the target app to be launched if necessary and its backup agent
9244 // instantiated. The backup agent will invoke backupAgentCreated() on the
9245 // activity manager to announce its creation.
9246 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009247 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009248 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9249
9250 synchronized(this) {
9251 // !!! TODO: currently no check here that we're already bound
9252 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9253 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9254 synchronized (stats) {
9255 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9256 }
9257
9258 BackupRecord r = new BackupRecord(ss, app, backupMode);
9259 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9260 // startProcessLocked() returns existing proc's record if it's already running
9261 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009262 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009263 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009264 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009265 return false;
9266 }
9267
9268 r.app = proc;
9269 mBackupTarget = r;
9270 mBackupAppName = app.packageName;
9271
Christopher Tate6fa95972009-06-05 18:43:55 -07009272 // Try not to kill the process during backup
9273 updateOomAdjLocked(proc);
9274
Christopher Tate181fafa2009-05-14 11:12:14 -07009275 // If the process is already attached, schedule the creation of the backup agent now.
9276 // If it is not yet live, this will be done when it attaches to the framework.
9277 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009279 try {
9280 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9281 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009282 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009283 }
9284 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009285 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009286 }
9287 // Invariants: at this point, the target app process exists and the application
9288 // is either already running or in the process of coming up. mBackupTarget and
9289 // mBackupAppName describe the app, so that when it binds back to the AM we
9290 // know that it's scheduled for a backup-agent operation.
9291 }
9292
9293 return true;
9294 }
9295
9296 // A backup agent has just come up
9297 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009298 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009299 + " = " + agent);
9300
9301 synchronized(this) {
9302 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009303 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009304 return;
9305 }
9306
Christopher Tate043dadc2009-06-02 16:11:00 -07009307 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009308 try {
9309 IBackupManager bm = IBackupManager.Stub.asInterface(
9310 ServiceManager.getService(Context.BACKUP_SERVICE));
9311 bm.agentConnected(agentPackageName, agent);
9312 } catch (RemoteException e) {
9313 // can't happen; the backup manager service is local
9314 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009315 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009316 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009317 } finally {
9318 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009319 }
9320 }
9321 }
9322
9323 // done with this agent
9324 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009325 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009326 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009327 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009328 return;
9329 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009330
9331 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009332 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009333 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009334 return;
9335 }
9336
Christopher Tate181fafa2009-05-14 11:12:14 -07009337 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009338 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009339 return;
9340 }
9341
Christopher Tate6fa95972009-06-05 18:43:55 -07009342 ProcessRecord proc = mBackupTarget.app;
9343 mBackupTarget = null;
9344 mBackupAppName = null;
9345
9346 // Not backing this app up any more; reset its OOM adjustment
9347 updateOomAdjLocked(proc);
9348
Christopher Tatec7b31e32009-06-10 15:49:30 -07009349 // If the app crashed during backup, 'thread' will be null here
9350 if (proc.thread != null) {
9351 try {
9352 proc.thread.scheduleDestroyBackupAgent(appInfo);
9353 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009354 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009355 e.printStackTrace();
9356 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009357 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009358 }
9359 }
9360 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009361 // BROADCASTS
9362 // =========================================================
9363
Josh Bartel7f208742010-02-25 11:01:44 -06009364 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 List cur) {
9366 final ContentResolver resolver = mContext.getContentResolver();
9367 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9368 if (list == null) {
9369 return cur;
9370 }
9371 int N = list.size();
9372 for (int i=0; i<N; i++) {
9373 Intent intent = list.get(i);
9374 if (filter.match(resolver, intent, true, TAG) >= 0) {
9375 if (cur == null) {
9376 cur = new ArrayList<Intent>();
9377 }
9378 cur.add(intent);
9379 }
9380 }
9381 return cur;
9382 }
9383
9384 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009385 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 + mBroadcastsScheduled);
9387
9388 if (mBroadcastsScheduled) {
9389 return;
9390 }
9391 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9392 mBroadcastsScheduled = true;
9393 }
9394
9395 public Intent registerReceiver(IApplicationThread caller,
9396 IIntentReceiver receiver, IntentFilter filter, String permission) {
9397 synchronized(this) {
9398 ProcessRecord callerApp = null;
9399 if (caller != null) {
9400 callerApp = getRecordForAppLocked(caller);
9401 if (callerApp == null) {
9402 throw new SecurityException(
9403 "Unable to find app for caller " + caller
9404 + " (pid=" + Binder.getCallingPid()
9405 + ") when registering receiver " + receiver);
9406 }
9407 }
9408
9409 List allSticky = null;
9410
9411 // Look for any matching sticky broadcasts...
9412 Iterator actions = filter.actionsIterator();
9413 if (actions != null) {
9414 while (actions.hasNext()) {
9415 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009416 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417 }
9418 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009419 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 }
9421
9422 // The first sticky in the list is returned directly back to
9423 // the client.
9424 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9425
Joe Onorato8a9b2202010-02-26 18:56:32 -08009426 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009427 + ": " + sticky);
9428
9429 if (receiver == null) {
9430 return sticky;
9431 }
9432
9433 ReceiverList rl
9434 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9435 if (rl == null) {
9436 rl = new ReceiverList(this, callerApp,
9437 Binder.getCallingPid(),
9438 Binder.getCallingUid(), receiver);
9439 if (rl.app != null) {
9440 rl.app.receivers.add(rl);
9441 } else {
9442 try {
9443 receiver.asBinder().linkToDeath(rl, 0);
9444 } catch (RemoteException e) {
9445 return sticky;
9446 }
9447 rl.linkedToDeath = true;
9448 }
9449 mRegisteredReceivers.put(receiver.asBinder(), rl);
9450 }
9451 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9452 rl.add(bf);
9453 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009454 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009455 }
9456 mReceiverResolver.addFilter(bf);
9457
9458 // Enqueue broadcasts for all existing stickies that match
9459 // this filter.
9460 if (allSticky != null) {
9461 ArrayList receivers = new ArrayList();
9462 receivers.add(bf);
9463
9464 int N = allSticky.size();
9465 for (int i=0; i<N; i++) {
9466 Intent intent = (Intent)allSticky.get(i);
9467 BroadcastRecord r = new BroadcastRecord(intent, null,
9468 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009469 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009470 if (mParallelBroadcasts.size() == 0) {
9471 scheduleBroadcastsLocked();
9472 }
9473 mParallelBroadcasts.add(r);
9474 }
9475 }
9476
9477 return sticky;
9478 }
9479 }
9480
9481 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009482 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483
9484 boolean doNext = false;
9485
9486 synchronized(this) {
9487 ReceiverList rl
9488 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9489 if (rl != null) {
9490 if (rl.curBroadcast != null) {
9491 BroadcastRecord r = rl.curBroadcast;
9492 doNext = finishReceiverLocked(
9493 receiver.asBinder(), r.resultCode, r.resultData,
9494 r.resultExtras, r.resultAbort, true);
9495 }
9496
9497 if (rl.app != null) {
9498 rl.app.receivers.remove(rl);
9499 }
9500 removeReceiverLocked(rl);
9501 if (rl.linkedToDeath) {
9502 rl.linkedToDeath = false;
9503 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9504 }
9505 }
9506 }
9507
9508 if (!doNext) {
9509 return;
9510 }
9511
9512 final long origId = Binder.clearCallingIdentity();
9513 processNextBroadcast(false);
9514 trimApplications();
9515 Binder.restoreCallingIdentity(origId);
9516 }
9517
9518 void removeReceiverLocked(ReceiverList rl) {
9519 mRegisteredReceivers.remove(rl.receiver.asBinder());
9520 int N = rl.size();
9521 for (int i=0; i<N; i++) {
9522 mReceiverResolver.removeFilter(rl.get(i));
9523 }
9524 }
9525
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009526 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9527 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9528 ProcessRecord r = mLruProcesses.get(i);
9529 if (r.thread != null) {
9530 try {
9531 r.thread.dispatchPackageBroadcast(cmd, packages);
9532 } catch (RemoteException ex) {
9533 }
9534 }
9535 }
9536 }
9537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009538 private final int broadcastIntentLocked(ProcessRecord callerApp,
9539 String callerPackage, Intent intent, String resolvedType,
9540 IIntentReceiver resultTo, int resultCode, String resultData,
9541 Bundle map, String requiredPermission,
9542 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9543 intent = new Intent(intent);
9544
Joe Onorato8a9b2202010-02-26 18:56:32 -08009545 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009546 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9547 + " ordered=" + ordered);
9548 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009549 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 }
9551
9552 // Handle special intents: if this broadcast is from the package
9553 // manager about a package being removed, we need to remove all of
9554 // its activities from the history stack.
9555 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9556 intent.getAction());
9557 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9558 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009559 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009560 || uidRemoved) {
9561 if (checkComponentPermission(
9562 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9563 callingPid, callingUid, -1)
9564 == PackageManager.PERMISSION_GRANTED) {
9565 if (uidRemoved) {
9566 final Bundle intentExtras = intent.getExtras();
9567 final int uid = intentExtras != null
9568 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9569 if (uid >= 0) {
9570 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9571 synchronized (bs) {
9572 bs.removeUidStatsLocked(uid);
9573 }
9574 }
9575 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009576 // If resources are unvailble just force stop all
9577 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009578 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009579 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9580 if (list != null && (list.length > 0)) {
9581 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009582 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009583 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009584 sendPackageBroadcastLocked(
9585 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009586 }
9587 } else {
9588 Uri data = intent.getData();
9589 String ssp;
9590 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9591 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9592 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009593 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009594 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009595 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9596 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9597 new String[] {ssp});
9598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 }
9600 }
9601 }
9602 } else {
9603 String msg = "Permission Denial: " + intent.getAction()
9604 + " broadcast from " + callerPackage + " (pid=" + callingPid
9605 + ", uid=" + callingUid + ")"
9606 + " requires "
9607 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009608 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009609 throw new SecurityException(msg);
9610 }
9611 }
9612
9613 /*
9614 * If this is the time zone changed action, queue up a message that will reset the timezone
9615 * of all currently running processes. This message will get queued up before the broadcast
9616 * happens.
9617 */
9618 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9619 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9620 }
9621
Dianne Hackborn854060af2009-07-09 18:14:31 -07009622 /*
9623 * Prevent non-system code (defined here to be non-persistent
9624 * processes) from sending protected broadcasts.
9625 */
9626 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9627 || callingUid == Process.SHELL_UID || callingUid == 0) {
9628 // Always okay.
9629 } else if (callerApp == null || !callerApp.persistent) {
9630 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009631 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009632 intent.getAction())) {
9633 String msg = "Permission Denial: not allowed to send broadcast "
9634 + intent.getAction() + " from pid="
9635 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009636 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009637 throw new SecurityException(msg);
9638 }
9639 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009640 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009641 return BROADCAST_SUCCESS;
9642 }
9643 }
9644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 // Add to the sticky list if requested.
9646 if (sticky) {
9647 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9648 callingPid, callingUid)
9649 != PackageManager.PERMISSION_GRANTED) {
9650 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9651 + callingPid + ", uid=" + callingUid
9652 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009653 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654 throw new SecurityException(msg);
9655 }
9656 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009657 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 + " and enforce permission " + requiredPermission);
9659 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9660 }
9661 if (intent.getComponent() != null) {
9662 throw new SecurityException(
9663 "Sticky broadcasts can't target a specific component");
9664 }
9665 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9666 if (list == null) {
9667 list = new ArrayList<Intent>();
9668 mStickyBroadcasts.put(intent.getAction(), list);
9669 }
9670 int N = list.size();
9671 int i;
9672 for (i=0; i<N; i++) {
9673 if (intent.filterEquals(list.get(i))) {
9674 // This sticky already exists, replace it.
9675 list.set(i, new Intent(intent));
9676 break;
9677 }
9678 }
9679 if (i >= N) {
9680 list.add(new Intent(intent));
9681 }
9682 }
9683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 // Figure out who all will receive this broadcast.
9685 List receivers = null;
9686 List<BroadcastFilter> registeredReceivers = null;
9687 try {
9688 if (intent.getComponent() != null) {
9689 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009690 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009691 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 if (ai != null) {
9693 receivers = new ArrayList();
9694 ResolveInfo ri = new ResolveInfo();
9695 ri.activityInfo = ai;
9696 receivers.add(ri);
9697 }
9698 } else {
9699 // Need to resolve the intent to interested receivers...
9700 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9701 == 0) {
9702 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009703 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009704 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 }
Mihai Preda074edef2009-05-18 17:13:31 +02009706 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009707 }
9708 } catch (RemoteException ex) {
9709 // pm is in same process, this will never happen.
9710 }
9711
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009712 final boolean replacePending =
9713 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9714
Joe Onorato8a9b2202010-02-26 18:56:32 -08009715 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009716 + " replacePending=" + replacePending);
9717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009718 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9719 if (!ordered && NR > 0) {
9720 // If we are not serializing this broadcast, then send the
9721 // registered receivers separately so they don't wait for the
9722 // components to be launched.
9723 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9724 callerPackage, callingPid, callingUid, requiredPermission,
9725 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009726 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009727 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 TAG, "Enqueueing parallel broadcast " + r
9729 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009730 boolean replaced = false;
9731 if (replacePending) {
9732 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9733 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009734 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009735 "***** DROPPING PARALLEL: " + intent);
9736 mParallelBroadcasts.set(i, r);
9737 replaced = true;
9738 break;
9739 }
9740 }
9741 }
9742 if (!replaced) {
9743 mParallelBroadcasts.add(r);
9744 scheduleBroadcastsLocked();
9745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009746 registeredReceivers = null;
9747 NR = 0;
9748 }
9749
9750 // Merge into one list.
9751 int ir = 0;
9752 if (receivers != null) {
9753 // A special case for PACKAGE_ADDED: do not allow the package
9754 // being added to see this broadcast. This prevents them from
9755 // using this as a back door to get run as soon as they are
9756 // installed. Maybe in the future we want to have a special install
9757 // broadcast or such for apps, but we'd like to deliberately make
9758 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009759 String skipPackages[] = null;
9760 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9761 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9762 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9763 Uri data = intent.getData();
9764 if (data != null) {
9765 String pkgName = data.getSchemeSpecificPart();
9766 if (pkgName != null) {
9767 skipPackages = new String[] { pkgName };
9768 }
9769 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009770 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009771 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009772 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009773 if (skipPackages != null && (skipPackages.length > 0)) {
9774 for (String skipPackage : skipPackages) {
9775 if (skipPackage != null) {
9776 int NT = receivers.size();
9777 for (int it=0; it<NT; it++) {
9778 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9779 if (curt.activityInfo.packageName.equals(skipPackage)) {
9780 receivers.remove(it);
9781 it--;
9782 NT--;
9783 }
9784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 }
9786 }
9787 }
9788
9789 int NT = receivers != null ? receivers.size() : 0;
9790 int it = 0;
9791 ResolveInfo curt = null;
9792 BroadcastFilter curr = null;
9793 while (it < NT && ir < NR) {
9794 if (curt == null) {
9795 curt = (ResolveInfo)receivers.get(it);
9796 }
9797 if (curr == null) {
9798 curr = registeredReceivers.get(ir);
9799 }
9800 if (curr.getPriority() >= curt.priority) {
9801 // Insert this broadcast record into the final list.
9802 receivers.add(it, curr);
9803 ir++;
9804 curr = null;
9805 it++;
9806 NT++;
9807 } else {
9808 // Skip to the next ResolveInfo in the final list.
9809 it++;
9810 curt = null;
9811 }
9812 }
9813 }
9814 while (ir < NR) {
9815 if (receivers == null) {
9816 receivers = new ArrayList();
9817 }
9818 receivers.add(registeredReceivers.get(ir));
9819 ir++;
9820 }
9821
9822 if ((receivers != null && receivers.size() > 0)
9823 || resultTo != null) {
9824 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9825 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009826 receivers, resultTo, resultCode, resultData, map, ordered,
9827 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009828 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 TAG, "Enqueueing ordered broadcast " + r
9830 + ": prev had " + mOrderedBroadcasts.size());
9831 if (DEBUG_BROADCAST) {
9832 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009833 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009834 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009835 boolean replaced = false;
9836 if (replacePending) {
9837 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9838 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009839 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009840 "***** DROPPING ORDERED: " + intent);
9841 mOrderedBroadcasts.set(i, r);
9842 replaced = true;
9843 break;
9844 }
9845 }
9846 }
9847 if (!replaced) {
9848 mOrderedBroadcasts.add(r);
9849 scheduleBroadcastsLocked();
9850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 }
9852
9853 return BROADCAST_SUCCESS;
9854 }
9855
9856 public final int broadcastIntent(IApplicationThread caller,
9857 Intent intent, String resolvedType, IIntentReceiver resultTo,
9858 int resultCode, String resultData, Bundle map,
9859 String requiredPermission, boolean serialized, boolean sticky) {
9860 // Refuse possible leaked file descriptors
9861 if (intent != null && intent.hasFileDescriptors() == true) {
9862 throw new IllegalArgumentException("File descriptors passed in Intent");
9863 }
9864
9865 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009866 int flags = intent.getFlags();
9867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 if (!mSystemReady) {
9869 // if the caller really truly claims to know what they're doing, go
9870 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9872 intent = new Intent(intent);
9873 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9874 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009875 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 + " before boot completion");
9877 throw new IllegalStateException("Cannot broadcast before boot completed");
9878 }
9879 }
9880
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009881 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9882 throw new IllegalArgumentException(
9883 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9884 }
9885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9887 final int callingPid = Binder.getCallingPid();
9888 final int callingUid = Binder.getCallingUid();
9889 final long origId = Binder.clearCallingIdentity();
9890 int res = broadcastIntentLocked(callerApp,
9891 callerApp != null ? callerApp.info.packageName : null,
9892 intent, resolvedType, resultTo,
9893 resultCode, resultData, map, requiredPermission, serialized,
9894 sticky, callingPid, callingUid);
9895 Binder.restoreCallingIdentity(origId);
9896 return res;
9897 }
9898 }
9899
9900 int broadcastIntentInPackage(String packageName, int uid,
9901 Intent intent, String resolvedType, IIntentReceiver resultTo,
9902 int resultCode, String resultData, Bundle map,
9903 String requiredPermission, boolean serialized, boolean sticky) {
9904 synchronized(this) {
9905 final long origId = Binder.clearCallingIdentity();
9906 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9907 resultTo, resultCode, resultData, map, requiredPermission,
9908 serialized, sticky, -1, uid);
9909 Binder.restoreCallingIdentity(origId);
9910 return res;
9911 }
9912 }
9913
9914 public final void unbroadcastIntent(IApplicationThread caller,
9915 Intent intent) {
9916 // Refuse possible leaked file descriptors
9917 if (intent != null && intent.hasFileDescriptors() == true) {
9918 throw new IllegalArgumentException("File descriptors passed in Intent");
9919 }
9920
9921 synchronized(this) {
9922 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9923 != PackageManager.PERMISSION_GRANTED) {
9924 String msg = "Permission Denial: unbroadcastIntent() from pid="
9925 + Binder.getCallingPid()
9926 + ", uid=" + Binder.getCallingUid()
9927 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009928 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 throw new SecurityException(msg);
9930 }
9931 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9932 if (list != null) {
9933 int N = list.size();
9934 int i;
9935 for (i=0; i<N; i++) {
9936 if (intent.filterEquals(list.get(i))) {
9937 list.remove(i);
9938 break;
9939 }
9940 }
9941 }
9942 }
9943 }
9944
9945 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9946 String resultData, Bundle resultExtras, boolean resultAbort,
9947 boolean explicit) {
9948 if (mOrderedBroadcasts.size() == 0) {
9949 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009950 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009951 }
9952 return false;
9953 }
9954 BroadcastRecord r = mOrderedBroadcasts.get(0);
9955 if (r.receiver == null) {
9956 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009957 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 }
9959 return false;
9960 }
9961 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009962 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 return false;
9964 }
9965 int state = r.state;
9966 r.state = r.IDLE;
9967 if (state == r.IDLE) {
9968 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009969 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 }
9971 }
9972 r.receiver = null;
9973 r.intent.setComponent(null);
9974 if (r.curApp != null) {
9975 r.curApp.curReceiver = null;
9976 }
9977 if (r.curFilter != null) {
9978 r.curFilter.receiverList.curBroadcast = null;
9979 }
9980 r.curFilter = null;
9981 r.curApp = null;
9982 r.curComponent = null;
9983 r.curReceiver = null;
9984 mPendingBroadcast = null;
9985
9986 r.resultCode = resultCode;
9987 r.resultData = resultData;
9988 r.resultExtras = resultExtras;
9989 r.resultAbort = resultAbort;
9990
9991 // We will process the next receiver right now if this is finishing
9992 // an app receiver (which is always asynchronous) or after we have
9993 // come back from calling a receiver.
9994 return state == BroadcastRecord.APP_RECEIVE
9995 || state == BroadcastRecord.CALL_DONE_RECEIVE;
9996 }
9997
9998 public void finishReceiver(IBinder who, int resultCode, String resultData,
9999 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010000 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001
10002 // Refuse possible leaked file descriptors
10003 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10004 throw new IllegalArgumentException("File descriptors passed in Bundle");
10005 }
10006
10007 boolean doNext;
10008
10009 final long origId = Binder.clearCallingIdentity();
10010
10011 synchronized(this) {
10012 doNext = finishReceiverLocked(
10013 who, resultCode, resultData, resultExtras, resultAbort, true);
10014 }
10015
10016 if (doNext) {
10017 processNextBroadcast(false);
10018 }
10019 trimApplications();
10020
10021 Binder.restoreCallingIdentity(origId);
10022 }
10023
10024 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10025 if (r.nextReceiver > 0) {
10026 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10027 if (curReceiver instanceof BroadcastFilter) {
10028 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010029 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 System.identityHashCode(r),
10031 r.intent.getAction(),
10032 r.nextReceiver - 1,
10033 System.identityHashCode(bf));
10034 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010035 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 System.identityHashCode(r),
10037 r.intent.getAction(),
10038 r.nextReceiver - 1,
10039 ((ResolveInfo)curReceiver).toString());
10040 }
10041 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010042 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010044 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045 System.identityHashCode(r),
10046 r.intent.getAction(),
10047 r.nextReceiver,
10048 "NONE");
10049 }
10050 }
10051
10052 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010053 ProcessRecord app = null;
10054 String anrMessage = null;
10055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 synchronized (this) {
10057 if (mOrderedBroadcasts.size() == 0) {
10058 return;
10059 }
10060 long now = SystemClock.uptimeMillis();
10061 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010062 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010063 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010065 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010067 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068 return;
10069 }
10070
Joe Onorato8a9b2202010-02-26 18:56:32 -080010071 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010072 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010073 r.anrCount++;
10074
10075 // Current receiver has passed its expiration date.
10076 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010077 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 return;
10079 }
10080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010082 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 logBroadcastReceiverDiscard(r);
10084 if (curReceiver instanceof BroadcastFilter) {
10085 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10086 if (bf.receiverList.pid != 0
10087 && bf.receiverList.pid != MY_PID) {
10088 synchronized (this.mPidsSelfLocked) {
10089 app = this.mPidsSelfLocked.get(
10090 bf.receiverList.pid);
10091 }
10092 }
10093 } else {
10094 app = r.curApp;
10095 }
10096
10097 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010098 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 }
10100
10101 if (mPendingBroadcast == r) {
10102 mPendingBroadcast = null;
10103 }
10104
10105 // Move on to the next receiver.
10106 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10107 r.resultExtras, r.resultAbort, true);
10108 scheduleBroadcastsLocked();
10109 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010110
10111 if (anrMessage != null) {
10112 appNotResponding(app, null, null, anrMessage);
10113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 }
10115
10116 private final void processCurBroadcastLocked(BroadcastRecord r,
10117 ProcessRecord app) throws RemoteException {
10118 if (app.thread == null) {
10119 throw new RemoteException();
10120 }
10121 r.receiver = app.thread.asBinder();
10122 r.curApp = app;
10123 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010124 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010125
10126 // Tell the application to launch this receiver.
10127 r.intent.setComponent(r.curComponent);
10128
10129 boolean started = false;
10130 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010131 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010132 "Delivering to component " + r.curComponent
10133 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010134 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10136 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10137 started = true;
10138 } finally {
10139 if (!started) {
10140 r.receiver = null;
10141 r.curApp = null;
10142 app.curReceiver = null;
10143 }
10144 }
10145
10146 }
10147
10148 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010149 Intent intent, int resultCode, String data, Bundle extras,
10150 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010151 if (app != null && app.thread != null) {
10152 // If we have an app thread, do the call through that so it is
10153 // correctly ordered with other one-way calls.
10154 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010155 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010156 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010157 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 }
10159 }
10160
10161 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10162 BroadcastFilter filter, boolean ordered) {
10163 boolean skip = false;
10164 if (filter.requiredPermission != null) {
10165 int perm = checkComponentPermission(filter.requiredPermission,
10166 r.callingPid, r.callingUid, -1);
10167 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010168 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010169 + r.intent.toString()
10170 + " from " + r.callerPackage + " (pid="
10171 + r.callingPid + ", uid=" + r.callingUid + ")"
10172 + " requires " + filter.requiredPermission
10173 + " due to registered receiver " + filter);
10174 skip = true;
10175 }
10176 }
10177 if (r.requiredPermission != null) {
10178 int perm = checkComponentPermission(r.requiredPermission,
10179 filter.receiverList.pid, filter.receiverList.uid, -1);
10180 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010181 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 + r.intent.toString()
10183 + " to " + filter.receiverList.app
10184 + " (pid=" + filter.receiverList.pid
10185 + ", uid=" + filter.receiverList.uid + ")"
10186 + " requires " + r.requiredPermission
10187 + " due to sender " + r.callerPackage
10188 + " (uid " + r.callingUid + ")");
10189 skip = true;
10190 }
10191 }
10192
10193 if (!skip) {
10194 // If this is not being sent as an ordered broadcast, then we
10195 // don't want to touch the fields that keep track of the current
10196 // state of ordered broadcasts.
10197 if (ordered) {
10198 r.receiver = filter.receiverList.receiver.asBinder();
10199 r.curFilter = filter;
10200 filter.receiverList.curBroadcast = r;
10201 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010202 if (filter.receiverList.app != null) {
10203 // Bump hosting application to no longer be in background
10204 // scheduling class. Note that we can't do that if there
10205 // isn't an app... but we can only be in that case for
10206 // things that directly call the IActivityManager API, which
10207 // are already core system stuff so don't matter for this.
10208 r.curApp = filter.receiverList.app;
10209 filter.receiverList.app.curReceiver = r;
10210 updateOomAdjLocked();
10211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010212 }
10213 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010214 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010215 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010216 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010217 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010218 }
10219 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10220 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010221 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010222 if (ordered) {
10223 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10224 }
10225 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010226 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 if (ordered) {
10228 r.receiver = null;
10229 r.curFilter = null;
10230 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010231 if (filter.receiverList.app != null) {
10232 filter.receiverList.app.curReceiver = null;
10233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 }
10235 }
10236 }
10237 }
10238
Dianne Hackborn12527f92009-11-11 17:39:50 -080010239 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10240 if (r.callingUid < 0) {
10241 // This was from a registerReceiver() call; ignore it.
10242 return;
10243 }
10244 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10245 MAX_BROADCAST_HISTORY-1);
10246 r.finishTime = SystemClock.uptimeMillis();
10247 mBroadcastHistory[0] = r;
10248 }
10249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 private final void processNextBroadcast(boolean fromMsg) {
10251 synchronized(this) {
10252 BroadcastRecord r;
10253
Joe Onorato8a9b2202010-02-26 18:56:32 -080010254 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010255 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010256 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010257
10258 updateCpuStats();
10259
10260 if (fromMsg) {
10261 mBroadcastsScheduled = false;
10262 }
10263
10264 // First, deliver any non-serialized broadcasts right away.
10265 while (mParallelBroadcasts.size() > 0) {
10266 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010267 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010269 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010270 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 for (int i=0; i<N; i++) {
10272 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010273 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010274 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010275 + target + ": " + r);
10276 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10277 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010278 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010279 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010280 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 }
10282
10283 // Now take care of the next serialized one...
10284
10285 // If we are waiting for a process to come up to handle the next
10286 // broadcast, then do nothing at this point. Just in case, we
10287 // check that the process we're waiting for still exists.
10288 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010289 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010290 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010291 + mPendingBroadcast.curApp);
10292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293
10294 boolean isDead;
10295 synchronized (mPidsSelfLocked) {
10296 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10297 }
10298 if (!isDead) {
10299 // It's still alive, so keep waiting
10300 return;
10301 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010302 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 + " died before responding to broadcast");
10304 mPendingBroadcast = null;
10305 }
10306 }
10307
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010308 boolean looped = false;
10309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310 do {
10311 if (mOrderedBroadcasts.size() == 0) {
10312 // No more broadcasts pending, so all done!
10313 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010314 if (looped) {
10315 // If we had finished the last ordered broadcast, then
10316 // make sure all processes have correct oom and sched
10317 // adjustments.
10318 updateOomAdjLocked();
10319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 return;
10321 }
10322 r = mOrderedBroadcasts.get(0);
10323 boolean forceReceive = false;
10324
10325 // Ensure that even if something goes awry with the timeout
10326 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010327 // and continue to make progress.
10328 //
10329 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10330 // receivers don't get executed with with timeouts. They're intended for
10331 // one time heavy lifting after system upgrades and can take
10332 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010334 if (mSystemReady && r.dispatchTime > 0) {
10335 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336 if ((numReceivers > 0) &&
10337 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010338 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 + " now=" + now
10340 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010341 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010342 + " intent=" + r.intent
10343 + " numReceivers=" + numReceivers
10344 + " nextReceiver=" + r.nextReceiver
10345 + " state=" + r.state);
10346 broadcastTimeout(); // forcibly finish this broadcast
10347 forceReceive = true;
10348 r.state = BroadcastRecord.IDLE;
10349 }
10350 }
10351
10352 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010353 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 "processNextBroadcast() called when not idle (state="
10355 + r.state + ")");
10356 return;
10357 }
10358
10359 if (r.receivers == null || r.nextReceiver >= numReceivers
10360 || r.resultAbort || forceReceive) {
10361 // No more receivers for this broadcast! Send the final
10362 // result if requested...
10363 if (r.resultTo != null) {
10364 try {
10365 if (DEBUG_BROADCAST) {
10366 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010367 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 + " seq=" + seq + " app=" + r.callerApp);
10369 }
10370 performReceive(r.callerApp, r.resultTo,
10371 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010372 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010374 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 }
10376 }
10377
Joe Onorato8a9b2202010-02-26 18:56:32 -080010378 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10380
Joe Onorato8a9b2202010-02-26 18:56:32 -080010381 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010382 + r);
10383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010385 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010386 mOrderedBroadcasts.remove(0);
10387 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010388 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389 continue;
10390 }
10391 } while (r == null);
10392
10393 // Get the next receiver...
10394 int recIdx = r.nextReceiver++;
10395
10396 // Keep track of when this receiver started, and make sure there
10397 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010398 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010400 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010401
Joe Onorato8a9b2202010-02-26 18:56:32 -080010402 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010403 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010404 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010406 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010408 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010409 }
10410
10411 Object nextReceiver = r.receivers.get(recIdx);
10412 if (nextReceiver instanceof BroadcastFilter) {
10413 // Simple case: this is a registered receiver who gets
10414 // a direct call.
10415 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010416 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010417 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418 + filter + ": " + r);
10419 deliverToRegisteredReceiver(r, filter, r.ordered);
10420 if (r.receiver == null || !r.ordered) {
10421 // The receiver has already finished, so schedule to
10422 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010423 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10424 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 r.state = BroadcastRecord.IDLE;
10426 scheduleBroadcastsLocked();
10427 }
10428 return;
10429 }
10430
10431 // Hard case: need to instantiate the receiver, possibly
10432 // starting its application process to host it.
10433
10434 ResolveInfo info =
10435 (ResolveInfo)nextReceiver;
10436
10437 boolean skip = false;
10438 int perm = checkComponentPermission(info.activityInfo.permission,
10439 r.callingPid, r.callingUid,
10440 info.activityInfo.exported
10441 ? -1 : info.activityInfo.applicationInfo.uid);
10442 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010443 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010444 + r.intent.toString()
10445 + " from " + r.callerPackage + " (pid=" + r.callingPid
10446 + ", uid=" + r.callingUid + ")"
10447 + " requires " + info.activityInfo.permission
10448 + " due to receiver " + info.activityInfo.packageName
10449 + "/" + info.activityInfo.name);
10450 skip = true;
10451 }
10452 if (r.callingUid != Process.SYSTEM_UID &&
10453 r.requiredPermission != null) {
10454 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010455 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 checkPermission(r.requiredPermission,
10457 info.activityInfo.applicationInfo.packageName);
10458 } catch (RemoteException e) {
10459 perm = PackageManager.PERMISSION_DENIED;
10460 }
10461 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010462 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 + r.intent + " to "
10464 + info.activityInfo.applicationInfo.packageName
10465 + " requires " + r.requiredPermission
10466 + " due to sender " + r.callerPackage
10467 + " (uid " + r.callingUid + ")");
10468 skip = true;
10469 }
10470 }
10471 if (r.curApp != null && r.curApp.crashing) {
10472 // If the target process is crashing, just skip it.
10473 skip = true;
10474 }
10475
10476 if (skip) {
10477 r.receiver = null;
10478 r.curFilter = null;
10479 r.state = BroadcastRecord.IDLE;
10480 scheduleBroadcastsLocked();
10481 return;
10482 }
10483
10484 r.state = BroadcastRecord.APP_RECEIVE;
10485 String targetProcess = info.activityInfo.processName;
10486 r.curComponent = new ComponentName(
10487 info.activityInfo.applicationInfo.packageName,
10488 info.activityInfo.name);
10489 r.curReceiver = info.activityInfo;
10490
10491 // Is this receiver's application already running?
10492 ProcessRecord app = getProcessRecordLocked(targetProcess,
10493 info.activityInfo.applicationInfo.uid);
10494 if (app != null && app.thread != null) {
10495 try {
10496 processCurBroadcastLocked(r, app);
10497 return;
10498 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010499 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 + r.curComponent, e);
10501 }
10502
10503 // If a dead object exception was thrown -- fall through to
10504 // restart the application.
10505 }
10506
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010507 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 if ((r.curApp=startProcessLocked(targetProcess,
10509 info.activityInfo.applicationInfo, true,
10510 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010511 "broadcast", r.curComponent,
10512 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10513 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 // Ah, this recipient is unavailable. Finish it if necessary,
10515 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010516 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517 + info.activityInfo.applicationInfo.packageName + "/"
10518 + info.activityInfo.applicationInfo.uid + " for broadcast "
10519 + r.intent + ": process is bad");
10520 logBroadcastReceiverDiscard(r);
10521 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10522 r.resultExtras, r.resultAbort, true);
10523 scheduleBroadcastsLocked();
10524 r.state = BroadcastRecord.IDLE;
10525 return;
10526 }
10527
10528 mPendingBroadcast = r;
10529 }
10530 }
10531
10532 // =========================================================
10533 // INSTRUMENTATION
10534 // =========================================================
10535
10536 public boolean startInstrumentation(ComponentName className,
10537 String profileFile, int flags, Bundle arguments,
10538 IInstrumentationWatcher watcher) {
10539 // Refuse possible leaked file descriptors
10540 if (arguments != null && arguments.hasFileDescriptors()) {
10541 throw new IllegalArgumentException("File descriptors passed in Bundle");
10542 }
10543
10544 synchronized(this) {
10545 InstrumentationInfo ii = null;
10546 ApplicationInfo ai = null;
10547 try {
10548 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010549 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010551 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 } catch (PackageManager.NameNotFoundException e) {
10553 }
10554 if (ii == null) {
10555 reportStartInstrumentationFailure(watcher, className,
10556 "Unable to find instrumentation info for: " + className);
10557 return false;
10558 }
10559 if (ai == null) {
10560 reportStartInstrumentationFailure(watcher, className,
10561 "Unable to find instrumentation target package: " + ii.targetPackage);
10562 return false;
10563 }
10564
10565 int match = mContext.getPackageManager().checkSignatures(
10566 ii.targetPackage, ii.packageName);
10567 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10568 String msg = "Permission Denial: starting instrumentation "
10569 + className + " from pid="
10570 + Binder.getCallingPid()
10571 + ", uid=" + Binder.getCallingPid()
10572 + " not allowed because package " + ii.packageName
10573 + " does not have a signature matching the target "
10574 + ii.targetPackage;
10575 reportStartInstrumentationFailure(watcher, className, msg);
10576 throw new SecurityException(msg);
10577 }
10578
10579 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010580 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 ProcessRecord app = addAppLocked(ai);
10582 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010583 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 app.instrumentationProfileFile = profileFile;
10585 app.instrumentationArguments = arguments;
10586 app.instrumentationWatcher = watcher;
10587 app.instrumentationResultClass = className;
10588 Binder.restoreCallingIdentity(origId);
10589 }
10590
10591 return true;
10592 }
10593
10594 /**
10595 * Report errors that occur while attempting to start Instrumentation. Always writes the
10596 * error to the logs, but if somebody is watching, send the report there too. This enables
10597 * the "am" command to report errors with more information.
10598 *
10599 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10600 * @param cn The component name of the instrumentation.
10601 * @param report The error report.
10602 */
10603 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10604 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010605 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010606 try {
10607 if (watcher != null) {
10608 Bundle results = new Bundle();
10609 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10610 results.putString("Error", report);
10611 watcher.instrumentationStatus(cn, -1, results);
10612 }
10613 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010614 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 }
10616 }
10617
10618 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10619 if (app.instrumentationWatcher != null) {
10620 try {
10621 // NOTE: IInstrumentationWatcher *must* be oneway here
10622 app.instrumentationWatcher.instrumentationFinished(
10623 app.instrumentationClass,
10624 resultCode,
10625 results);
10626 } catch (RemoteException e) {
10627 }
10628 }
10629 app.instrumentationWatcher = null;
10630 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010631 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 app.instrumentationProfileFile = null;
10633 app.instrumentationArguments = null;
10634
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010635 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636 }
10637
10638 public void finishInstrumentation(IApplicationThread target,
10639 int resultCode, Bundle results) {
10640 // Refuse possible leaked file descriptors
10641 if (results != null && results.hasFileDescriptors()) {
10642 throw new IllegalArgumentException("File descriptors passed in Intent");
10643 }
10644
10645 synchronized(this) {
10646 ProcessRecord app = getRecordForAppLocked(target);
10647 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010648 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 return;
10650 }
10651 final long origId = Binder.clearCallingIdentity();
10652 finishInstrumentationLocked(app, resultCode, results);
10653 Binder.restoreCallingIdentity(origId);
10654 }
10655 }
10656
10657 // =========================================================
10658 // CONFIGURATION
10659 // =========================================================
10660
10661 public ConfigurationInfo getDeviceConfigurationInfo() {
10662 ConfigurationInfo config = new ConfigurationInfo();
10663 synchronized (this) {
10664 config.reqTouchScreen = mConfiguration.touchscreen;
10665 config.reqKeyboardType = mConfiguration.keyboard;
10666 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010667 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10668 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010669 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10670 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010671 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10672 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10674 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010675 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 }
10677 return config;
10678 }
10679
10680 public Configuration getConfiguration() {
10681 Configuration ci;
10682 synchronized(this) {
10683 ci = new Configuration(mConfiguration);
10684 }
10685 return ci;
10686 }
10687
10688 public void updateConfiguration(Configuration values) {
10689 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10690 "updateConfiguration()");
10691
10692 synchronized(this) {
10693 if (values == null && mWindowManager != null) {
10694 // sentinel: fetch the current configuration from the window manager
10695 values = mWindowManager.computeNewConfiguration();
10696 }
10697
10698 final long origId = Binder.clearCallingIdentity();
10699 updateConfigurationLocked(values, null);
10700 Binder.restoreCallingIdentity(origId);
10701 }
10702 }
10703
10704 /**
10705 * Do either or both things: (1) change the current configuration, and (2)
10706 * make sure the given activity is running with the (now) current
10707 * configuration. Returns true if the activity has been left running, or
10708 * false if <var>starting</var> is being destroyed to match the new
10709 * configuration.
10710 */
10711 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010712 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 int changes = 0;
10714
10715 boolean kept = true;
10716
10717 if (values != null) {
10718 Configuration newConfig = new Configuration(mConfiguration);
10719 changes = newConfig.updateFrom(values);
10720 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010721 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010722 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010723 }
10724
Doug Zongker2bec3d42009-12-04 12:52:44 -080010725 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726
10727 if (values.locale != null) {
10728 saveLocaleLocked(values.locale,
10729 !values.locale.equals(mConfiguration.locale),
10730 values.userSetLocale);
10731 }
10732
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010733 mConfigurationSeq++;
10734 if (mConfigurationSeq <= 0) {
10735 mConfigurationSeq = 1;
10736 }
10737 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010738 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010739 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010740
10741 AttributeCache ac = AttributeCache.instance();
10742 if (ac != null) {
10743 ac.updateConfiguration(mConfiguration);
10744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010745
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010746 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10747 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10748 msg.obj = new Configuration(mConfiguration);
10749 mHandler.sendMessage(msg);
10750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010752 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10753 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 try {
10755 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010756 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010757 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758 app.thread.scheduleConfigurationChanged(mConfiguration);
10759 }
10760 } catch (Exception e) {
10761 }
10762 }
10763 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010764 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10765 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10767 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010768 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10769 broadcastIntentLocked(null, null,
10770 new Intent(Intent.ACTION_LOCALE_CHANGED),
10771 null, null, 0, null, null,
10772 null, false, false, MY_PID, Process.SYSTEM_UID);
10773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 }
10775 }
10776
10777 if (changes != 0 && starting == null) {
10778 // If the configuration changed, and the caller is not already
10779 // in the process of starting an activity, then find the top
10780 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010781 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 }
10783
10784 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010785 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 if (kept) {
10787 // If this didn't result in the starting activity being
10788 // destroyed, then we need to make sure at this point that all
10789 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010790 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010792 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010793 }
10794 }
10795
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010796 if (values != null && mWindowManager != null) {
10797 mWindowManager.setNewConfiguration(mConfiguration);
10798 }
10799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 return kept;
10801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010802
10803 /**
10804 * Save the locale. You must be inside a synchronized (this) block.
10805 */
10806 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10807 if(isDiff) {
10808 SystemProperties.set("user.language", l.getLanguage());
10809 SystemProperties.set("user.region", l.getCountry());
10810 }
10811
10812 if(isPersist) {
10813 SystemProperties.set("persist.sys.language", l.getLanguage());
10814 SystemProperties.set("persist.sys.country", l.getCountry());
10815 SystemProperties.set("persist.sys.localevar", l.getVariant());
10816 }
10817 }
10818
10819 // =========================================================
10820 // LIFETIME MANAGEMENT
10821 // =========================================================
10822
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010823 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10824 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010826 // This adjustment has already been computed. If we are calling
10827 // from the top, we may have already computed our adjustment with
10828 // an earlier hidden adjustment that isn't really for us... if
10829 // so, use the new hidden adjustment.
10830 if (!recursed && app.hidden) {
10831 app.curAdj = hiddenAdj;
10832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 return app.curAdj;
10834 }
10835
10836 if (app.thread == null) {
10837 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010838 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 return (app.curAdj=EMPTY_APP_ADJ);
10840 }
10841
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010842 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10843 // The max adjustment doesn't allow this app to be anything
10844 // below foreground, so it is not worth doing work for it.
10845 app.adjType = "fixed";
10846 app.adjSeq = mAdjSeq;
10847 app.curRawAdj = app.maxAdj;
10848 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10849 return (app.curAdj=app.maxAdj);
10850 }
10851
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010852 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010853 app.adjSource = null;
10854 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010855 app.empty = false;
10856 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857
The Android Open Source Project4df24232009-03-05 14:34:35 -080010858 // Determine the importance of the process, starting with most
10859 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010861 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010863 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 // The last app on the list is the foreground app.
10865 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010866 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010867 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010868 } else if (app.instrumentationClass != null) {
10869 // Don't want to kill running instrumentation.
10870 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010871 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010872 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010873 } else if (app.persistentActivities > 0) {
10874 // Special persistent activities... shouldn't be used these days.
10875 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010876 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010877 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 } else if (app.curReceiver != null ||
10879 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10880 // An app that is currently receiving a broadcast also
10881 // counts as being in the foreground.
10882 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010883 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010884 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010885 } else if (app.executingServices.size() > 0) {
10886 // An app that is currently executing a service callback also
10887 // counts as being in the foreground.
10888 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010889 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010890 app.adjType = "exec-service";
10891 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010893 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010894 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010895 app.adjType = "foreground-service";
10896 } else if (app.forcingToForeground != null) {
10897 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010898 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010899 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010900 app.adjType = "force-foreground";
10901 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010902 } else if (app == mHeavyWeightProcess) {
10903 // We don't want to kill the current heavy-weight process.
10904 adj = HEAVY_WEIGHT_APP_ADJ;
10905 schedGroup = Process.THREAD_GROUP_DEFAULT;
10906 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010907 } else if (app == mHomeProcess) {
10908 // This process is hosting what we currently consider to be the
10909 // home app, so we don't want to let it go into the background.
10910 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010911 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010912 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 } else if ((N=app.activities.size()) != 0) {
10914 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010915 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010917 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010918 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010919 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010921 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010923 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010925 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010926 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 break;
10928 }
10929 }
10930 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010931 // A very not-needed process. If this is lower in the lru list,
10932 // we will push it in to the empty bucket.
10933 app.hidden = true;
10934 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010935 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010936 adj = hiddenAdj;
10937 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 }
10939
Joe Onorato8a9b2202010-02-26 18:56:32 -080010940 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010941
The Android Open Source Project4df24232009-03-05 14:34:35 -080010942 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 // there are applications dependent on our services or providers, but
10944 // this gives us a baseline and makes sure we don't get into an
10945 // infinite recursion.
10946 app.adjSeq = mAdjSeq;
10947 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948
Christopher Tate6fa95972009-06-05 18:43:55 -070010949 if (mBackupTarget != null && app == mBackupTarget.app) {
10950 // If possible we want to avoid killing apps while they're being backed up
10951 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010952 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010953 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010954 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010955 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010956 }
10957 }
10958
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010959 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10960 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 final long now = SystemClock.uptimeMillis();
10962 // This process is more important if the top activity is
10963 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010964 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010965 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010966 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010967 if (s.startRequested) {
10968 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
10969 // This service has seen some activity within
10970 // recent memory, so we will keep its process ahead
10971 // of the background processes.
10972 if (adj > SECONDARY_SERVER_ADJ) {
10973 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010974 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010975 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 }
10977 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080010978 // If we have let the service slide into the background
10979 // state, still have some text describing what it is doing
10980 // even though the service no longer has an impact.
10981 if (adj > SECONDARY_SERVER_ADJ) {
10982 app.adjType = "started-bg-services";
10983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010984 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010985 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
10986 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 Iterator<ConnectionRecord> kt
10988 = s.connections.values().iterator();
10989 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
10990 // XXX should compute this based on the max of
10991 // all connected clients.
10992 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070010993 if (cr.binding.client == app) {
10994 // Binding to ourself is not interesting.
10995 continue;
10996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10998 ProcessRecord client = cr.binding.client;
10999 int myHiddenAdj = hiddenAdj;
11000 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011001 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 myHiddenAdj = client.hiddenAdj;
11003 } else {
11004 myHiddenAdj = VISIBLE_APP_ADJ;
11005 }
11006 }
11007 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011008 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011010 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011012 if (!client.hidden) {
11013 app.hidden = false;
11014 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011015 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011016 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11017 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011018 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011019 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011021 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11022 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11023 schedGroup = Process.THREAD_GROUP_DEFAULT;
11024 }
11025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011027 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011029 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 //}
11031 if (a != null && adj > FOREGROUND_APP_ADJ &&
11032 (a.state == ActivityState.RESUMED
11033 || a.state == ActivityState.PAUSING)) {
11034 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011035 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011036 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011037 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011038 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11039 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011040 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011041 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 }
11043 }
11044 }
11045 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011046
11047 // Finally, f this process has active services running in it, we
11048 // would like to avoid killing it unless it would prevent the current
11049 // application from running. By default we put the process in
11050 // with the rest of the background processes; as we scan through
11051 // its services we may bump it up from there.
11052 if (adj > hiddenAdj) {
11053 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011054 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011055 app.adjType = "bg-services";
11056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 }
11058
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011059 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11060 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011061 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011062 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11063 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011064 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 if (cpr.clients.size() != 0) {
11066 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11067 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11068 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011069 if (client == app) {
11070 // Being our own client is not interesting.
11071 continue;
11072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 int myHiddenAdj = hiddenAdj;
11074 if (myHiddenAdj > client.hiddenAdj) {
11075 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11076 myHiddenAdj = client.hiddenAdj;
11077 } else {
11078 myHiddenAdj = FOREGROUND_APP_ADJ;
11079 }
11080 }
11081 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011082 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083 if (adj > clientAdj) {
11084 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011085 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011086 if (!client.hidden) {
11087 app.hidden = false;
11088 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011089 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011090 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11091 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011092 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011093 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011095 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11096 schedGroup = Process.THREAD_GROUP_DEFAULT;
11097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 }
11099 }
11100 // If the provider has external (non-framework) process
11101 // dependencies, ensure that its adjustment is at least
11102 // FOREGROUND_APP_ADJ.
11103 if (cpr.externals != 0) {
11104 if (adj > FOREGROUND_APP_ADJ) {
11105 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011106 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011107 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011108 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011109 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 }
11111 }
11112 }
11113 }
11114
11115 app.curRawAdj = adj;
11116
Joe Onorato8a9b2202010-02-26 18:56:32 -080011117 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11119 if (adj > app.maxAdj) {
11120 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011121 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011122 schedGroup = Process.THREAD_GROUP_DEFAULT;
11123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 }
11125
11126 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011127 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 return adj;
11130 }
11131
11132 /**
11133 * Ask a given process to GC right now.
11134 */
11135 final void performAppGcLocked(ProcessRecord app) {
11136 try {
11137 app.lastRequestedGc = SystemClock.uptimeMillis();
11138 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011139 if (app.reportLowMemory) {
11140 app.reportLowMemory = false;
11141 app.thread.scheduleLowMemory();
11142 } else {
11143 app.thread.processInBackground();
11144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 }
11146 } catch (Exception e) {
11147 // whatever.
11148 }
11149 }
11150
11151 /**
11152 * Returns true if things are idle enough to perform GCs.
11153 */
Josh Bartel7f208742010-02-25 11:01:44 -060011154 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 return mParallelBroadcasts.size() == 0
11156 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011157 && (mSleeping || (mMainStack.mResumedActivity != null &&
11158 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 }
11160
11161 /**
11162 * Perform GCs on all processes that are waiting for it, but only
11163 * if things are idle.
11164 */
11165 final void performAppGcsLocked() {
11166 final int N = mProcessesToGc.size();
11167 if (N <= 0) {
11168 return;
11169 }
Josh Bartel7f208742010-02-25 11:01:44 -060011170 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 while (mProcessesToGc.size() > 0) {
11172 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011173 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011174 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11175 <= SystemClock.uptimeMillis()) {
11176 // To avoid spamming the system, we will GC processes one
11177 // at a time, waiting a few seconds between each.
11178 performAppGcLocked(proc);
11179 scheduleAppGcsLocked();
11180 return;
11181 } else {
11182 // It hasn't been long enough since we last GCed this
11183 // process... put it in the list to wait for its time.
11184 addProcessToGcListLocked(proc);
11185 break;
11186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 }
11188 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011189
11190 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 }
11192 }
11193
11194 /**
11195 * If all looks good, perform GCs on all processes waiting for them.
11196 */
11197 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011198 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 performAppGcsLocked();
11200 return;
11201 }
11202 // Still not idle, wait some more.
11203 scheduleAppGcsLocked();
11204 }
11205
11206 /**
11207 * Schedule the execution of all pending app GCs.
11208 */
11209 final void scheduleAppGcsLocked() {
11210 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011211
11212 if (mProcessesToGc.size() > 0) {
11213 // Schedule a GC for the time to the next process.
11214 ProcessRecord proc = mProcessesToGc.get(0);
11215 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11216
11217 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11218 long now = SystemClock.uptimeMillis();
11219 if (when < (now+GC_TIMEOUT)) {
11220 when = now + GC_TIMEOUT;
11221 }
11222 mHandler.sendMessageAtTime(msg, when);
11223 }
11224 }
11225
11226 /**
11227 * Add a process to the array of processes waiting to be GCed. Keeps the
11228 * list in sorted order by the last GC time. The process can't already be
11229 * on the list.
11230 */
11231 final void addProcessToGcListLocked(ProcessRecord proc) {
11232 boolean added = false;
11233 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11234 if (mProcessesToGc.get(i).lastRequestedGc <
11235 proc.lastRequestedGc) {
11236 added = true;
11237 mProcessesToGc.add(i+1, proc);
11238 break;
11239 }
11240 }
11241 if (!added) {
11242 mProcessesToGc.add(0, proc);
11243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011244 }
11245
11246 /**
11247 * Set up to ask a process to GC itself. This will either do it
11248 * immediately, or put it on the list of processes to gc the next
11249 * time things are idle.
11250 */
11251 final void scheduleAppGcLocked(ProcessRecord app) {
11252 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011253 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 return;
11255 }
11256 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011257 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 scheduleAppGcsLocked();
11259 }
11260 }
11261
11262 private final boolean updateOomAdjLocked(
11263 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11264 app.hiddenAdj = hiddenAdj;
11265
11266 if (app.thread == null) {
11267 return true;
11268 }
11269
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011270 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011272 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 if (app.curRawAdj != app.setRawAdj) {
11274 if (app.curRawAdj > FOREGROUND_APP_ADJ
11275 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11276 // If this app is transitioning from foreground to
11277 // non-foreground, have it do a gc.
11278 scheduleAppGcLocked(app);
11279 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11280 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11281 // Likewise do a gc when an app is moving in to the
11282 // background (such as a service stopping).
11283 scheduleAppGcLocked(app);
11284 }
11285 app.setRawAdj = app.curRawAdj;
11286 }
11287 if (adj != app.setAdj) {
11288 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011289 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011290 TAG, "Set app " + app.processName +
11291 " oom adj to " + adj);
11292 app.setAdj = adj;
11293 } else {
11294 return false;
11295 }
11296 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011297 if (app.setSchedGroup != app.curSchedGroup) {
11298 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011299 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011300 "Setting process group of " + app.processName
11301 + " to " + app.curSchedGroup);
11302 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011303 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011304 try {
11305 Process.setProcessGroup(app.pid, app.curSchedGroup);
11306 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011307 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011308 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011309 e.printStackTrace();
11310 } finally {
11311 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011312 }
11313 }
11314 if (false) {
11315 if (app.thread != null) {
11316 try {
11317 app.thread.setSchedulingGroup(app.curSchedGroup);
11318 } catch (RemoteException e) {
11319 }
11320 }
11321 }
11322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011323 }
11324
11325 return true;
11326 }
11327
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011328 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011329 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011330 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011331 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011333 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 }
11335 }
11336 return resumedActivity;
11337 }
11338
11339 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011340 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11342 int curAdj = app.curAdj;
11343 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11344 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11345
11346 mAdjSeq++;
11347
11348 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11349 if (res) {
11350 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11351 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11352 if (nowHidden != wasHidden) {
11353 // Changed to/from hidden state, so apps after it in the LRU
11354 // list may also be changed.
11355 updateOomAdjLocked();
11356 }
11357 }
11358 return res;
11359 }
11360
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011361 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011363 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11365
11366 if (false) {
11367 RuntimeException e = new RuntimeException();
11368 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011369 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 }
11371
11372 mAdjSeq++;
11373
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011374 // Let's determine how many processes we have running vs.
11375 // how many slots we have for background processes; we may want
11376 // to put multiple processes in a slot of there are enough of
11377 // them.
11378 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11379 int factor = (mLruProcesses.size()-4)/numSlots;
11380 if (factor < 1) factor = 1;
11381 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011382 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 // First try updating the OOM adjustment for each of the
11385 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011386 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11388 while (i > 0) {
11389 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011390 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011391 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011392 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011393 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011395 step++;
11396 if (step >= factor) {
11397 step = 0;
11398 curHiddenAdj++;
11399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011401 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011402 if (!app.killedBackground) {
11403 numHidden++;
11404 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011405 Slog.i(TAG, "No longer want " + app.processName
11406 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011407 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11408 app.processName, app.setAdj, "too many background");
11409 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011410 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011411 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011412 }
11413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 } else {
11415 didOomAdj = false;
11416 }
11417 }
11418
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011419 // If we return false, we will fall back on killing processes to
11420 // have a fixed limit. Do this if a limit has been requested; else
11421 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11423 }
11424
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011425 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 synchronized (this) {
11427 int i;
11428
11429 // First remove any unused application processes whose package
11430 // has been removed.
11431 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11432 final ProcessRecord app = mRemovedProcesses.get(i);
11433 if (app.activities.size() == 0
11434 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011435 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 TAG, "Exiting empty application process "
11437 + app.processName + " ("
11438 + (app.thread != null ? app.thread.asBinder() : null)
11439 + ")\n");
11440 if (app.pid > 0 && app.pid != MY_PID) {
11441 Process.killProcess(app.pid);
11442 } else {
11443 try {
11444 app.thread.scheduleExit();
11445 } catch (Exception e) {
11446 // Ignore exceptions.
11447 }
11448 }
11449 cleanUpApplicationRecordLocked(app, false, -1);
11450 mRemovedProcesses.remove(i);
11451
11452 if (app.persistent) {
11453 if (app.persistent) {
11454 addAppLocked(app.info);
11455 }
11456 }
11457 }
11458 }
11459
11460 // Now try updating the OOM adjustment for each of the
11461 // application processes based on their current state.
11462 // If the setOomAdj() API is not supported, then go with our
11463 // back-up plan...
11464 if (!updateOomAdjLocked()) {
11465
11466 // Count how many processes are running services.
11467 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011468 for (i=mLruProcesses.size()-1; i>=0; i--) {
11469 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470
11471 if (app.persistent || app.services.size() != 0
11472 || app.curReceiver != null
11473 || app.persistentActivities > 0) {
11474 // Don't count processes holding services against our
11475 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011476 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 TAG, "Not trimming app " + app + " with services: "
11478 + app.services);
11479 numServiceProcs++;
11480 }
11481 }
11482
11483 int curMaxProcs = mProcessLimit;
11484 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11485 if (mAlwaysFinishActivities) {
11486 curMaxProcs = 1;
11487 }
11488 curMaxProcs += numServiceProcs;
11489
11490 // Quit as many processes as we can to get down to the desired
11491 // process count. First remove any processes that no longer
11492 // have activites running in them.
11493 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011494 i<mLruProcesses.size()
11495 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011496 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011497 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 // Quit an application only if it is not currently
11499 // running any activities.
11500 if (!app.persistent && app.activities.size() == 0
11501 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011502 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 TAG, "Exiting empty application process "
11504 + app.processName + " ("
11505 + (app.thread != null ? app.thread.asBinder() : null)
11506 + ")\n");
11507 if (app.pid > 0 && app.pid != MY_PID) {
11508 Process.killProcess(app.pid);
11509 } else {
11510 try {
11511 app.thread.scheduleExit();
11512 } catch (Exception e) {
11513 // Ignore exceptions.
11514 }
11515 }
11516 // todo: For now we assume the application is not buggy
11517 // or evil, and will quit as a result of our request.
11518 // Eventually we need to drive this off of the death
11519 // notification, and kill the process if it takes too long.
11520 cleanUpApplicationRecordLocked(app, false, i);
11521 i--;
11522 }
11523 }
11524
11525 // If we still have too many processes, now from the least
11526 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011527 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011528 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011529 " of " + curMaxProcs + " processes");
11530 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011531 i<mLruProcesses.size()
11532 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011534 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011535 // Quit the application only if we have a state saved for
11536 // all of its activities.
11537 boolean canQuit = !app.persistent && app.curReceiver == null
11538 && app.services.size() == 0
11539 && app.persistentActivities == 0;
11540 int NUMA = app.activities.size();
11541 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011542 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 TAG, "Looking to quit " + app.processName);
11544 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011545 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011546 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 TAG, " " + r.intent.getComponent().flattenToShortString()
11548 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11549 canQuit = (r.haveState || !r.stateNotNeeded)
11550 && !r.visible && r.stopped;
11551 }
11552 if (canQuit) {
11553 // Finish all of the activities, and then the app itself.
11554 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011555 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011557 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011558 }
11559 r.resultTo = null;
11560 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011561 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562 + app.processName + " ("
11563 + (app.thread != null ? app.thread.asBinder() : null)
11564 + ")\n");
11565 if (app.pid > 0 && app.pid != MY_PID) {
11566 Process.killProcess(app.pid);
11567 } else {
11568 try {
11569 app.thread.scheduleExit();
11570 } catch (Exception e) {
11571 // Ignore exceptions.
11572 }
11573 }
11574 // todo: For now we assume the application is not buggy
11575 // or evil, and will quit as a result of our request.
11576 // Eventually we need to drive this off of the death
11577 // notification, and kill the process if it takes too long.
11578 cleanUpApplicationRecordLocked(app, false, i);
11579 i--;
11580 //dump();
11581 }
11582 }
11583
11584 }
11585
11586 int curMaxActivities = MAX_ACTIVITIES;
11587 if (mAlwaysFinishActivities) {
11588 curMaxActivities = 1;
11589 }
11590
11591 // Finally, if there are too many activities now running, try to
11592 // finish as many as we can to get back down to the limit.
11593 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011594 i<mMainStack.mLRUActivities.size()
11595 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011597 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011598 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599
11600 // We can finish this one if we have its icicle saved and
11601 // it is not persistent.
11602 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11603 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011604 final int origSize = mMainStack.mLRUActivities.size();
11605 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011606
11607 // This will remove it from the LRU list, so keep
11608 // our index at the same value. Note that this check to
11609 // see if the size changes is just paranoia -- if
11610 // something unexpected happens, we don't want to end up
11611 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011612 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 i--;
11614 }
11615 }
11616 }
11617 }
11618 }
11619
11620 /** This method sends the specified signal to each of the persistent apps */
11621 public void signalPersistentProcesses(int sig) throws RemoteException {
11622 if (sig != Process.SIGNAL_USR1) {
11623 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11624 }
11625
11626 synchronized (this) {
11627 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11628 != PackageManager.PERMISSION_GRANTED) {
11629 throw new SecurityException("Requires permission "
11630 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11631 }
11632
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011633 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11634 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 if (r.thread != null && r.persistent) {
11636 Process.sendSignal(r.pid, sig);
11637 }
11638 }
11639 }
11640 }
11641
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011642 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011643 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011644
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011645 try {
11646 synchronized (this) {
11647 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11648 // its own permission.
11649 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11650 != PackageManager.PERMISSION_GRANTED) {
11651 throw new SecurityException("Requires permission "
11652 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011653 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011654
11655 if (start && fd == null) {
11656 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011657 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011658
11659 ProcessRecord proc = null;
11660 try {
11661 int pid = Integer.parseInt(process);
11662 synchronized (mPidsSelfLocked) {
11663 proc = mPidsSelfLocked.get(pid);
11664 }
11665 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011666 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011667
11668 if (proc == null) {
11669 HashMap<String, SparseArray<ProcessRecord>> all
11670 = mProcessNames.getMap();
11671 SparseArray<ProcessRecord> procs = all.get(process);
11672 if (procs != null && procs.size() > 0) {
11673 proc = procs.valueAt(0);
11674 }
11675 }
11676
11677 if (proc == null || proc.thread == null) {
11678 throw new IllegalArgumentException("Unknown process: " + process);
11679 }
11680
11681 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11682 if (isSecure) {
11683 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11684 throw new SecurityException("Process not debuggable: " + proc);
11685 }
11686 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011687
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011688 proc.thread.profilerControl(start, path, fd);
11689 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011690 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011691 }
11692 } catch (RemoteException e) {
11693 throw new IllegalStateException("Process disappeared");
11694 } finally {
11695 if (fd != null) {
11696 try {
11697 fd.close();
11698 } catch (IOException e) {
11699 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011700 }
11701 }
11702 }
11703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011704 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11705 public void monitor() {
11706 synchronized (this) { }
11707 }
11708}