blob: 162fffef5d2b0c3f562d2a83b62d80f30eab794a [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 Hackborn9acc0302009-08-25 00:27:12 -07003574 broadcastIntentLocked(null, null,
3575 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3576 null, null, 0, null, null,
3577 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3578 false, false, MY_PID, Process.SYSTEM_UID);
3579 }
3580 }
3581 }
3582
3583 final void ensureBootCompleted() {
3584 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003585 boolean enableScreen;
3586 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003587 booting = mBooting;
3588 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003589 enableScreen = !mBooted;
3590 mBooted = true;
3591 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003592
3593 if (booting) {
3594 finishBooting();
3595 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003596
3597 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003598 enableScreenAfterBoot();
3599 }
3600 }
3601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003602 public final void activityPaused(IBinder token, Bundle icicle) {
3603 // Refuse possible leaked file descriptors
3604 if (icicle != null && icicle.hasFileDescriptors()) {
3605 throw new IllegalArgumentException("File descriptors passed in Bundle");
3606 }
3607
3608 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003609 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 Binder.restoreCallingIdentity(origId);
3611 }
3612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 public final void activityStopped(IBinder token, Bitmap thumbnail,
3614 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003615 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 TAG, "Activity stopped: token=" + token);
3617
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003618 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619
3620 final long origId = Binder.clearCallingIdentity();
3621
3622 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003623 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003625 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 r.thumbnail = thumbnail;
3627 r.description = description;
3628 r.stopped = true;
3629 r.state = ActivityState.STOPPED;
3630 if (!r.finishing) {
3631 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003632 r.stack.destroyActivityLocked(r, true);
3633 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 }
3635 }
3636 }
3637 }
3638
3639 if (r != null) {
3640 sendPendingThumbnail(r, null, null, null, false);
3641 }
3642
3643 trimApplications();
3644
3645 Binder.restoreCallingIdentity(origId);
3646 }
3647
3648 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003649 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003650 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 }
3652
3653 public String getCallingPackage(IBinder token) {
3654 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003655 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003656 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 }
3658 }
3659
3660 public ComponentName getCallingActivity(IBinder token) {
3661 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003662 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 return r != null ? r.intent.getComponent() : null;
3664 }
3665 }
3666
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003667 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003668 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003670 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 if (r != null) {
3672 return r.resultTo;
3673 }
3674 }
3675 return null;
3676 }
3677
3678 public ComponentName getActivityClassForToken(IBinder token) {
3679 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003680 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003682 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 return r.intent.getComponent();
3684 }
3685 return null;
3686 }
3687 }
3688
3689 public String getPackageForToken(IBinder token) {
3690 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003691 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003693 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 return r.packageName;
3695 }
3696 return null;
3697 }
3698 }
3699
3700 public IIntentSender getIntentSender(int type,
3701 String packageName, IBinder token, String resultWho,
3702 int requestCode, Intent intent, String resolvedType, int flags) {
3703 // Refuse possible leaked file descriptors
3704 if (intent != null && intent.hasFileDescriptors() == true) {
3705 throw new IllegalArgumentException("File descriptors passed in Intent");
3706 }
3707
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003708 if (type == INTENT_SENDER_BROADCAST) {
3709 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3710 throw new IllegalArgumentException(
3711 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3712 }
3713 }
3714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 synchronized(this) {
3716 int callingUid = Binder.getCallingUid();
3717 try {
3718 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3719 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003720 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 .getPackageUid(packageName);
3722 if (uid != Binder.getCallingUid()) {
3723 String msg = "Permission Denial: getIntentSender() from pid="
3724 + Binder.getCallingPid()
3725 + ", uid=" + Binder.getCallingUid()
3726 + ", (need uid=" + uid + ")"
3727 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003728 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 throw new SecurityException(msg);
3730 }
3731 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003732
3733 return getIntentSenderLocked(type, packageName, callingUid,
3734 token, resultWho, requestCode, intent, resolvedType, flags);
3735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 } catch (RemoteException e) {
3737 throw new SecurityException(e);
3738 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003739 }
3740 }
3741
3742 IIntentSender getIntentSenderLocked(int type,
3743 String packageName, int callingUid, IBinder token, String resultWho,
3744 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003745 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003746 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003747 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003748 if (index < 0) {
3749 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003751 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003752 if (activity.finishing) {
3753 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003755 }
3756
3757 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3758 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3759 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3760 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3761 |PendingIntent.FLAG_UPDATE_CURRENT);
3762
3763 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3764 type, packageName, activity, resultWho,
3765 requestCode, intent, resolvedType, flags);
3766 WeakReference<PendingIntentRecord> ref;
3767 ref = mIntentSenderRecords.get(key);
3768 PendingIntentRecord rec = ref != null ? ref.get() : null;
3769 if (rec != null) {
3770 if (!cancelCurrent) {
3771 if (updateCurrent) {
3772 rec.key.requestIntent.replaceExtras(intent);
3773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 return rec;
3775 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003776 rec.canceled = true;
3777 mIntentSenderRecords.remove(key);
3778 }
3779 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 return rec;
3781 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003782 rec = new PendingIntentRecord(this, key, callingUid);
3783 mIntentSenderRecords.put(key, rec.ref);
3784 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3785 if (activity.pendingResults == null) {
3786 activity.pendingResults
3787 = new HashSet<WeakReference<PendingIntentRecord>>();
3788 }
3789 activity.pendingResults.add(rec.ref);
3790 }
3791 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 }
3793
3794 public void cancelIntentSender(IIntentSender sender) {
3795 if (!(sender instanceof PendingIntentRecord)) {
3796 return;
3797 }
3798 synchronized(this) {
3799 PendingIntentRecord rec = (PendingIntentRecord)sender;
3800 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003801 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 .getPackageUid(rec.key.packageName);
3803 if (uid != Binder.getCallingUid()) {
3804 String msg = "Permission Denial: cancelIntentSender() from pid="
3805 + Binder.getCallingPid()
3806 + ", uid=" + Binder.getCallingUid()
3807 + " is not allowed to cancel packges "
3808 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003809 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 throw new SecurityException(msg);
3811 }
3812 } catch (RemoteException e) {
3813 throw new SecurityException(e);
3814 }
3815 cancelIntentSenderLocked(rec, true);
3816 }
3817 }
3818
3819 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3820 rec.canceled = true;
3821 mIntentSenderRecords.remove(rec.key);
3822 if (cleanActivity && rec.key.activity != null) {
3823 rec.key.activity.pendingResults.remove(rec.ref);
3824 }
3825 }
3826
3827 public String getPackageForIntentSender(IIntentSender pendingResult) {
3828 if (!(pendingResult instanceof PendingIntentRecord)) {
3829 return null;
3830 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003831 try {
3832 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3833 return res.key.packageName;
3834 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 }
3836 return null;
3837 }
3838
3839 public void setProcessLimit(int max) {
3840 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3841 "setProcessLimit()");
3842 mProcessLimit = max;
3843 }
3844
3845 public int getProcessLimit() {
3846 return mProcessLimit;
3847 }
3848
3849 void foregroundTokenDied(ForegroundToken token) {
3850 synchronized (ActivityManagerService.this) {
3851 synchronized (mPidsSelfLocked) {
3852 ForegroundToken cur
3853 = mForegroundProcesses.get(token.pid);
3854 if (cur != token) {
3855 return;
3856 }
3857 mForegroundProcesses.remove(token.pid);
3858 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3859 if (pr == null) {
3860 return;
3861 }
3862 pr.forcingToForeground = null;
3863 pr.foregroundServices = false;
3864 }
3865 updateOomAdjLocked();
3866 }
3867 }
3868
3869 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3870 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3871 "setProcessForeground()");
3872 synchronized(this) {
3873 boolean changed = false;
3874
3875 synchronized (mPidsSelfLocked) {
3876 ProcessRecord pr = mPidsSelfLocked.get(pid);
3877 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003878 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 return;
3880 }
3881 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3882 if (oldToken != null) {
3883 oldToken.token.unlinkToDeath(oldToken, 0);
3884 mForegroundProcesses.remove(pid);
3885 pr.forcingToForeground = null;
3886 changed = true;
3887 }
3888 if (isForeground && token != null) {
3889 ForegroundToken newToken = new ForegroundToken() {
3890 public void binderDied() {
3891 foregroundTokenDied(this);
3892 }
3893 };
3894 newToken.pid = pid;
3895 newToken.token = token;
3896 try {
3897 token.linkToDeath(newToken, 0);
3898 mForegroundProcesses.put(pid, newToken);
3899 pr.forcingToForeground = token;
3900 changed = true;
3901 } catch (RemoteException e) {
3902 // If the process died while doing this, we will later
3903 // do the cleanup with the process death link.
3904 }
3905 }
3906 }
3907
3908 if (changed) {
3909 updateOomAdjLocked();
3910 }
3911 }
3912 }
3913
3914 // =========================================================
3915 // PERMISSIONS
3916 // =========================================================
3917
3918 static class PermissionController extends IPermissionController.Stub {
3919 ActivityManagerService mActivityManagerService;
3920 PermissionController(ActivityManagerService activityManagerService) {
3921 mActivityManagerService = activityManagerService;
3922 }
3923
3924 public boolean checkPermission(String permission, int pid, int uid) {
3925 return mActivityManagerService.checkPermission(permission, pid,
3926 uid) == PackageManager.PERMISSION_GRANTED;
3927 }
3928 }
3929
3930 /**
3931 * This can be called with or without the global lock held.
3932 */
3933 int checkComponentPermission(String permission, int pid, int uid,
3934 int reqUid) {
3935 // We might be performing an operation on behalf of an indirect binder
3936 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3937 // client identity accordingly before proceeding.
3938 Identity tlsIdentity = sCallerIdentity.get();
3939 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003940 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3942 uid = tlsIdentity.uid;
3943 pid = tlsIdentity.pid;
3944 }
3945
3946 // Root, system server and our own process get to do everything.
3947 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3948 !Process.supportsProcesses()) {
3949 return PackageManager.PERMISSION_GRANTED;
3950 }
3951 // If the target requires a specific UID, always fail for others.
3952 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003953 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 return PackageManager.PERMISSION_DENIED;
3955 }
3956 if (permission == null) {
3957 return PackageManager.PERMISSION_GRANTED;
3958 }
3959 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003960 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 .checkUidPermission(permission, uid);
3962 } catch (RemoteException e) {
3963 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003964 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 }
3966 return PackageManager.PERMISSION_DENIED;
3967 }
3968
3969 /**
3970 * As the only public entry point for permissions checking, this method
3971 * can enforce the semantic that requesting a check on a null global
3972 * permission is automatically denied. (Internally a null permission
3973 * string is used when calling {@link #checkComponentPermission} in cases
3974 * when only uid-based security is needed.)
3975 *
3976 * This can be called with or without the global lock held.
3977 */
3978 public int checkPermission(String permission, int pid, int uid) {
3979 if (permission == null) {
3980 return PackageManager.PERMISSION_DENIED;
3981 }
3982 return checkComponentPermission(permission, pid, uid, -1);
3983 }
3984
3985 /**
3986 * Binder IPC calls go through the public entry point.
3987 * This can be called with or without the global lock held.
3988 */
3989 int checkCallingPermission(String permission) {
3990 return checkPermission(permission,
3991 Binder.getCallingPid(),
3992 Binder.getCallingUid());
3993 }
3994
3995 /**
3996 * This can be called with or without the global lock held.
3997 */
3998 void enforceCallingPermission(String permission, String func) {
3999 if (checkCallingPermission(permission)
4000 == PackageManager.PERMISSION_GRANTED) {
4001 return;
4002 }
4003
4004 String msg = "Permission Denial: " + func + " from pid="
4005 + Binder.getCallingPid()
4006 + ", uid=" + Binder.getCallingUid()
4007 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004008 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 throw new SecurityException(msg);
4010 }
4011
4012 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4013 ProviderInfo pi, int uid, int modeFlags) {
4014 try {
4015 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4016 if ((pi.readPermission != null) &&
4017 (pm.checkUidPermission(pi.readPermission, uid)
4018 != PackageManager.PERMISSION_GRANTED)) {
4019 return false;
4020 }
4021 }
4022 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4023 if ((pi.writePermission != null) &&
4024 (pm.checkUidPermission(pi.writePermission, uid)
4025 != PackageManager.PERMISSION_GRANTED)) {
4026 return false;
4027 }
4028 }
4029 return true;
4030 } catch (RemoteException e) {
4031 return false;
4032 }
4033 }
4034
4035 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4036 int modeFlags) {
4037 // Root gets to do everything.
4038 if (uid == 0 || !Process.supportsProcesses()) {
4039 return true;
4040 }
4041 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4042 if (perms == null) return false;
4043 UriPermission perm = perms.get(uri);
4044 if (perm == null) return false;
4045 return (modeFlags&perm.modeFlags) == modeFlags;
4046 }
4047
4048 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4049 // Another redirected-binder-call permissions check as in
4050 // {@link checkComponentPermission}.
4051 Identity tlsIdentity = sCallerIdentity.get();
4052 if (tlsIdentity != null) {
4053 uid = tlsIdentity.uid;
4054 pid = tlsIdentity.pid;
4055 }
4056
4057 // Our own process gets to do everything.
4058 if (pid == MY_PID) {
4059 return PackageManager.PERMISSION_GRANTED;
4060 }
4061 synchronized(this) {
4062 return checkUriPermissionLocked(uri, uid, modeFlags)
4063 ? PackageManager.PERMISSION_GRANTED
4064 : PackageManager.PERMISSION_DENIED;
4065 }
4066 }
4067
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004068 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004069 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4071 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4072 if (modeFlags == 0) {
4073 return;
4074 }
4075
Joe Onorato8a9b2202010-02-26 18:56:32 -08004076 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004077 "Requested grant " + targetPkg + " permission to " + uri);
4078
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004079 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004080
4081 // If this is not a content: uri, we can't do anything with it.
4082 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004083 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004084 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 return;
4086 }
4087
4088 String name = uri.getAuthority();
4089 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004090 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 if (cpr != null) {
4092 pi = cpr.info;
4093 } else {
4094 try {
4095 pi = pm.resolveContentProvider(name,
4096 PackageManager.GET_URI_PERMISSION_PATTERNS);
4097 } catch (RemoteException ex) {
4098 }
4099 }
4100 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004101 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 return;
4103 }
4104
4105 int targetUid;
4106 try {
4107 targetUid = pm.getPackageUid(targetPkg);
4108 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004109 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004110 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111 return;
4112 }
4113 } catch (RemoteException ex) {
4114 return;
4115 }
4116
4117 // First... does the target actually need this permission?
4118 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4119 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004120 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004121 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 return;
4123 }
4124
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004125 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 if (!pi.grantUriPermissions) {
4127 throw new SecurityException("Provider " + pi.packageName
4128 + "/" + pi.name
4129 + " does not allow granting of Uri permissions (uri "
4130 + uri + ")");
4131 }
4132 if (pi.uriPermissionPatterns != null) {
4133 final int N = pi.uriPermissionPatterns.length;
4134 boolean allowed = false;
4135 for (int i=0; i<N; i++) {
4136 if (pi.uriPermissionPatterns[i] != null
4137 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4138 allowed = true;
4139 break;
4140 }
4141 }
4142 if (!allowed) {
4143 throw new SecurityException("Provider " + pi.packageName
4144 + "/" + pi.name
4145 + " does not allow granting of permission to path of Uri "
4146 + uri);
4147 }
4148 }
4149
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004150 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 // this uri?
4152 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4153 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4154 throw new SecurityException("Uid " + callingUid
4155 + " does not have permission to uri " + uri);
4156 }
4157 }
4158
4159 // Okay! So here we are: the caller has the assumed permission
4160 // to the uri, and the target doesn't. Let's now give this to
4161 // the target.
4162
Joe Onorato8a9b2202010-02-26 18:56:32 -08004163 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004164 "Granting " + targetPkg + " permission to " + uri);
4165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 HashMap<Uri, UriPermission> targetUris
4167 = mGrantedUriPermissions.get(targetUid);
4168 if (targetUris == null) {
4169 targetUris = new HashMap<Uri, UriPermission>();
4170 mGrantedUriPermissions.put(targetUid, targetUris);
4171 }
4172
4173 UriPermission perm = targetUris.get(uri);
4174 if (perm == null) {
4175 perm = new UriPermission(targetUid, uri);
4176 targetUris.put(uri, perm);
4177
4178 }
4179 perm.modeFlags |= modeFlags;
4180 if (activity == null) {
4181 perm.globalModeFlags |= modeFlags;
4182 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4183 perm.readActivities.add(activity);
4184 if (activity.readUriPermissions == null) {
4185 activity.readUriPermissions = new HashSet<UriPermission>();
4186 }
4187 activity.readUriPermissions.add(perm);
4188 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4189 perm.writeActivities.add(activity);
4190 if (activity.writeUriPermissions == null) {
4191 activity.writeUriPermissions = new HashSet<UriPermission>();
4192 }
4193 activity.writeUriPermissions.add(perm);
4194 }
4195 }
4196
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004197 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004198 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 if (intent == null) {
4200 return;
4201 }
4202 Uri data = intent.getData();
4203 if (data == null) {
4204 return;
4205 }
4206 grantUriPermissionLocked(callingUid, targetPkg, data,
4207 intent.getFlags(), activity);
4208 }
4209
4210 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4211 Uri uri, int modeFlags) {
4212 synchronized(this) {
4213 final ProcessRecord r = getRecordForAppLocked(caller);
4214 if (r == null) {
4215 throw new SecurityException("Unable to find app for caller "
4216 + caller
4217 + " when granting permission to uri " + uri);
4218 }
4219 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004220 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 return;
4222 }
4223 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004224 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 return;
4226 }
4227
4228 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4229 null);
4230 }
4231 }
4232
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004233 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4235 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4236 HashMap<Uri, UriPermission> perms
4237 = mGrantedUriPermissions.get(perm.uid);
4238 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004239 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004240 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 perms.remove(perm.uri);
4242 if (perms.size() == 0) {
4243 mGrantedUriPermissions.remove(perm.uid);
4244 }
4245 }
4246 }
4247 }
4248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4250 int modeFlags) {
4251 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4252 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4253 if (modeFlags == 0) {
4254 return;
4255 }
4256
Joe Onorato8a9b2202010-02-26 18:56:32 -08004257 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004258 "Revoking all granted permissions to " + uri);
4259
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004260 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261
4262 final String authority = uri.getAuthority();
4263 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004264 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 if (cpr != null) {
4266 pi = cpr.info;
4267 } else {
4268 try {
4269 pi = pm.resolveContentProvider(authority,
4270 PackageManager.GET_URI_PERMISSION_PATTERNS);
4271 } catch (RemoteException ex) {
4272 }
4273 }
4274 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004275 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004276 return;
4277 }
4278
4279 // Does the caller have this permission on the URI?
4280 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4281 // Right now, if you are not the original owner of the permission,
4282 // you are not allowed to revoke it.
4283 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4284 throw new SecurityException("Uid " + callingUid
4285 + " does not have permission to uri " + uri);
4286 //}
4287 }
4288
4289 // Go through all of the permissions and remove any that match.
4290 final List<String> SEGMENTS = uri.getPathSegments();
4291 if (SEGMENTS != null) {
4292 final int NS = SEGMENTS.size();
4293 int N = mGrantedUriPermissions.size();
4294 for (int i=0; i<N; i++) {
4295 HashMap<Uri, UriPermission> perms
4296 = mGrantedUriPermissions.valueAt(i);
4297 Iterator<UriPermission> it = perms.values().iterator();
4298 toploop:
4299 while (it.hasNext()) {
4300 UriPermission perm = it.next();
4301 Uri targetUri = perm.uri;
4302 if (!authority.equals(targetUri.getAuthority())) {
4303 continue;
4304 }
4305 List<String> targetSegments = targetUri.getPathSegments();
4306 if (targetSegments == null) {
4307 continue;
4308 }
4309 if (targetSegments.size() < NS) {
4310 continue;
4311 }
4312 for (int j=0; j<NS; j++) {
4313 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4314 continue toploop;
4315 }
4316 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004317 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004318 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 perm.clearModes(modeFlags);
4320 if (perm.modeFlags == 0) {
4321 it.remove();
4322 }
4323 }
4324 if (perms.size() == 0) {
4325 mGrantedUriPermissions.remove(
4326 mGrantedUriPermissions.keyAt(i));
4327 N--;
4328 i--;
4329 }
4330 }
4331 }
4332 }
4333
4334 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4335 int modeFlags) {
4336 synchronized(this) {
4337 final ProcessRecord r = getRecordForAppLocked(caller);
4338 if (r == null) {
4339 throw new SecurityException("Unable to find app for caller "
4340 + caller
4341 + " when revoking permission to uri " + uri);
4342 }
4343 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004344 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 return;
4346 }
4347
4348 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4349 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4350 if (modeFlags == 0) {
4351 return;
4352 }
4353
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004354 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355
4356 final String authority = uri.getAuthority();
4357 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004358 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 if (cpr != null) {
4360 pi = cpr.info;
4361 } else {
4362 try {
4363 pi = pm.resolveContentProvider(authority,
4364 PackageManager.GET_URI_PERMISSION_PATTERNS);
4365 } catch (RemoteException ex) {
4366 }
4367 }
4368 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004369 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 return;
4371 }
4372
4373 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4374 }
4375 }
4376
4377 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4378 synchronized (this) {
4379 ProcessRecord app =
4380 who != null ? getRecordForAppLocked(who) : null;
4381 if (app == null) return;
4382
4383 Message msg = Message.obtain();
4384 msg.what = WAIT_FOR_DEBUGGER_MSG;
4385 msg.obj = app;
4386 msg.arg1 = waiting ? 1 : 0;
4387 mHandler.sendMessage(msg);
4388 }
4389 }
4390
4391 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4392 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004393 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004395 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 }
4397
4398 // =========================================================
4399 // TASK MANAGEMENT
4400 // =========================================================
4401
4402 public List getTasks(int maxNum, int flags,
4403 IThumbnailReceiver receiver) {
4404 ArrayList list = new ArrayList();
4405
4406 PendingThumbnailsRecord pending = null;
4407 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004408 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409
4410 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004411 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4413 + ", receiver=" + receiver);
4414
4415 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4416 != PackageManager.PERMISSION_GRANTED) {
4417 if (receiver != null) {
4418 // If the caller wants to wait for pending thumbnails,
4419 // it ain't gonna get them.
4420 try {
4421 receiver.finished();
4422 } catch (RemoteException ex) {
4423 }
4424 }
4425 String msg = "Permission Denial: getTasks() from pid="
4426 + Binder.getCallingPid()
4427 + ", uid=" + Binder.getCallingUid()
4428 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004429 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430 throw new SecurityException(msg);
4431 }
4432
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004433 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004434 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004435 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004436 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 CharSequence topDescription = null;
4438 TaskRecord curTask = null;
4439 int numActivities = 0;
4440 int numRunning = 0;
4441 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004442 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004444 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445
4446 // Initialize state for next task if needed.
4447 if (top == null ||
4448 (top.state == ActivityState.INITIALIZING
4449 && top.task == r.task)) {
4450 top = r;
4451 topDescription = r.description;
4452 curTask = r.task;
4453 numActivities = numRunning = 0;
4454 }
4455
4456 // Add 'r' into the current task.
4457 numActivities++;
4458 if (r.app != null && r.app.thread != null) {
4459 numRunning++;
4460 }
4461 if (topDescription == null) {
4462 topDescription = r.description;
4463 }
4464
Joe Onorato8a9b2202010-02-26 18:56:32 -08004465 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 TAG, r.intent.getComponent().flattenToShortString()
4467 + ": task=" + r.task);
4468
4469 // If the next one is a different task, generate a new
4470 // TaskInfo entry for what we have.
4471 if (next == null || next.task != curTask) {
4472 ActivityManager.RunningTaskInfo ci
4473 = new ActivityManager.RunningTaskInfo();
4474 ci.id = curTask.taskId;
4475 ci.baseActivity = r.intent.getComponent();
4476 ci.topActivity = top.intent.getComponent();
4477 ci.thumbnail = top.thumbnail;
4478 ci.description = topDescription;
4479 ci.numActivities = numActivities;
4480 ci.numRunning = numRunning;
4481 //System.out.println(
4482 // "#" + maxNum + ": " + " descr=" + ci.description);
4483 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004484 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 TAG, "State=" + top.state + "Idle=" + top.idle
4486 + " app=" + top.app
4487 + " thr=" + (top.app != null ? top.app.thread : null));
4488 if (top.state == ActivityState.RESUMED
4489 || top.state == ActivityState.PAUSING) {
4490 if (top.idle && top.app != null
4491 && top.app.thread != null) {
4492 topRecord = top;
4493 topThumbnail = top.app.thread;
4494 } else {
4495 top.thumbnailNeeded = true;
4496 }
4497 }
4498 if (pending == null) {
4499 pending = new PendingThumbnailsRecord(receiver);
4500 }
4501 pending.pendingRecords.add(top);
4502 }
4503 list.add(ci);
4504 maxNum--;
4505 top = null;
4506 }
4507 }
4508
4509 if (pending != null) {
4510 mPendingThumbnails.add(pending);
4511 }
4512 }
4513
Joe Onorato8a9b2202010-02-26 18:56:32 -08004514 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515
4516 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004517 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 try {
4519 topThumbnail.requestThumbnail(topRecord);
4520 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004521 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004522 sendPendingThumbnail(null, topRecord, null, null, true);
4523 }
4524 }
4525
4526 if (pending == null && receiver != null) {
4527 // In this case all thumbnails were available and the client
4528 // is being asked to be told when the remaining ones come in...
4529 // which is unusually, since the top-most currently running
4530 // activity should never have a canned thumbnail! Oh well.
4531 try {
4532 receiver.finished();
4533 } catch (RemoteException ex) {
4534 }
4535 }
4536
4537 return list;
4538 }
4539
4540 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4541 int flags) {
4542 synchronized (this) {
4543 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4544 "getRecentTasks()");
4545
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004546 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004548 final int N = mRecentTasks.size();
4549 ArrayList<ActivityManager.RecentTaskInfo> res
4550 = new ArrayList<ActivityManager.RecentTaskInfo>(
4551 maxNum < N ? maxNum : N);
4552 for (int i=0; i<N && maxNum > 0; i++) {
4553 TaskRecord tr = mRecentTasks.get(i);
4554 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4555 || (tr.intent == null)
4556 || ((tr.intent.getFlags()
4557 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4558 ActivityManager.RecentTaskInfo rti
4559 = new ActivityManager.RecentTaskInfo();
4560 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4561 rti.baseIntent = new Intent(
4562 tr.intent != null ? tr.intent : tr.affinityIntent);
4563 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004564
4565 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4566 // Check whether this activity is currently available.
4567 try {
4568 if (rti.origActivity != null) {
4569 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4570 continue;
4571 }
4572 } else if (rti.baseIntent != null) {
4573 if (pm.queryIntentActivities(rti.baseIntent,
4574 null, 0) == null) {
4575 continue;
4576 }
4577 }
4578 } catch (RemoteException e) {
4579 // Will never happen.
4580 }
4581 }
4582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 res.add(rti);
4584 maxNum--;
4585 }
4586 }
4587 return res;
4588 }
4589 }
4590
4591 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4592 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004593 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 TaskRecord jt = startTask;
4595
4596 // First look backwards
4597 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004598 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 if (r.task != jt) {
4600 jt = r.task;
4601 if (affinity.equals(jt.affinity)) {
4602 return j;
4603 }
4604 }
4605 }
4606
4607 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004608 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 jt = startTask;
4610 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004611 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 if (r.task != jt) {
4613 if (affinity.equals(jt.affinity)) {
4614 return j;
4615 }
4616 jt = r.task;
4617 }
4618 }
4619
4620 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004621 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 return N-1;
4623 }
4624
4625 return -1;
4626 }
4627
4628 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004629 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 */
4631 public void moveTaskToFront(int task) {
4632 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4633 "moveTaskToFront()");
4634
4635 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004636 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4637 Binder.getCallingUid(), "Task to front")) {
4638 return;
4639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 final long origId = Binder.clearCallingIdentity();
4641 try {
4642 int N = mRecentTasks.size();
4643 for (int i=0; i<N; i++) {
4644 TaskRecord tr = mRecentTasks.get(i);
4645 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004646 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 return;
4648 }
4649 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004650 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4651 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004653 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 return;
4655 }
4656 }
4657 } finally {
4658 Binder.restoreCallingIdentity(origId);
4659 }
4660 }
4661 }
4662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 public void moveTaskToBack(int task) {
4664 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4665 "moveTaskToBack()");
4666
4667 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004668 if (mMainStack.mResumedActivity != null
4669 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004670 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4671 Binder.getCallingUid(), "Task to back")) {
4672 return;
4673 }
4674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004676 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004677 Binder.restoreCallingIdentity(origId);
4678 }
4679 }
4680
4681 /**
4682 * Moves an activity, and all of the other activities within the same task, to the bottom
4683 * of the history stack. The activity's order within the task is unchanged.
4684 *
4685 * @param token A reference to the activity we wish to move
4686 * @param nonRoot If false then this only works if the activity is the root
4687 * of a task; if true it will work for any activity in a task.
4688 * @return Returns true if the move completed, false if not.
4689 */
4690 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4691 synchronized(this) {
4692 final long origId = Binder.clearCallingIdentity();
4693 int taskId = getTaskForActivityLocked(token, !nonRoot);
4694 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004695 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 }
4697 Binder.restoreCallingIdentity(origId);
4698 }
4699 return false;
4700 }
4701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 public void moveTaskBackwards(int task) {
4703 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4704 "moveTaskBackwards()");
4705
4706 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004707 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4708 Binder.getCallingUid(), "Task backwards")) {
4709 return;
4710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 final long origId = Binder.clearCallingIdentity();
4712 moveTaskBackwardsLocked(task);
4713 Binder.restoreCallingIdentity(origId);
4714 }
4715 }
4716
4717 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004718 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 }
4720
4721 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4722 synchronized(this) {
4723 return getTaskForActivityLocked(token, onlyRoot);
4724 }
4725 }
4726
4727 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004728 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 TaskRecord lastTask = null;
4730 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004731 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 if (r == token) {
4733 if (!onlyRoot || lastTask != r.task) {
4734 return r.task.taskId;
4735 }
4736 return -1;
4737 }
4738 lastTask = r.task;
4739 }
4740
4741 return -1;
4742 }
4743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 public void finishOtherInstances(IBinder token, ComponentName className) {
4745 synchronized(this) {
4746 final long origId = Binder.clearCallingIdentity();
4747
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004748 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 TaskRecord lastTask = null;
4750 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004751 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 if (r.realActivity.equals(className)
4753 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004754 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 null, "others")) {
4756 i--;
4757 N--;
4758 }
4759 }
4760 lastTask = r.task;
4761 }
4762
4763 Binder.restoreCallingIdentity(origId);
4764 }
4765 }
4766
4767 // =========================================================
4768 // THUMBNAILS
4769 // =========================================================
4770
4771 public void reportThumbnail(IBinder token,
4772 Bitmap thumbnail, CharSequence description) {
4773 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4774 final long origId = Binder.clearCallingIdentity();
4775 sendPendingThumbnail(null, token, thumbnail, description, true);
4776 Binder.restoreCallingIdentity(origId);
4777 }
4778
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004779 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 Bitmap thumbnail, CharSequence description, boolean always) {
4781 TaskRecord task = null;
4782 ArrayList receivers = null;
4783
4784 //System.out.println("Send pending thumbnail: " + r);
4785
4786 synchronized(this) {
4787 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004788 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 if (index < 0) {
4790 return;
4791 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004792 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 }
4794 if (thumbnail == null) {
4795 thumbnail = r.thumbnail;
4796 description = r.description;
4797 }
4798 if (thumbnail == null && !always) {
4799 // If there is no thumbnail, and this entry is not actually
4800 // going away, then abort for now and pick up the next
4801 // thumbnail we get.
4802 return;
4803 }
4804 task = r.task;
4805
4806 int N = mPendingThumbnails.size();
4807 int i=0;
4808 while (i<N) {
4809 PendingThumbnailsRecord pr =
4810 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4811 //System.out.println("Looking in " + pr.pendingRecords);
4812 if (pr.pendingRecords.remove(r)) {
4813 if (receivers == null) {
4814 receivers = new ArrayList();
4815 }
4816 receivers.add(pr);
4817 if (pr.pendingRecords.size() == 0) {
4818 pr.finished = true;
4819 mPendingThumbnails.remove(i);
4820 N--;
4821 continue;
4822 }
4823 }
4824 i++;
4825 }
4826 }
4827
4828 if (receivers != null) {
4829 final int N = receivers.size();
4830 for (int i=0; i<N; i++) {
4831 try {
4832 PendingThumbnailsRecord pr =
4833 (PendingThumbnailsRecord)receivers.get(i);
4834 pr.receiver.newThumbnail(
4835 task != null ? task.taskId : -1, thumbnail, description);
4836 if (pr.finished) {
4837 pr.receiver.finished();
4838 }
4839 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004840 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 }
4842 }
4843 }
4844 }
4845
4846 // =========================================================
4847 // CONTENT PROVIDERS
4848 // =========================================================
4849
4850 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4851 List providers = null;
4852 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004853 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004855 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856 } catch (RemoteException ex) {
4857 }
4858 if (providers != null) {
4859 final int N = providers.size();
4860 for (int i=0; i<N; i++) {
4861 ProviderInfo cpi =
4862 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004863 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864 if (cpr == null) {
4865 cpr = new ContentProviderRecord(cpi, app.info);
4866 mProvidersByClass.put(cpi.name, cpr);
4867 }
4868 app.pubProviders.put(cpi.name, cpr);
4869 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004870 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 }
4872 }
4873 return providers;
4874 }
4875
4876 private final String checkContentProviderPermissionLocked(
4877 ProviderInfo cpi, ProcessRecord r, int mode) {
4878 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4879 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4880 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4881 cpi.exported ? -1 : cpi.applicationInfo.uid)
4882 == PackageManager.PERMISSION_GRANTED
4883 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4884 return null;
4885 }
4886 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4887 cpi.exported ? -1 : cpi.applicationInfo.uid)
4888 == PackageManager.PERMISSION_GRANTED) {
4889 return null;
4890 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004891
4892 PathPermission[] pps = cpi.pathPermissions;
4893 if (pps != null) {
4894 int i = pps.length;
4895 while (i > 0) {
4896 i--;
4897 PathPermission pp = pps[i];
4898 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4899 cpi.exported ? -1 : cpi.applicationInfo.uid)
4900 == PackageManager.PERMISSION_GRANTED
4901 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4902 return null;
4903 }
4904 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4905 cpi.exported ? -1 : cpi.applicationInfo.uid)
4906 == PackageManager.PERMISSION_GRANTED) {
4907 return null;
4908 }
4909 }
4910 }
4911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 String msg = "Permission Denial: opening provider " + cpi.name
4913 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4914 + ", uid=" + callingUid + ") requires "
4915 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004916 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 return msg;
4918 }
4919
4920 private final ContentProviderHolder getContentProviderImpl(
4921 IApplicationThread caller, String name) {
4922 ContentProviderRecord cpr;
4923 ProviderInfo cpi = null;
4924
4925 synchronized(this) {
4926 ProcessRecord r = null;
4927 if (caller != null) {
4928 r = getRecordForAppLocked(caller);
4929 if (r == null) {
4930 throw new SecurityException(
4931 "Unable to find app for caller " + caller
4932 + " (pid=" + Binder.getCallingPid()
4933 + ") when getting content provider " + name);
4934 }
4935 }
4936
4937 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004938 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 if (cpr != null) {
4940 cpi = cpr.info;
4941 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4942 return new ContentProviderHolder(cpi,
4943 cpi.readPermission != null
4944 ? cpi.readPermission : cpi.writePermission);
4945 }
4946
4947 if (r != null && cpr.canRunHere(r)) {
4948 // This provider has been published or is in the process
4949 // of being published... but it is also allowed to run
4950 // in the caller's process, so don't make a connection
4951 // and just let the caller instantiate its own instance.
4952 if (cpr.provider != null) {
4953 // don't give caller the provider object, it needs
4954 // to make its own.
4955 cpr = new ContentProviderRecord(cpr);
4956 }
4957 return cpr;
4958 }
4959
4960 final long origId = Binder.clearCallingIdentity();
4961
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004962 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 // return it right away.
4964 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004965 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004966 "Adding provider requested by "
4967 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004968 + cpr.info.processName);
4969 Integer cnt = r.conProviders.get(cpr);
4970 if (cnt == null) {
4971 r.conProviders.put(cpr, new Integer(1));
4972 } else {
4973 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
4974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004976 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
4977 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07004978 // make sure to count it as being accessed and thus
4979 // back up on the LRU list. This is good because
4980 // content providers are often expensive to start.
4981 updateLruProcessLocked(cpr.app, false, true);
4982 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07004983 } else {
4984 cpr.externals++;
4985 }
4986
4987 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 updateOomAdjLocked(cpr.app);
4989 }
4990
4991 Binder.restoreCallingIdentity(origId);
4992
4993 } else {
4994 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004995 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07004996 resolveContentProvider(name,
4997 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 } catch (RemoteException ex) {
4999 }
5000 if (cpi == null) {
5001 return null;
5002 }
5003
5004 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
5005 return new ContentProviderHolder(cpi,
5006 cpi.readPermission != null
5007 ? cpi.readPermission : cpi.writePermission);
5008 }
5009
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005010 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5011 && !cpi.processName.equals("system")) {
5012 // If this content provider does not run in the system
5013 // process, and the system is not yet ready to run other
5014 // processes, then fail fast instead of hanging.
5015 throw new IllegalArgumentException(
5016 "Attempt to launch content provider before system ready");
5017 }
5018
Dianne Hackborn860755f2010-06-03 18:47:52 -07005019 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005020 final boolean firstClass = cpr == null;
5021 if (firstClass) {
5022 try {
5023 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005024 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 getApplicationInfo(
5026 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005027 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005029 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 + cpi.name);
5031 return null;
5032 }
5033 cpr = new ContentProviderRecord(cpi, ai);
5034 } catch (RemoteException ex) {
5035 // pm is in same process, this will never happen.
5036 }
5037 }
5038
5039 if (r != null && cpr.canRunHere(r)) {
5040 // If this is a multiprocess provider, then just return its
5041 // info and allow the caller to instantiate it. Only do
5042 // this if the provider is the same user as the caller's
5043 // process, or can run as root (so can be in any process).
5044 return cpr;
5045 }
5046
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005047 if (DEBUG_PROVIDER) {
5048 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005049 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005050 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 }
5052
5053 // This is single process, and our app is now connecting to it.
5054 // See if we are already in the process of launching this
5055 // provider.
5056 final int N = mLaunchingProviders.size();
5057 int i;
5058 for (i=0; i<N; i++) {
5059 if (mLaunchingProviders.get(i) == cpr) {
5060 break;
5061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 }
5063
5064 // If the provider is not already being launched, then get it
5065 // started.
5066 if (i >= N) {
5067 final long origId = Binder.clearCallingIdentity();
5068 ProcessRecord proc = startProcessLocked(cpi.processName,
5069 cpr.appInfo, false, 0, "content provider",
5070 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005071 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005073 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 + cpi.applicationInfo.packageName + "/"
5075 + cpi.applicationInfo.uid + " for provider "
5076 + name + ": process is bad");
5077 return null;
5078 }
5079 cpr.launchingApp = proc;
5080 mLaunchingProviders.add(cpr);
5081 Binder.restoreCallingIdentity(origId);
5082 }
5083
5084 // Make sure the provider is published (the same provider class
5085 // may be published under multiple names).
5086 if (firstClass) {
5087 mProvidersByClass.put(cpi.name, cpr);
5088 }
5089 mProvidersByName.put(name, cpr);
5090
5091 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005092 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005093 "Adding provider requested by "
5094 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005095 + cpr.info.processName);
5096 Integer cnt = r.conProviders.get(cpr);
5097 if (cnt == null) {
5098 r.conProviders.put(cpr, new Integer(1));
5099 } else {
5100 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 cpr.clients.add(r);
5103 } else {
5104 cpr.externals++;
5105 }
5106 }
5107 }
5108
5109 // Wait for the provider to be published...
5110 synchronized (cpr) {
5111 while (cpr.provider == null) {
5112 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005113 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 + cpi.applicationInfo.packageName + "/"
5115 + cpi.applicationInfo.uid + " for provider "
5116 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005117 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 cpi.applicationInfo.packageName,
5119 cpi.applicationInfo.uid, name);
5120 return null;
5121 }
5122 try {
5123 cpr.wait();
5124 } catch (InterruptedException ex) {
5125 }
5126 }
5127 }
5128 return cpr;
5129 }
5130
5131 public final ContentProviderHolder getContentProvider(
5132 IApplicationThread caller, String name) {
5133 if (caller == null) {
5134 String msg = "null IApplicationThread when getting content provider "
5135 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005136 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005137 throw new SecurityException(msg);
5138 }
5139
5140 return getContentProviderImpl(caller, name);
5141 }
5142
5143 private ContentProviderHolder getContentProviderExternal(String name) {
5144 return getContentProviderImpl(null, name);
5145 }
5146
5147 /**
5148 * Drop a content provider from a ProcessRecord's bookkeeping
5149 * @param cpr
5150 */
5151 public void removeContentProvider(IApplicationThread caller, String name) {
5152 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005153 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005155 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005156 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005157 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 return;
5159 }
5160 final ProcessRecord r = getRecordForAppLocked(caller);
5161 if (r == null) {
5162 throw new SecurityException(
5163 "Unable to find app for caller " + caller +
5164 " when removing content provider " + name);
5165 }
5166 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005167 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005168 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005169 + r.info.processName + " from process "
5170 + localCpr.appInfo.processName);
5171 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005173 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005174 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 return;
5176 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005177 Integer cnt = r.conProviders.get(localCpr);
5178 if (cnt == null || cnt.intValue() <= 1) {
5179 localCpr.clients.remove(r);
5180 r.conProviders.remove(localCpr);
5181 } else {
5182 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 }
5185 updateOomAdjLocked();
5186 }
5187 }
5188
5189 private void removeContentProviderExternal(String name) {
5190 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005191 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 if(cpr == null) {
5193 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005194 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 return;
5196 }
5197
5198 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005199 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 localCpr.externals--;
5201 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005202 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 }
5204 updateOomAdjLocked();
5205 }
5206 }
5207
5208 public final void publishContentProviders(IApplicationThread caller,
5209 List<ContentProviderHolder> providers) {
5210 if (providers == null) {
5211 return;
5212 }
5213
5214 synchronized(this) {
5215 final ProcessRecord r = getRecordForAppLocked(caller);
5216 if (r == null) {
5217 throw new SecurityException(
5218 "Unable to find app for caller " + caller
5219 + " (pid=" + Binder.getCallingPid()
5220 + ") when publishing content providers");
5221 }
5222
5223 final long origId = Binder.clearCallingIdentity();
5224
5225 final int N = providers.size();
5226 for (int i=0; i<N; i++) {
5227 ContentProviderHolder src = providers.get(i);
5228 if (src == null || src.info == null || src.provider == null) {
5229 continue;
5230 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005231 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 if (dst != null) {
5233 mProvidersByClass.put(dst.info.name, dst);
5234 String names[] = dst.info.authority.split(";");
5235 for (int j = 0; j < names.length; j++) {
5236 mProvidersByName.put(names[j], dst);
5237 }
5238
5239 int NL = mLaunchingProviders.size();
5240 int j;
5241 for (j=0; j<NL; j++) {
5242 if (mLaunchingProviders.get(j) == dst) {
5243 mLaunchingProviders.remove(j);
5244 j--;
5245 NL--;
5246 }
5247 }
5248 synchronized (dst) {
5249 dst.provider = src.provider;
5250 dst.app = r;
5251 dst.notifyAll();
5252 }
5253 updateOomAdjLocked(r);
5254 }
5255 }
5256
5257 Binder.restoreCallingIdentity(origId);
5258 }
5259 }
5260
5261 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005262 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005263 synchronized (mSelf) {
5264 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5265 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005266 if (providers != null) {
5267 for (int i=providers.size()-1; i>=0; i--) {
5268 ProviderInfo pi = (ProviderInfo)providers.get(i);
5269 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5270 Slog.w(TAG, "Not installing system proc provider " + pi.name
5271 + ": not system .apk");
5272 providers.remove(i);
5273 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005274 }
5275 }
5276 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005277 if (providers != null) {
5278 mSystemThread.installSystemProviders(providers);
5279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
5281
5282 // =========================================================
5283 // GLOBAL MANAGEMENT
5284 // =========================================================
5285
5286 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5287 ApplicationInfo info, String customProcess) {
5288 String proc = customProcess != null ? customProcess : info.processName;
5289 BatteryStatsImpl.Uid.Proc ps = null;
5290 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5291 synchronized (stats) {
5292 ps = stats.getProcessStatsLocked(info.uid, proc);
5293 }
5294 return new ProcessRecord(ps, thread, info, proc);
5295 }
5296
5297 final ProcessRecord addAppLocked(ApplicationInfo info) {
5298 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5299
5300 if (app == null) {
5301 app = newProcessRecordLocked(null, info, null);
5302 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005303 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 }
5305
5306 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5307 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5308 app.persistent = true;
5309 app.maxAdj = CORE_SERVER_ADJ;
5310 }
5311 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5312 mPersistentStartingProcesses.add(app);
5313 startProcessLocked(app, "added application", app.processName);
5314 }
5315
5316 return app;
5317 }
5318
5319 public void unhandledBack() {
5320 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5321 "unhandledBack()");
5322
5323 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005324 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 TAG, "Performing unhandledBack(): stack size = " + count);
5327 if (count > 1) {
5328 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005329 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5331 Binder.restoreCallingIdentity(origId);
5332 }
5333 }
5334 }
5335
5336 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5337 String name = uri.getAuthority();
5338 ContentProviderHolder cph = getContentProviderExternal(name);
5339 ParcelFileDescriptor pfd = null;
5340 if (cph != null) {
5341 // We record the binder invoker's uid in thread-local storage before
5342 // going to the content provider to open the file. Later, in the code
5343 // that handles all permissions checks, we look for this uid and use
5344 // that rather than the Activity Manager's own uid. The effect is that
5345 // we do the check against the caller's permissions even though it looks
5346 // to the content provider like the Activity Manager itself is making
5347 // the request.
5348 sCallerIdentity.set(new Identity(
5349 Binder.getCallingPid(), Binder.getCallingUid()));
5350 try {
5351 pfd = cph.provider.openFile(uri, "r");
5352 } catch (FileNotFoundException e) {
5353 // do nothing; pfd will be returned null
5354 } finally {
5355 // Ensure that whatever happens, we clean up the identity state
5356 sCallerIdentity.remove();
5357 }
5358
5359 // We've got the fd now, so we're done with the provider.
5360 removeContentProviderExternal(name);
5361 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005362 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 }
5364 return pfd;
5365 }
5366
5367 public void goingToSleep() {
5368 synchronized(this) {
5369 mSleeping = true;
5370 mWindowManager.setEventDispatching(false);
5371
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005372 if (mMainStack.mResumedActivity != null) {
5373 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005374 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005375 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 }
5377 }
5378 }
5379
Dianne Hackborn55280a92009-05-07 15:53:46 -07005380 public boolean shutdown(int timeout) {
5381 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5382 != PackageManager.PERMISSION_GRANTED) {
5383 throw new SecurityException("Requires permission "
5384 + android.Manifest.permission.SHUTDOWN);
5385 }
5386
5387 boolean timedout = false;
5388
5389 synchronized(this) {
5390 mShuttingDown = true;
5391 mWindowManager.setEventDispatching(false);
5392
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005393 if (mMainStack.mResumedActivity != null) {
5394 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005395 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005396 while (mMainStack.mResumedActivity != null
5397 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005398 long delay = endTime - System.currentTimeMillis();
5399 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005401 timedout = true;
5402 break;
5403 }
5404 try {
5405 this.wait();
5406 } catch (InterruptedException e) {
5407 }
5408 }
5409 }
5410 }
5411
5412 mUsageStatsService.shutdown();
5413 mBatteryStatsService.shutdown();
5414
5415 return timedout;
5416 }
5417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 public void wakingUp() {
5419 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005420 if (mMainStack.mGoingToSleep.isHeld()) {
5421 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 }
5423 mWindowManager.setEventDispatching(true);
5424 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005425 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 }
5427 }
5428
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005429 public void stopAppSwitches() {
5430 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5431 != PackageManager.PERMISSION_GRANTED) {
5432 throw new SecurityException("Requires permission "
5433 + android.Manifest.permission.STOP_APP_SWITCHES);
5434 }
5435
5436 synchronized(this) {
5437 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5438 + APP_SWITCH_DELAY_TIME;
5439 mDidAppSwitch = false;
5440 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5441 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5442 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5443 }
5444 }
5445
5446 public void resumeAppSwitches() {
5447 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5448 != PackageManager.PERMISSION_GRANTED) {
5449 throw new SecurityException("Requires permission "
5450 + android.Manifest.permission.STOP_APP_SWITCHES);
5451 }
5452
5453 synchronized(this) {
5454 // Note that we don't execute any pending app switches... we will
5455 // let those wait until either the timeout, or the next start
5456 // activity request.
5457 mAppSwitchesAllowedTime = 0;
5458 }
5459 }
5460
5461 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5462 String name) {
5463 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5464 return true;
5465 }
5466
5467 final int perm = checkComponentPermission(
5468 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5469 callingUid, -1);
5470 if (perm == PackageManager.PERMISSION_GRANTED) {
5471 return true;
5472 }
5473
Joe Onorato8a9b2202010-02-26 18:56:32 -08005474 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005475 return false;
5476 }
5477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 public void setDebugApp(String packageName, boolean waitForDebugger,
5479 boolean persistent) {
5480 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5481 "setDebugApp()");
5482
5483 // Note that this is not really thread safe if there are multiple
5484 // callers into it at the same time, but that's not a situation we
5485 // care about.
5486 if (persistent) {
5487 final ContentResolver resolver = mContext.getContentResolver();
5488 Settings.System.putString(
5489 resolver, Settings.System.DEBUG_APP,
5490 packageName);
5491 Settings.System.putInt(
5492 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5493 waitForDebugger ? 1 : 0);
5494 }
5495
5496 synchronized (this) {
5497 if (!persistent) {
5498 mOrigDebugApp = mDebugApp;
5499 mOrigWaitForDebugger = mWaitForDebugger;
5500 }
5501 mDebugApp = packageName;
5502 mWaitForDebugger = waitForDebugger;
5503 mDebugTransient = !persistent;
5504 if (packageName != null) {
5505 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005506 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 Binder.restoreCallingIdentity(origId);
5508 }
5509 }
5510 }
5511
5512 public void setAlwaysFinish(boolean enabled) {
5513 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5514 "setAlwaysFinish()");
5515
5516 Settings.System.putInt(
5517 mContext.getContentResolver(),
5518 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5519
5520 synchronized (this) {
5521 mAlwaysFinishActivities = enabled;
5522 }
5523 }
5524
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005525 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005527 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005529 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 }
5531 }
5532
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005533 public boolean isUserAMonkey() {
5534 // For now the fact that there is a controller implies
5535 // we have a monkey.
5536 synchronized (this) {
5537 return mController != null;
5538 }
5539 }
5540
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005541 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005542 synchronized (this) {
5543 mWatchers.register(watcher);
5544 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005545 }
5546
5547 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005548 synchronized (this) {
5549 mWatchers.unregister(watcher);
5550 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005551 }
5552
Daniel Sandler69a48172010-06-23 16:29:36 -04005553 public void setImmersive(IBinder token, boolean immersive) {
5554 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005555 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005556 if (index < 0) {
5557 throw new IllegalArgumentException();
5558 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005559 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005560 r.immersive = immersive;
5561 }
5562 }
5563
5564 public boolean isImmersive(IBinder token) {
5565 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005566 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005567 if (index < 0) {
5568 throw new IllegalArgumentException();
5569 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005570 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005571 return r.immersive;
5572 }
5573 }
5574
5575 public boolean isTopActivityImmersive() {
5576 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005577 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005578 return (r != null) ? r.immersive : false;
5579 }
5580 }
5581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 public final void enterSafeMode() {
5583 synchronized(this) {
5584 // It only makes sense to do this before the system is ready
5585 // and started launching other packages.
5586 if (!mSystemReady) {
5587 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005588 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 } catch (RemoteException e) {
5590 }
5591
5592 View v = LayoutInflater.from(mContext).inflate(
5593 com.android.internal.R.layout.safe_mode, null);
5594 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5595 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5596 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5597 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5598 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5599 lp.format = v.getBackground().getOpacity();
5600 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5601 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5602 ((WindowManager)mContext.getSystemService(
5603 Context.WINDOW_SERVICE)).addView(v, lp);
5604 }
5605 }
5606 }
5607
5608 public void noteWakeupAlarm(IIntentSender sender) {
5609 if (!(sender instanceof PendingIntentRecord)) {
5610 return;
5611 }
5612 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5613 synchronized (stats) {
5614 if (mBatteryStatsService.isOnBattery()) {
5615 mBatteryStatsService.enforceCallingPermission();
5616 PendingIntentRecord rec = (PendingIntentRecord)sender;
5617 int MY_UID = Binder.getCallingUid();
5618 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5619 BatteryStatsImpl.Uid.Pkg pkg =
5620 stats.getPackageStatsLocked(uid, rec.key.packageName);
5621 pkg.incWakeupsLocked();
5622 }
5623 }
5624 }
5625
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005626 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005628 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005630 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 // XXX Note: don't acquire main activity lock here, because the window
5632 // manager calls in with its locks held.
5633
5634 boolean killed = false;
5635 synchronized (mPidsSelfLocked) {
5636 int[] types = new int[pids.length];
5637 int worstType = 0;
5638 for (int i=0; i<pids.length; i++) {
5639 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5640 if (proc != null) {
5641 int type = proc.setAdj;
5642 types[i] = type;
5643 if (type > worstType) {
5644 worstType = type;
5645 }
5646 }
5647 }
5648
5649 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5650 // then constrain it so we will kill all hidden procs.
5651 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5652 worstType = HIDDEN_APP_MIN_ADJ;
5653 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005654 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 for (int i=0; i<pids.length; i++) {
5656 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5657 if (proc == null) {
5658 continue;
5659 }
5660 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005661 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005662 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005663 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5664 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005666 proc.killedBackground = true;
5667 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 }
5669 }
5670 }
5671 return killed;
5672 }
5673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 public final void startRunning(String pkg, String cls, String action,
5675 String data) {
5676 synchronized(this) {
5677 if (mStartRunning) {
5678 return;
5679 }
5680 mStartRunning = true;
5681 mTopComponent = pkg != null && cls != null
5682 ? new ComponentName(pkg, cls) : null;
5683 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5684 mTopData = data;
5685 if (!mSystemReady) {
5686 return;
5687 }
5688 }
5689
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005690 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 }
5692
5693 private void retrieveSettings() {
5694 final ContentResolver resolver = mContext.getContentResolver();
5695 String debugApp = Settings.System.getString(
5696 resolver, Settings.System.DEBUG_APP);
5697 boolean waitForDebugger = Settings.System.getInt(
5698 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5699 boolean alwaysFinishActivities = Settings.System.getInt(
5700 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5701
5702 Configuration configuration = new Configuration();
5703 Settings.System.getConfiguration(resolver, configuration);
5704
5705 synchronized (this) {
5706 mDebugApp = mOrigDebugApp = debugApp;
5707 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5708 mAlwaysFinishActivities = alwaysFinishActivities;
5709 // This happens before any activities are started, so we can
5710 // change mConfiguration in-place.
5711 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005712 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005713 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 }
5715 }
5716
5717 public boolean testIsSystemReady() {
5718 // no need to synchronize(this) just to read & return the value
5719 return mSystemReady;
5720 }
5721
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005722 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 // In the simulator, startRunning will never have been called, which
5724 // normally sets a few crucial variables. Do it here instead.
5725 if (!Process.supportsProcesses()) {
5726 mStartRunning = true;
5727 mTopAction = Intent.ACTION_MAIN;
5728 }
5729
5730 synchronized(this) {
5731 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005732 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005733 return;
5734 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005735
5736 // Check to see if there are any update receivers to run.
5737 if (!mDidUpdate) {
5738 if (mWaitingUpdate) {
5739 return;
5740 }
5741 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5742 List<ResolveInfo> ris = null;
5743 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005744 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005745 intent, null, 0);
5746 } catch (RemoteException e) {
5747 }
5748 if (ris != null) {
5749 for (int i=ris.size()-1; i>=0; i--) {
5750 if ((ris.get(i).activityInfo.applicationInfo.flags
5751 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5752 ris.remove(i);
5753 }
5754 }
5755 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5756 for (int i=0; i<ris.size(); i++) {
5757 ActivityInfo ai = ris.get(i).activityInfo;
5758 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5759 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005760 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005761 finisher = new IIntentReceiver.Stub() {
5762 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005763 String data, Bundle extras, boolean ordered,
5764 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005765 throws RemoteException {
5766 synchronized (ActivityManagerService.this) {
5767 mDidUpdate = true;
5768 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005769 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005770 }
5771 };
5772 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005773 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005774 broadcastIntentLocked(null, null, intent, null, finisher,
5775 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005776 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005777 mWaitingUpdate = true;
5778 }
5779 }
5780 }
5781 if (mWaitingUpdate) {
5782 return;
5783 }
5784 mDidUpdate = true;
5785 }
5786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 mSystemReady = true;
5788 if (!mStartRunning) {
5789 return;
5790 }
5791 }
5792
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005793 ArrayList<ProcessRecord> procsToKill = null;
5794 synchronized(mPidsSelfLocked) {
5795 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5796 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5797 if (!isAllowedWhileBooting(proc.info)){
5798 if (procsToKill == null) {
5799 procsToKill = new ArrayList<ProcessRecord>();
5800 }
5801 procsToKill.add(proc);
5802 }
5803 }
5804 }
5805
5806 if (procsToKill != null) {
5807 synchronized(this) {
5808 for (int i=procsToKill.size()-1; i>=0; i--) {
5809 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005810 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005811 removeProcessLocked(proc, true);
5812 }
5813 }
5814 }
5815
Joe Onorato8a9b2202010-02-26 18:56:32 -08005816 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005817 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 SystemClock.uptimeMillis());
5819
5820 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005821 // Make sure we have no pre-ready processes sitting around.
5822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5824 ResolveInfo ri = mContext.getPackageManager()
5825 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005826 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 CharSequence errorMsg = null;
5828 if (ri != null) {
5829 ActivityInfo ai = ri.activityInfo;
5830 ApplicationInfo app = ai.applicationInfo;
5831 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5832 mTopAction = Intent.ACTION_FACTORY_TEST;
5833 mTopData = null;
5834 mTopComponent = new ComponentName(app.packageName,
5835 ai.name);
5836 } else {
5837 errorMsg = mContext.getResources().getText(
5838 com.android.internal.R.string.factorytest_not_system);
5839 }
5840 } else {
5841 errorMsg = mContext.getResources().getText(
5842 com.android.internal.R.string.factorytest_no_action);
5843 }
5844 if (errorMsg != null) {
5845 mTopAction = null;
5846 mTopData = null;
5847 mTopComponent = null;
5848 Message msg = Message.obtain();
5849 msg.what = SHOW_FACTORY_ERROR_MSG;
5850 msg.getData().putCharSequence("msg", errorMsg);
5851 mHandler.sendMessage(msg);
5852 }
5853 }
5854 }
5855
5856 retrieveSettings();
5857
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005858 if (goingCallback != null) goingCallback.run();
5859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 synchronized (this) {
5861 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5862 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005863 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005864 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 if (apps != null) {
5866 int N = apps.size();
5867 int i;
5868 for (i=0; i<N; i++) {
5869 ApplicationInfo info
5870 = (ApplicationInfo)apps.get(i);
5871 if (info != null &&
5872 !info.packageName.equals("android")) {
5873 addAppLocked(info);
5874 }
5875 }
5876 }
5877 } catch (RemoteException ex) {
5878 // pm is in same process, this will never happen.
5879 }
5880 }
5881
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005882 // Start up initial activity.
5883 mBooting = true;
5884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005886 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 Message msg = Message.obtain();
5888 msg.what = SHOW_UID_ERROR_MSG;
5889 mHandler.sendMessage(msg);
5890 }
5891 } catch (RemoteException e) {
5892 }
5893
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005894 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 }
5896 }
5897
Dan Egnorb7f03672009-12-09 16:22:32 -08005898 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005899 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005901 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005902 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 startAppProblemLocked(app);
5904 app.stopFreezingAllLocked();
5905 return handleAppCrashLocked(app);
5906 }
5907
Dan Egnorb7f03672009-12-09 16:22:32 -08005908 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005909 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005911 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005912 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5913 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 startAppProblemLocked(app);
5915 app.stopFreezingAllLocked();
5916 }
5917
5918 /**
5919 * Generate a process error record, suitable for attachment to a ProcessRecord.
5920 *
5921 * @param app The ProcessRecord in which the error occurred.
5922 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5923 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005924 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 * @param shortMsg Short message describing the crash.
5926 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005927 * @param stackTrace Full crash stack trace, may be null.
5928 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 * @return Returns a fully-formed AppErrorStateInfo record.
5930 */
5931 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005932 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 report.condition = condition;
5936 report.processName = app.processName;
5937 report.pid = app.pid;
5938 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005939 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 report.shortMsg = shortMsg;
5941 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005942 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943
5944 return report;
5945 }
5946
Dan Egnor42471dd2010-01-07 17:25:22 -08005947 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 synchronized (this) {
5949 app.crashing = false;
5950 app.crashingReport = null;
5951 app.notResponding = false;
5952 app.notRespondingReport = null;
5953 if (app.anrDialog == fromDialog) {
5954 app.anrDialog = null;
5955 }
5956 if (app.waitDialog == fromDialog) {
5957 app.waitDialog = null;
5958 }
5959 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005960 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07005961 Slog.i(ActivityManagerService.TAG, "Killing "
5962 + app.processName + " (pid=" + app.pid + "): user's request");
5963 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
5964 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 Process.killProcess(app.pid);
5966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005967 }
5968 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005969
Dan Egnorb7f03672009-12-09 16:22:32 -08005970 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 long now = SystemClock.uptimeMillis();
5972
5973 Long crashTime = mProcessCrashTimes.get(app.info.processName,
5974 app.info.uid);
5975 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
5976 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005977 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005979 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005980 app.info.processName, app.info.uid);
5981 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005982 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5983 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005985 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005987 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 }
5989 }
5990 if (!app.persistent) {
5991 // We don't want to start this process again until the user
5992 // explicitly does so... but for persistent process, we really
5993 // need to keep it running. If a persistent process is actually
5994 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08005995 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 app.info.processName);
5997 mBadProcesses.put(app.info.processName, app.info.uid, now);
5998 app.bad = true;
5999 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6000 app.removed = true;
6001 removeProcessLocked(app, false);
6002 return false;
6003 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006004 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006005 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006006 if (r.app == app) {
6007 // If the top running activity is from this crashing
6008 // process, then terminate it to avoid getting in a loop.
6009 Slog.w(TAG, " Force finishing activity "
6010 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006011 int index = mMainStack.indexOfTokenLocked(r);
6012 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006013 Activity.RESULT_CANCELED, null, "crashed");
6014 // Also terminate an activities below it that aren't yet
6015 // stopped, to avoid a situation where one will get
6016 // re-start our crashing activity once it gets resumed again.
6017 index--;
6018 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006019 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006020 if (r.state == ActivityState.RESUMED
6021 || r.state == ActivityState.PAUSING
6022 || r.state == ActivityState.PAUSED) {
6023 if (!r.isHomeActivity) {
6024 Slog.w(TAG, " Force finishing activity "
6025 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006026 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006027 Activity.RESULT_CANCELED, null, "crashed");
6028 }
6029 }
6030 }
6031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 }
6033
6034 // Bump up the crash count of any services currently running in the proc.
6035 if (app.services.size() != 0) {
6036 // Any services running in the application need to be placed
6037 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006038 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006040 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 sr.crashCount++;
6042 }
6043 }
6044
6045 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6046 return true;
6047 }
6048
6049 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006050 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6051 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 skipCurrentReceiverLocked(app);
6053 }
6054
6055 void skipCurrentReceiverLocked(ProcessRecord app) {
6056 boolean reschedule = false;
6057 BroadcastRecord r = app.curReceiver;
6058 if (r != null) {
6059 // The current broadcast is waiting for this app's receiver
6060 // to be finished. Looks like that's not going to happen, so
6061 // let the broadcast continue.
6062 logBroadcastReceiverDiscard(r);
6063 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6064 r.resultExtras, r.resultAbort, true);
6065 reschedule = true;
6066 }
6067 r = mPendingBroadcast;
6068 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006069 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 "skip & discard pending app " + r);
6071 logBroadcastReceiverDiscard(r);
6072 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6073 r.resultExtras, r.resultAbort, true);
6074 reschedule = true;
6075 }
6076 if (reschedule) {
6077 scheduleBroadcastsLocked();
6078 }
6079 }
6080
Dan Egnor60d87622009-12-16 16:32:58 -08006081 /**
6082 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6083 * The application process will exit immediately after this call returns.
6084 * @param app object of the crashing app, null for the system server
6085 * @param crashInfo describing the exception
6086 */
6087 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6088 ProcessRecord r = findAppProcess(app);
6089
6090 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6091 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006092 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006093 crashInfo.exceptionClassName,
6094 crashInfo.exceptionMessage,
6095 crashInfo.throwFileName,
6096 crashInfo.throwLineNumber);
6097
Dan Egnor42471dd2010-01-07 17:25:22 -08006098 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006099
6100 crashApplication(r, crashInfo);
6101 }
6102
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006103 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006104 IBinder app,
6105 int violationMask,
6106 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006107 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006108
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006109 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006110 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006111 boolean logIt = true;
6112 synchronized (mAlreadyLoggedViolatedStacks) {
6113 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6114 logIt = false;
6115 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006116 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006117 // the relative pain numbers, without logging all
6118 // the stack traces repeatedly. We'd want to do
6119 // likewise in the client code, which also does
6120 // dup suppression, before the Binder call.
6121 } else {
6122 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6123 mAlreadyLoggedViolatedStacks.clear();
6124 }
6125 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6126 }
6127 }
6128 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006129 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006130 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006131 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006132
6133 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6134 AppErrorResult result = new AppErrorResult();
6135 synchronized (this) {
6136 final long origId = Binder.clearCallingIdentity();
6137
6138 Message msg = Message.obtain();
6139 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6140 HashMap<String, Object> data = new HashMap<String, Object>();
6141 data.put("result", result);
6142 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006143 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006144 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006145 msg.obj = data;
6146 mHandler.sendMessage(msg);
6147
6148 Binder.restoreCallingIdentity(origId);
6149 }
6150 int res = result.get();
6151 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6152 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006153 }
6154
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006155 // Depending on the policy in effect, there could be a bunch of
6156 // these in quick succession so we try to batch these together to
6157 // minimize disk writes, number of dropbox entries, and maximize
6158 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006159 private void logStrictModeViolationToDropBox(
6160 ProcessRecord process,
6161 StrictMode.ViolationInfo info) {
6162 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006163 return;
6164 }
6165 final boolean isSystemApp = process == null ||
6166 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6167 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6168 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6169 final DropBoxManager dbox = (DropBoxManager)
6170 mContext.getSystemService(Context.DROPBOX_SERVICE);
6171
6172 // Exit early if the dropbox isn't configured to accept this report type.
6173 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6174
6175 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006176 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006177 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6178 synchronized (sb) {
6179 bufferWasEmpty = sb.length() == 0;
6180 appendDropBoxProcessHeaders(process, sb);
6181 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6182 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006183 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6184 if (info.violationNumThisLoop != 0) {
6185 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6186 }
6187 if (info != null && info.durationMillis != -1) {
6188 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006189 }
6190 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006191 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6192 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006193 }
6194 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006195
6196 // Only buffer up to ~64k. Various logging bits truncate
6197 // things at 128k.
6198 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006199 }
6200
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006201 // Flush immediately if the buffer's grown too large, or this
6202 // is a non-system app. Non-system apps are isolated with a
6203 // different tag & policy and not batched.
6204 //
6205 // Batching is useful during internal testing with
6206 // StrictMode settings turned up high. Without batching,
6207 // thousands of separate files could be created on boot.
6208 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006209 new Thread("Error dump: " + dropboxTag) {
6210 @Override
6211 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006212 String report;
6213 synchronized (sb) {
6214 report = sb.toString();
6215 sb.delete(0, sb.length());
6216 sb.trimToSize();
6217 }
6218 if (report.length() != 0) {
6219 dbox.addText(dropboxTag, report);
6220 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006221 }
6222 }.start();
6223 return;
6224 }
6225
6226 // System app batching:
6227 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006228 // An existing dropbox-writing thread is outstanding, so
6229 // we don't need to start it up. The existing thread will
6230 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006231 return;
6232 }
6233
6234 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6235 // (After this point, we shouldn't access AMS internal data structures.)
6236 new Thread("Error dump: " + dropboxTag) {
6237 @Override
6238 public void run() {
6239 // 5 second sleep to let stacks arrive and be batched together
6240 try {
6241 Thread.sleep(5000); // 5 seconds
6242 } catch (InterruptedException e) {}
6243
6244 String errorReport;
6245 synchronized (mStrictModeBuffer) {
6246 errorReport = mStrictModeBuffer.toString();
6247 if (errorReport.length() == 0) {
6248 return;
6249 }
6250 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6251 mStrictModeBuffer.trimToSize();
6252 }
6253 dbox.addText(dropboxTag, errorReport);
6254 }
6255 }.start();
6256 }
6257
Dan Egnor60d87622009-12-16 16:32:58 -08006258 /**
6259 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6260 * @param app object of the crashing app, null for the system server
6261 * @param tag reported by the caller
6262 * @param crashInfo describing the context of the error
6263 * @return true if the process should exit immediately (WTF is fatal)
6264 */
6265 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006266 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006267 ProcessRecord r = findAppProcess(app);
6268
6269 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6270 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006271 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006272 tag, crashInfo.exceptionMessage);
6273
Dan Egnor42471dd2010-01-07 17:25:22 -08006274 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006275
Doug Zongker43866e02010-01-07 12:09:54 -08006276 if (Settings.Secure.getInt(mContext.getContentResolver(),
6277 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006278 crashApplication(r, crashInfo);
6279 return true;
6280 } else {
6281 return false;
6282 }
6283 }
6284
6285 /**
6286 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6287 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6288 */
6289 private ProcessRecord findAppProcess(IBinder app) {
6290 if (app == null) {
6291 return null;
6292 }
6293
6294 synchronized (this) {
6295 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6296 final int NA = apps.size();
6297 for (int ia=0; ia<NA; ia++) {
6298 ProcessRecord p = apps.valueAt(ia);
6299 if (p.thread != null && p.thread.asBinder() == app) {
6300 return p;
6301 }
6302 }
6303 }
6304
Joe Onorato8a9b2202010-02-26 18:56:32 -08006305 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006306 return null;
6307 }
6308 }
6309
6310 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006311 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6312 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006313 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006314 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006315 if (process == null || process.pid == MY_PID) {
6316 sb.append("Process: system_server\n");
6317 } else {
6318 sb.append("Process: ").append(process.processName).append("\n");
6319 }
6320 if (process != null) {
6321 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006322 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006323 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6324 for (String pkg : process.pkgList) {
6325 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006326 try {
Dan Egnora455d192010-03-12 08:52:28 -08006327 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6328 if (pi != null) {
6329 sb.append(" v").append(pi.versionCode);
6330 if (pi.versionName != null) {
6331 sb.append(" (").append(pi.versionName).append(")");
6332 }
6333 }
6334 } catch (RemoteException e) {
6335 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006336 }
Dan Egnora455d192010-03-12 08:52:28 -08006337 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006338 }
Dan Egnora455d192010-03-12 08:52:28 -08006339 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006340 }
6341
6342 private static String processClass(ProcessRecord process) {
6343 if (process == null || process.pid == MY_PID) {
6344 return "system_server";
6345 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6346 return "system_app";
6347 } else {
6348 return "data_app";
6349 }
6350 }
6351
6352 /**
6353 * Write a description of an error (crash, WTF, ANR) to the drop box.
6354 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6355 * @param process which caused the error, null means the system server
6356 * @param activity which triggered the error, null if unknown
6357 * @param parent activity related to the error, null if unknown
6358 * @param subject line related to the error, null if absent
6359 * @param report in long form describing the error, null if absent
6360 * @param logFile to include in the report, null if none
6361 * @param crashInfo giving an application stack trace, null if absent
6362 */
6363 public void addErrorToDropBox(String eventType,
6364 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6365 final String report, final File logFile,
6366 final ApplicationErrorReport.CrashInfo crashInfo) {
6367 // NOTE -- this must never acquire the ActivityManagerService lock,
6368 // otherwise the watchdog may be prevented from resetting the system.
6369
6370 final String dropboxTag = processClass(process) + "_" + eventType;
6371 final DropBoxManager dbox = (DropBoxManager)
6372 mContext.getSystemService(Context.DROPBOX_SERVICE);
6373
6374 // Exit early if the dropbox isn't configured to accept this report type.
6375 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6376
6377 final StringBuilder sb = new StringBuilder(1024);
6378 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006379 if (activity != null) {
6380 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6381 }
6382 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6383 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6384 }
6385 if (parent != null && parent != activity) {
6386 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6387 }
6388 if (subject != null) {
6389 sb.append("Subject: ").append(subject).append("\n");
6390 }
6391 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6392 sb.append("\n");
6393
6394 // Do the rest in a worker thread to avoid blocking the caller on I/O
6395 // (After this point, we shouldn't access AMS internal data structures.)
6396 Thread worker = new Thread("Error dump: " + dropboxTag) {
6397 @Override
6398 public void run() {
6399 if (report != null) {
6400 sb.append(report);
6401 }
6402 if (logFile != null) {
6403 try {
6404 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6405 } catch (IOException e) {
6406 Slog.e(TAG, "Error reading " + logFile, e);
6407 }
6408 }
6409 if (crashInfo != null && crashInfo.stackTrace != null) {
6410 sb.append(crashInfo.stackTrace);
6411 }
6412
6413 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6414 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6415 if (lines > 0) {
6416 sb.append("\n");
6417
6418 // Merge several logcat streams, and take the last N lines
6419 InputStreamReader input = null;
6420 try {
6421 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6422 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6423 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6424
6425 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6426 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6427 input = new InputStreamReader(logcat.getInputStream());
6428
6429 int num;
6430 char[] buf = new char[8192];
6431 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6432 } catch (IOException e) {
6433 Slog.e(TAG, "Error running logcat", e);
6434 } finally {
6435 if (input != null) try { input.close(); } catch (IOException e) {}
6436 }
6437 }
6438
6439 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006440 }
Dan Egnora455d192010-03-12 08:52:28 -08006441 };
6442
6443 if (process == null || process.pid == MY_PID) {
6444 worker.run(); // We may be about to die -- need to run this synchronously
6445 } else {
6446 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006447 }
6448 }
6449
6450 /**
6451 * Bring up the "unexpected error" dialog box for a crashing app.
6452 * Deal with edge cases (intercepts from instrumented applications,
6453 * ActivityController, error intent receivers, that sort of thing).
6454 * @param r the application crashing
6455 * @param crashInfo describing the failure
6456 */
6457 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006458 long timeMillis = System.currentTimeMillis();
6459 String shortMsg = crashInfo.exceptionClassName;
6460 String longMsg = crashInfo.exceptionMessage;
6461 String stackTrace = crashInfo.stackTrace;
6462 if (shortMsg != null && longMsg != null) {
6463 longMsg = shortMsg + ": " + longMsg;
6464 } else if (shortMsg != null) {
6465 longMsg = shortMsg;
6466 }
6467
Dan Egnor60d87622009-12-16 16:32:58 -08006468 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006470 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 try {
6472 String name = r != null ? r.processName : null;
6473 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006474 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006475 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006476 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 + " at watcher's request");
6478 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006479 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 }
6481 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006482 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 }
6484 }
6485
6486 final long origId = Binder.clearCallingIdentity();
6487
6488 // If this process is running instrumentation, finish it.
6489 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006490 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006492 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6493 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006494 Bundle info = new Bundle();
6495 info.putString("shortMsg", shortMsg);
6496 info.putString("longMsg", longMsg);
6497 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6498 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006499 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500 }
6501
Dan Egnor60d87622009-12-16 16:32:58 -08006502 // If we can't identify the process or it's already exceeded its crash quota,
6503 // quit right away without showing a crash dialog.
6504 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006506 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 }
6508
6509 Message msg = Message.obtain();
6510 msg.what = SHOW_ERROR_MSG;
6511 HashMap data = new HashMap();
6512 data.put("result", result);
6513 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 msg.obj = data;
6515 mHandler.sendMessage(msg);
6516
6517 Binder.restoreCallingIdentity(origId);
6518 }
6519
6520 int res = result.get();
6521
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006522 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 synchronized (this) {
6524 if (r != null) {
6525 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6526 SystemClock.uptimeMillis());
6527 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006528 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006529 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006530 }
6531 }
6532
6533 if (appErrorIntent != null) {
6534 try {
6535 mContext.startActivity(appErrorIntent);
6536 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006537 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006541
6542 Intent createAppErrorIntentLocked(ProcessRecord r,
6543 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6544 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006545 if (report == null) {
6546 return null;
6547 }
6548 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6549 result.setComponent(r.errorReportReceiver);
6550 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6551 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6552 return result;
6553 }
6554
Dan Egnorb7f03672009-12-09 16:22:32 -08006555 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6556 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006557 if (r.errorReportReceiver == null) {
6558 return null;
6559 }
6560
6561 if (!r.crashing && !r.notResponding) {
6562 return null;
6563 }
6564
Dan Egnorb7f03672009-12-09 16:22:32 -08006565 ApplicationErrorReport report = new ApplicationErrorReport();
6566 report.packageName = r.info.packageName;
6567 report.installerPackageName = r.errorReportReceiver.getPackageName();
6568 report.processName = r.processName;
6569 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006570 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006571
Dan Egnorb7f03672009-12-09 16:22:32 -08006572 if (r.crashing) {
6573 report.type = ApplicationErrorReport.TYPE_CRASH;
6574 report.crashInfo = crashInfo;
6575 } else if (r.notResponding) {
6576 report.type = ApplicationErrorReport.TYPE_ANR;
6577 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006578
Dan Egnorb7f03672009-12-09 16:22:32 -08006579 report.anrInfo.activity = r.notRespondingReport.tag;
6580 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6581 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006582 }
6583
Dan Egnorb7f03672009-12-09 16:22:32 -08006584 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006585 }
6586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006587 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6588 // assume our apps are happy - lazy create the list
6589 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6590
6591 synchronized (this) {
6592
6593 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006594 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6595 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006596 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6597 // This one's in trouble, so we'll generate a report for it
6598 // crashes are higher priority (in case there's a crash *and* an anr)
6599 ActivityManager.ProcessErrorStateInfo report = null;
6600 if (app.crashing) {
6601 report = app.crashingReport;
6602 } else if (app.notResponding) {
6603 report = app.notRespondingReport;
6604 }
6605
6606 if (report != null) {
6607 if (errList == null) {
6608 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6609 }
6610 errList.add(report);
6611 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006612 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 " crashing = " + app.crashing +
6614 " notResponding = " + app.notResponding);
6615 }
6616 }
6617 }
6618 }
6619
6620 return errList;
6621 }
6622
6623 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6624 // Lazy instantiation of list
6625 List<ActivityManager.RunningAppProcessInfo> runList = null;
6626 synchronized (this) {
6627 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006628 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6629 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6631 // Generate process state info for running application
6632 ActivityManager.RunningAppProcessInfo currApp =
6633 new ActivityManager.RunningAppProcessInfo(app.processName,
6634 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006635 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006636 if (mHeavyWeightProcess == app) {
6637 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006640 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6642 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6643 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006644 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6645 } else if (adj >= HOME_APP_ADJ) {
6646 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6647 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006648 } else if (adj >= SECONDARY_SERVER_ADJ) {
6649 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006650 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6651 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6652 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6653 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006654 } else if (adj >= VISIBLE_APP_ADJ) {
6655 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6656 } else {
6657 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6658 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006659 currApp.importanceReasonCode = app.adjTypeCode;
6660 if (app.adjSource instanceof ProcessRecord) {
6661 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006662 } else if (app.adjSource instanceof ActivityRecord) {
6663 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006664 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6665 }
6666 if (app.adjTarget instanceof ComponentName) {
6667 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6668 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006669 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 // + " lru=" + currApp.lru);
6671 if (runList == null) {
6672 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6673 }
6674 runList.add(currApp);
6675 }
6676 }
6677 }
6678 return runList;
6679 }
6680
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006681 public List<ApplicationInfo> getRunningExternalApplications() {
6682 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6683 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6684 if (runningApps != null && runningApps.size() > 0) {
6685 Set<String> extList = new HashSet<String>();
6686 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6687 if (app.pkgList != null) {
6688 for (String pkg : app.pkgList) {
6689 extList.add(pkg);
6690 }
6691 }
6692 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006693 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006694 for (String pkg : extList) {
6695 try {
6696 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6697 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6698 retList.add(info);
6699 }
6700 } catch (RemoteException e) {
6701 }
6702 }
6703 }
6704 return retList;
6705 }
6706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 @Override
6708 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006709 if (checkCallingPermission(android.Manifest.permission.DUMP)
6710 != PackageManager.PERMISSION_GRANTED) {
6711 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6712 + Binder.getCallingPid()
6713 + ", uid=" + Binder.getCallingUid()
6714 + " without permission "
6715 + android.Manifest.permission.DUMP);
6716 return;
6717 }
6718
6719 boolean dumpAll = false;
6720
6721 int opti = 0;
6722 while (opti < args.length) {
6723 String opt = args[opti];
6724 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6725 break;
6726 }
6727 opti++;
6728 if ("-a".equals(opt)) {
6729 dumpAll = true;
6730 } else if ("-h".equals(opt)) {
6731 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006732 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006733 pw.println(" cmd may be one of:");
6734 pw.println(" activities: activity stack state");
6735 pw.println(" broadcasts: broadcast state");
6736 pw.println(" intents: pending intent state");
6737 pw.println(" processes: process state");
6738 pw.println(" providers: content provider state");
6739 pw.println(" services: service state");
6740 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006742 } else {
6743 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006745 }
6746
6747 // Is the caller requesting to dump a particular piece of data?
6748 if (opti < args.length) {
6749 String cmd = args[opti];
6750 opti++;
6751 if ("activities".equals(cmd) || "a".equals(cmd)) {
6752 synchronized (this) {
6753 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006755 return;
6756 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6757 synchronized (this) {
6758 dumpBroadcastsLocked(fd, pw, args, opti, true);
6759 }
6760 return;
6761 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6762 synchronized (this) {
6763 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6764 }
6765 return;
6766 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6767 synchronized (this) {
6768 dumpProcessesLocked(fd, pw, args, opti, true);
6769 }
6770 return;
6771 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6772 synchronized (this) {
6773 dumpProvidersLocked(fd, pw, args, opti, true);
6774 }
6775 return;
6776 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006777 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006778 return;
6779 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6780 synchronized (this) {
6781 dumpServicesLocked(fd, pw, args, opti, true);
6782 }
6783 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006785 }
6786
6787 // No piece of data specified, dump everything.
6788 synchronized (this) {
6789 boolean needSep;
6790 if (dumpAll) {
6791 pw.println("Providers in Current Activity Manager State:");
6792 }
6793 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6794 if (needSep) {
6795 pw.println(" ");
6796 }
6797 if (dumpAll) {
6798 pw.println("-------------------------------------------------------------------------------");
6799 pw.println("Broadcasts in Current Activity Manager State:");
6800 }
6801 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6802 if (needSep) {
6803 pw.println(" ");
6804 }
6805 if (dumpAll) {
6806 pw.println("-------------------------------------------------------------------------------");
6807 pw.println("Services in Current Activity Manager State:");
6808 }
6809 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6810 if (needSep) {
6811 pw.println(" ");
6812 }
6813 if (dumpAll) {
6814 pw.println("-------------------------------------------------------------------------------");
6815 pw.println("PendingIntents in Current Activity Manager State:");
6816 }
6817 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6818 if (needSep) {
6819 pw.println(" ");
6820 }
6821 if (dumpAll) {
6822 pw.println("-------------------------------------------------------------------------------");
6823 pw.println("Activities in Current Activity Manager State:");
6824 }
6825 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6826 if (needSep) {
6827 pw.println(" ");
6828 }
6829 if (dumpAll) {
6830 pw.println("-------------------------------------------------------------------------------");
6831 pw.println("Processes in Current Activity Manager State:");
6832 }
6833 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6834 }
6835 }
6836
6837 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6838 int opti, boolean dumpAll, boolean needHeader) {
6839 if (needHeader) {
6840 pw.println(" Activity stack:");
6841 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006842 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006843 pw.println(" ");
6844 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006845 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6846 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006848 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006849 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006850 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006851 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006852 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006853 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006854 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006855 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006856 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006857 pw.println(" ");
6858 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006859 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006861
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006862 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006863 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6864 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006865 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006866 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006867
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006868 if (dumpAll && mRecentTasks.size() > 0) {
6869 pw.println(" ");
6870 pw.println("Recent tasks in Current Activity Manager State:");
6871
6872 final int N = mRecentTasks.size();
6873 for (int i=0; i<N; i++) {
6874 TaskRecord tr = mRecentTasks.get(i);
6875 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6876 pw.println(tr);
6877 mRecentTasks.get(i).dump(pw, " ");
6878 }
6879 }
6880
6881 pw.println(" ");
6882 pw.println(" mCurTask: " + mCurTask);
6883
6884 return true;
6885 }
6886
6887 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6888 int opti, boolean dumpAll) {
6889 boolean needSep = false;
6890 int numPers = 0;
6891
6892 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006893 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6894 final int NA = procs.size();
6895 for (int ia=0; ia<NA; ia++) {
6896 if (!needSep) {
6897 pw.println(" All known processes:");
6898 needSep = true;
6899 }
6900 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006901 pw.print(r.persistent ? " *PERS*" : " *APP*");
6902 pw.print(" UID "); pw.print(procs.keyAt(ia));
6903 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006904 r.dump(pw, " ");
6905 if (r.persistent) {
6906 numPers++;
6907 }
6908 }
6909 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006910 }
6911
6912 if (mLruProcesses.size() > 0) {
6913 if (needSep) pw.println(" ");
6914 needSep = true;
6915 pw.println(" Running processes (most recent first):");
6916 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006917 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006918 needSep = true;
6919 }
6920
6921 synchronized (mPidsSelfLocked) {
6922 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 if (needSep) pw.println(" ");
6924 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006925 pw.println(" PID mappings:");
6926 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6927 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6928 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006929 }
6930 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006931 }
6932
6933 if (mForegroundProcesses.size() > 0) {
6934 if (needSep) pw.println(" ");
6935 needSep = true;
6936 pw.println(" Foreground Processes:");
6937 for (int i=0; i<mForegroundProcesses.size(); i++) {
6938 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6939 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006941 }
6942
6943 if (mPersistentStartingProcesses.size() > 0) {
6944 if (needSep) pw.println(" ");
6945 needSep = true;
6946 pw.println(" Persisent processes that are starting:");
6947 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6948 "Starting Norm", "Restarting PERS", false);
6949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006951 if (mStartingProcesses.size() > 0) {
6952 if (needSep) pw.println(" ");
6953 needSep = true;
6954 pw.println(" Processes that are starting:");
6955 dumpProcessList(pw, this, mStartingProcesses, " ",
6956 "Starting Norm", "Starting PERS", false);
6957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006959 if (mRemovedProcesses.size() > 0) {
6960 if (needSep) pw.println(" ");
6961 needSep = true;
6962 pw.println(" Processes that are being removed:");
6963 dumpProcessList(pw, this, mRemovedProcesses, " ",
6964 "Removed Norm", "Removed PERS", false);
6965 }
6966
6967 if (mProcessesOnHold.size() > 0) {
6968 if (needSep) pw.println(" ");
6969 needSep = true;
6970 pw.println(" Processes that are on old until the system is ready:");
6971 dumpProcessList(pw, this, mProcessesOnHold, " ",
6972 "OnHold Norm", "OnHold PERS", false);
6973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006975 if (mProcessesToGc.size() > 0) {
6976 if (needSep) pw.println(" ");
6977 needSep = true;
6978 pw.println(" Processes that are waiting to GC:");
6979 long now = SystemClock.uptimeMillis();
6980 for (int i=0; i<mProcessesToGc.size(); i++) {
6981 ProcessRecord proc = mProcessesToGc.get(i);
6982 pw.print(" Process "); pw.println(proc);
6983 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
6984 pw.print(", last gced=");
6985 pw.print(now-proc.lastRequestedGc);
6986 pw.print(" ms ago, last lowMem=");
6987 pw.print(now-proc.lastLowMemory);
6988 pw.println(" ms ago");
6989
6990 }
6991 }
6992
6993 if (mProcessCrashTimes.getMap().size() > 0) {
6994 if (needSep) pw.println(" ");
6995 needSep = true;
6996 pw.println(" Time since processes crashed:");
6997 long now = SystemClock.uptimeMillis();
6998 for (Map.Entry<String, SparseArray<Long>> procs
6999 : mProcessCrashTimes.getMap().entrySet()) {
7000 SparseArray<Long> uids = procs.getValue();
7001 final int N = uids.size();
7002 for (int i=0; i<N; i++) {
7003 pw.print(" Process "); pw.print(procs.getKey());
7004 pw.print(" uid "); pw.print(uids.keyAt(i));
7005 pw.print(": last crashed ");
7006 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007007 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007008 }
7009 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007012 if (mBadProcesses.getMap().size() > 0) {
7013 if (needSep) pw.println(" ");
7014 needSep = true;
7015 pw.println(" Bad processes:");
7016 for (Map.Entry<String, SparseArray<Long>> procs
7017 : mBadProcesses.getMap().entrySet()) {
7018 SparseArray<Long> uids = procs.getValue();
7019 final int N = uids.size();
7020 for (int i=0; i<N; i++) {
7021 pw.print(" Bad process "); pw.print(procs.getKey());
7022 pw.print(" uid "); pw.print(uids.keyAt(i));
7023 pw.print(": crashed at time ");
7024 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007025 }
7026 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007028
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007029 pw.println(" ");
7030 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007031 if (mHeavyWeightProcess != null) {
7032 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7033 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007034 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007035 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007036 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7037 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7038 || mOrigWaitForDebugger) {
7039 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7040 + " mDebugTransient=" + mDebugTransient
7041 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7042 }
7043 if (mAlwaysFinishActivities || mController != null) {
7044 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7045 + " mController=" + mController);
7046 }
7047 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 pw.println(" mStartRunning=" + mStartRunning
7050 + " mSystemReady=" + mSystemReady
7051 + " mBooting=" + mBooting
7052 + " mBooted=" + mBooted
7053 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007054 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7055 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007056 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007058
7059 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 }
7061
7062 /**
7063 * There are three ways to call this:
7064 * - no service specified: dump all the services
7065 * - a flattened component name that matched an existing service was specified as the
7066 * first arg: dump that one service
7067 * - the first arg isn't the flattened component name of an existing service:
7068 * dump all services whose component contains the first arg as a substring
7069 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007070 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7071 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 String[] newArgs;
7073 String componentNameString;
7074 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007075 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007076 componentNameString = null;
7077 newArgs = EMPTY_STRING_ARRAY;
7078 r = null;
7079 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007080 componentNameString = args[opti];
7081 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007083 synchronized (this) {
7084 r = componentName != null ? mServices.get(componentName) : null;
7085 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007086 newArgs = new String[args.length - opti];
7087 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088 }
7089
7090 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007091 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007093 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7094 synchronized (this) {
7095 for (ServiceRecord r1 : mServices.values()) {
7096 if (componentNameString == null
7097 || r1.name.flattenToString().contains(componentNameString)) {
7098 services.add(r1);
7099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 }
7101 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007102 for (int i=0; i<services.size(); i++) {
7103 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 }
7106 }
7107
7108 /**
7109 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7110 * there is a thread associated with the service.
7111 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007112 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7113 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007115 if (dumpAll) {
7116 synchronized (this) {
7117 pw.print(" * "); pw.println(r);
7118 r.dump(pw, " ");
7119 }
7120 pw.println("");
7121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007122 if (r.app != null && r.app.thread != null) {
7123 try {
7124 // flush anything that is already in the PrintWriter since the thread is going
7125 // to write to the file descriptor directly
7126 pw.flush();
7127 r.app.thread.dumpService(fd, r, args);
7128 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007129 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 } catch (RemoteException e) {
7131 pw.println("got a RemoteException while dumping the service");
7132 }
7133 }
7134 }
7135
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007136 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7137 int opti, boolean dumpAll) {
7138 boolean needSep = false;
7139
7140 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007141 if (mRegisteredReceivers.size() > 0) {
7142 pw.println(" ");
7143 pw.println(" Registered Receivers:");
7144 Iterator it = mRegisteredReceivers.values().iterator();
7145 while (it.hasNext()) {
7146 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007147 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 r.dump(pw, " ");
7149 }
7150 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152 pw.println(" ");
7153 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007154 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007155 needSep = true;
7156 }
7157
7158 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7159 || mPendingBroadcast != null) {
7160 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007162 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007163 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007164 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7165 pw.println(" Broadcast #" + i + ":");
7166 mParallelBroadcasts.get(i).dump(pw, " ");
7167 }
7168 if (mOrderedBroadcasts.size() > 0) {
7169 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007170 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007171 }
7172 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7173 pw.println(" Serialized Broadcast #" + i + ":");
7174 mOrderedBroadcasts.get(i).dump(pw, " ");
7175 }
7176 pw.println(" ");
7177 pw.println(" Pending broadcast:");
7178 if (mPendingBroadcast != null) {
7179 mPendingBroadcast.dump(pw, " ");
7180 } else {
7181 pw.println(" (null)");
7182 }
7183 needSep = true;
7184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007185
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007186 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007187 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007188 pw.println(" Historical broadcasts:");
7189 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7190 BroadcastRecord r = mBroadcastHistory[i];
7191 if (r == null) {
7192 break;
7193 }
7194 pw.println(" Historical Broadcast #" + i + ":");
7195 r.dump(pw, " ");
7196 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007197 needSep = true;
7198 }
7199
7200 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007201 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007202 pw.println(" Sticky broadcasts:");
7203 StringBuilder sb = new StringBuilder(128);
7204 for (Map.Entry<String, ArrayList<Intent>> ent
7205 : mStickyBroadcasts.entrySet()) {
7206 pw.print(" * Sticky action "); pw.print(ent.getKey());
7207 pw.println(":");
7208 ArrayList<Intent> intents = ent.getValue();
7209 final int N = intents.size();
7210 for (int i=0; i<N; i++) {
7211 sb.setLength(0);
7212 sb.append(" Intent: ");
7213 intents.get(i).toShortString(sb, true, false);
7214 pw.println(sb.toString());
7215 Bundle bundle = intents.get(i).getExtras();
7216 if (bundle != null) {
7217 pw.print(" ");
7218 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 }
7220 }
7221 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007222 needSep = true;
7223 }
7224
7225 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007227 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 pw.println(" mHandler:");
7229 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007230 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007231 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007232
7233 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 }
7235
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007236 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7237 int opti, boolean dumpAll) {
7238 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007239
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007240 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 if (mServices.size() > 0) {
7242 pw.println(" Active services:");
7243 Iterator<ServiceRecord> it = mServices.values().iterator();
7244 while (it.hasNext()) {
7245 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007246 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247 r.dump(pw, " ");
7248 }
7249 needSep = true;
7250 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 if (mPendingServices.size() > 0) {
7254 if (needSep) pw.println(" ");
7255 pw.println(" Pending services:");
7256 for (int i=0; i<mPendingServices.size(); i++) {
7257 ServiceRecord r = mPendingServices.get(i);
7258 pw.print(" * Pending "); pw.println(r);
7259 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007260 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007261 needSep = true;
7262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007263
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007264 if (mRestartingServices.size() > 0) {
7265 if (needSep) pw.println(" ");
7266 pw.println(" Restarting services:");
7267 for (int i=0; i<mRestartingServices.size(); i++) {
7268 ServiceRecord r = mRestartingServices.get(i);
7269 pw.print(" * Restarting "); pw.println(r);
7270 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 needSep = true;
7273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007274
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007275 if (mStoppingServices.size() > 0) {
7276 if (needSep) pw.println(" ");
7277 pw.println(" Stopping services:");
7278 for (int i=0; i<mStoppingServices.size(); i++) {
7279 ServiceRecord r = mStoppingServices.get(i);
7280 pw.print(" * Stopping "); pw.println(r);
7281 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007282 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007283 needSep = true;
7284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007286 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 if (mServiceConnections.size() > 0) {
7288 if (needSep) pw.println(" ");
7289 pw.println(" Connection bindings to services:");
7290 Iterator<ConnectionRecord> it
7291 = mServiceConnections.values().iterator();
7292 while (it.hasNext()) {
7293 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007294 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 r.dump(pw, " ");
7296 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007297 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 }
7299 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007300
7301 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 }
7303
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007304 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7305 int opti, boolean dumpAll) {
7306 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007308 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 if (mProvidersByClass.size() > 0) {
7310 if (needSep) pw.println(" ");
7311 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007312 Iterator<Map.Entry<String, ContentProviderRecord>> it
7313 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007315 Map.Entry<String, ContentProviderRecord> e = it.next();
7316 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007317 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 r.dump(pw, " ");
7319 }
7320 needSep = true;
7321 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007322
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007323 if (mProvidersByName.size() > 0) {
7324 pw.println(" ");
7325 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007326 Iterator<Map.Entry<String, ContentProviderRecord>> it
7327 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007328 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007329 Map.Entry<String, ContentProviderRecord> e = it.next();
7330 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007331 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7332 pw.println(r);
7333 }
7334 needSep = true;
7335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007337
7338 if (mLaunchingProviders.size() > 0) {
7339 if (needSep) pw.println(" ");
7340 pw.println(" Launching content providers:");
7341 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7342 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7343 pw.println(mLaunchingProviders.get(i));
7344 }
7345 needSep = true;
7346 }
7347
7348 if (mGrantedUriPermissions.size() > 0) {
7349 pw.println();
7350 pw.println("Granted Uri Permissions:");
7351 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7352 int uid = mGrantedUriPermissions.keyAt(i);
7353 HashMap<Uri, UriPermission> perms
7354 = mGrantedUriPermissions.valueAt(i);
7355 pw.print(" * UID "); pw.print(uid);
7356 pw.println(" holds:");
7357 for (UriPermission perm : perms.values()) {
7358 pw.print(" "); pw.println(perm);
7359 perm.dump(pw, " ");
7360 }
7361 }
7362 needSep = true;
7363 }
7364
7365 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 }
7367
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007368 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7369 int opti, boolean dumpAll) {
7370 boolean needSep = false;
7371
7372 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 if (this.mIntentSenderRecords.size() > 0) {
7374 Iterator<WeakReference<PendingIntentRecord>> it
7375 = mIntentSenderRecords.values().iterator();
7376 while (it.hasNext()) {
7377 WeakReference<PendingIntentRecord> ref = it.next();
7378 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007379 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007381 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 rec.dump(pw, " ");
7383 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007384 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007385 }
7386 }
7387 }
7388 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007389
7390 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 }
7392
7393 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007394 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395 TaskRecord lastTask = null;
7396 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007397 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007398 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 if (lastTask != r.task) {
7400 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007401 pw.print(prefix);
7402 pw.print(full ? "* " : " ");
7403 pw.println(lastTask);
7404 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007405 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007408 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7409 pw.print(" #"); pw.print(i); pw.print(": ");
7410 pw.println(r);
7411 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007412 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 }
7415 }
7416
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007417 private static String buildOomTag(String prefix, String space, int val, int base) {
7418 if (val == base) {
7419 if (space == null) return prefix;
7420 return prefix + " ";
7421 }
7422 return prefix + "+" + Integer.toString(val-base);
7423 }
7424
7425 private static final int dumpProcessList(PrintWriter pw,
7426 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 String prefix, String normalLabel, String persistentLabel,
7428 boolean inclOomAdj) {
7429 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007430 final int N = list.size()-1;
7431 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 ProcessRecord r = (ProcessRecord)list.get(i);
7433 if (false) {
7434 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7435 + " #" + i + ":");
7436 r.dump(pw, prefix + " ");
7437 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007438 String oomAdj;
7439 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007440 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007441 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007442 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7443 } else if (r.setAdj >= HOME_APP_ADJ) {
7444 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7445 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7446 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7447 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7448 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007449 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7450 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7451 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7452 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007453 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7454 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7455 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7456 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007457 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007458 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007459 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007460 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007461 } else {
7462 oomAdj = Integer.toString(r.setAdj);
7463 }
7464 String schedGroup;
7465 switch (r.setSchedGroup) {
7466 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7467 schedGroup = "B";
7468 break;
7469 case Process.THREAD_GROUP_DEFAULT:
7470 schedGroup = "F";
7471 break;
7472 default:
7473 schedGroup = Integer.toString(r.setSchedGroup);
7474 break;
7475 }
7476 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007478 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007479 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007480 pw.print(prefix);
7481 pw.print(" ");
7482 if (r.adjTarget instanceof ComponentName) {
7483 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7484 } else if (r.adjTarget != null) {
7485 pw.print(r.adjTarget.toString());
7486 } else {
7487 pw.print("{null}");
7488 }
7489 pw.print("<=");
7490 if (r.adjSource instanceof ProcessRecord) {
7491 pw.print("Proc{");
7492 pw.print(((ProcessRecord)r.adjSource).toShortString());
7493 pw.println("}");
7494 } else if (r.adjSource != null) {
7495 pw.println(r.adjSource.toString());
7496 } else {
7497 pw.println("{null}");
7498 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007500 } else {
7501 pw.println(String.format("%s%s #%2d: %s",
7502 prefix, (r.persistent ? persistentLabel : normalLabel),
7503 i, r.toString()));
7504 }
7505 if (r.persistent) {
7506 numPers++;
7507 }
7508 }
7509 return numPers;
7510 }
7511
Dianne Hackborn472ad872010-04-07 17:31:48 -07007512 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007514 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 long uptime = SystemClock.uptimeMillis();
7516 long realtime = SystemClock.elapsedRealtime();
7517
7518 if (isCheckinRequest) {
7519 // short checkin version
7520 pw.println(uptime + "," + realtime);
7521 pw.flush();
7522 } else {
7523 pw.println("Applications Memory Usage (kB):");
7524 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7525 }
7526 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7527 ProcessRecord r = (ProcessRecord)list.get(i);
7528 if (r.thread != null) {
7529 if (!isCheckinRequest) {
7530 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7531 pw.flush();
7532 }
7533 try {
7534 r.thread.asBinder().dump(fd, args);
7535 } catch (RemoteException e) {
7536 if (!isCheckinRequest) {
7537 pw.println("Got RemoteException!");
7538 pw.flush();
7539 }
7540 }
7541 }
7542 }
7543 }
7544
7545 /**
7546 * Searches array of arguments for the specified string
7547 * @param args array of argument strings
7548 * @param value value to search for
7549 * @return true if the value is contained in the array
7550 */
7551 private static boolean scanArgs(String[] args, String value) {
7552 if (args != null) {
7553 for (String arg : args) {
7554 if (value.equals(arg)) {
7555 return true;
7556 }
7557 }
7558 }
7559 return false;
7560 }
7561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 private final void killServicesLocked(ProcessRecord app,
7563 boolean allowRestart) {
7564 // Report disconnected services.
7565 if (false) {
7566 // XXX we are letting the client link to the service for
7567 // death notifications.
7568 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007569 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007571 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 if (r.connections.size() > 0) {
7573 Iterator<ConnectionRecord> jt
7574 = r.connections.values().iterator();
7575 while (jt.hasNext()) {
7576 ConnectionRecord c = jt.next();
7577 if (c.binding.client != app) {
7578 try {
7579 //c.conn.connected(r.className, null);
7580 } catch (Exception e) {
7581 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007582 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 + r.shortName
7584 + " from app " + app.processName, e);
7585 }
7586 }
7587 }
7588 }
7589 }
7590 }
7591 }
7592
7593 // Clean up any connections this application has to other services.
7594 if (app.connections.size() > 0) {
7595 Iterator<ConnectionRecord> it = app.connections.iterator();
7596 while (it.hasNext()) {
7597 ConnectionRecord r = it.next();
7598 removeConnectionLocked(r, app, null);
7599 }
7600 }
7601 app.connections.clear();
7602
7603 if (app.services.size() != 0) {
7604 // Any services running in the application need to be placed
7605 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007606 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007608 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007609 synchronized (sr.stats.getBatteryStats()) {
7610 sr.stats.stopLaunchedLocked();
7611 }
7612 sr.app = null;
7613 sr.executeNesting = 0;
7614 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007615
7616 boolean hasClients = sr.bindings.size() > 0;
7617 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 Iterator<IntentBindRecord> bindings
7619 = sr.bindings.values().iterator();
7620 while (bindings.hasNext()) {
7621 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007622 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007623 + ": shouldUnbind=" + b.hasBound);
7624 b.binder = null;
7625 b.requested = b.received = b.hasBound = false;
7626 }
7627 }
7628
7629 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007630 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007632 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 sr.crashCount, sr.shortName, app.pid);
7634 bringDownServiceLocked(sr, true);
7635 } else if (!allowRestart) {
7636 bringDownServiceLocked(sr, true);
7637 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007638 boolean canceled = scheduleServiceRestartLocked(sr, true);
7639
7640 // Should the service remain running? Note that in the
7641 // extreme case of so many attempts to deliver a command
7642 // that it failed, that we also will stop it here.
7643 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7644 if (sr.pendingStarts.size() == 0) {
7645 sr.startRequested = false;
7646 if (!hasClients) {
7647 // Whoops, no reason to restart!
7648 bringDownServiceLocked(sr, true);
7649 }
7650 }
7651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 }
7653 }
7654
7655 if (!allowRestart) {
7656 app.services.clear();
7657 }
7658 }
7659
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007660 // Make sure we have no more records on the stopping list.
7661 int i = mStoppingServices.size();
7662 while (i > 0) {
7663 i--;
7664 ServiceRecord sr = mStoppingServices.get(i);
7665 if (sr.app == app) {
7666 mStoppingServices.remove(i);
7667 }
7668 }
7669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 app.executingServices.clear();
7671 }
7672
7673 private final void removeDyingProviderLocked(ProcessRecord proc,
7674 ContentProviderRecord cpr) {
7675 synchronized (cpr) {
7676 cpr.launchingApp = null;
7677 cpr.notifyAll();
7678 }
7679
7680 mProvidersByClass.remove(cpr.info.name);
7681 String names[] = cpr.info.authority.split(";");
7682 for (int j = 0; j < names.length; j++) {
7683 mProvidersByName.remove(names[j]);
7684 }
7685
7686 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7687 while (cit.hasNext()) {
7688 ProcessRecord capp = cit.next();
7689 if (!capp.persistent && capp.thread != null
7690 && capp.pid != 0
7691 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007692 Slog.i(TAG, "Kill " + capp.processName
7693 + " (pid " + capp.pid + "): provider " + cpr.info.name
7694 + " in dying process " + proc.processName);
7695 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7696 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 Process.killProcess(capp.pid);
7698 }
7699 }
7700
7701 mLaunchingProviders.remove(cpr);
7702 }
7703
7704 /**
7705 * Main code for cleaning up a process when it has gone away. This is
7706 * called both as a result of the process dying, or directly when stopping
7707 * a process when running in single process mode.
7708 */
7709 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7710 boolean restarting, int index) {
7711 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007712 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 }
7714
Dianne Hackborn36124872009-10-08 16:22:03 -07007715 mProcessesToGc.remove(app);
7716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 // Dismiss any open dialogs.
7718 if (app.crashDialog != null) {
7719 app.crashDialog.dismiss();
7720 app.crashDialog = null;
7721 }
7722 if (app.anrDialog != null) {
7723 app.anrDialog.dismiss();
7724 app.anrDialog = null;
7725 }
7726 if (app.waitDialog != null) {
7727 app.waitDialog.dismiss();
7728 app.waitDialog = null;
7729 }
7730
7731 app.crashing = false;
7732 app.notResponding = false;
7733
7734 app.resetPackageList();
7735 app.thread = null;
7736 app.forcingToForeground = null;
7737 app.foregroundServices = false;
7738
7739 killServicesLocked(app, true);
7740
7741 boolean restart = false;
7742
7743 int NL = mLaunchingProviders.size();
7744
7745 // Remove published content providers.
7746 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007747 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007749 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 cpr.provider = null;
7751 cpr.app = null;
7752
7753 // See if someone is waiting for this provider... in which
7754 // case we don't remove it, but just let it restart.
7755 int i = 0;
7756 if (!app.bad) {
7757 for (; i<NL; i++) {
7758 if (mLaunchingProviders.get(i) == cpr) {
7759 restart = true;
7760 break;
7761 }
7762 }
7763 } else {
7764 i = NL;
7765 }
7766
7767 if (i >= NL) {
7768 removeDyingProviderLocked(app, cpr);
7769 NL = mLaunchingProviders.size();
7770 }
7771 }
7772 app.pubProviders.clear();
7773 }
7774
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007775 // Take care of any launching providers waiting for this process.
7776 if (checkAppInLaunchingProvidersLocked(app, false)) {
7777 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007778 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007780 // Unregister from connected content providers.
7781 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007782 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 while (it.hasNext()) {
7784 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7785 cpr.clients.remove(app);
7786 }
7787 app.conProviders.clear();
7788 }
7789
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007790 // At this point there may be remaining entries in mLaunchingProviders
7791 // where we were the only one waiting, so they are no longer of use.
7792 // Look for these and clean up if found.
7793 // XXX Commented out for now. Trying to figure out a way to reproduce
7794 // the actual situation to identify what is actually going on.
7795 if (false) {
7796 for (int i=0; i<NL; i++) {
7797 ContentProviderRecord cpr = (ContentProviderRecord)
7798 mLaunchingProviders.get(i);
7799 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7800 synchronized (cpr) {
7801 cpr.launchingApp = null;
7802 cpr.notifyAll();
7803 }
7804 }
7805 }
7806 }
7807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 skipCurrentReceiverLocked(app);
7809
7810 // Unregister any receivers.
7811 if (app.receivers.size() > 0) {
7812 Iterator<ReceiverList> it = app.receivers.iterator();
7813 while (it.hasNext()) {
7814 removeReceiverLocked(it.next());
7815 }
7816 app.receivers.clear();
7817 }
7818
Christopher Tate181fafa2009-05-14 11:12:14 -07007819 // If the app is undergoing backup, tell the backup manager about it
7820 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007821 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007822 try {
7823 IBackupManager bm = IBackupManager.Stub.asInterface(
7824 ServiceManager.getService(Context.BACKUP_SERVICE));
7825 bm.agentDisconnected(app.info.packageName);
7826 } catch (RemoteException e) {
7827 // can't happen; backup manager is local
7828 }
7829 }
7830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 // If the caller is restarting this app, then leave it in its
7832 // current lists and let the caller take care of it.
7833 if (restarting) {
7834 return;
7835 }
7836
7837 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007838 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 "Removing non-persistent process during cleanup: " + app);
7840 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007841 if (mHeavyWeightProcess == app) {
7842 mHeavyWeightProcess = null;
7843 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 } else if (!app.removed) {
7846 // This app is persistent, so we need to keep its record around.
7847 // If it is not already on the pending app list, add it there
7848 // and start a new process for it.
7849 app.thread = null;
7850 app.forcingToForeground = null;
7851 app.foregroundServices = false;
7852 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7853 mPersistentStartingProcesses.add(app);
7854 restart = true;
7855 }
7856 }
7857 mProcessesOnHold.remove(app);
7858
The Android Open Source Project4df24232009-03-05 14:34:35 -08007859 if (app == mHomeProcess) {
7860 mHomeProcess = null;
7861 }
7862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 if (restart) {
7864 // We have components that still need to be running in the
7865 // process, so re-launch it.
7866 mProcessNames.put(app.processName, app.info.uid, app);
7867 startProcessLocked(app, "restart", app.processName);
7868 } else if (app.pid > 0 && app.pid != MY_PID) {
7869 // Goodbye!
7870 synchronized (mPidsSelfLocked) {
7871 mPidsSelfLocked.remove(app.pid);
7872 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7873 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007874 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007875 }
7876 }
7877
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007878 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7879 // Look through the content providers we are waiting to have launched,
7880 // and if any run in this process then either schedule a restart of
7881 // the process or kill the client waiting for it if this process has
7882 // gone bad.
7883 int NL = mLaunchingProviders.size();
7884 boolean restart = false;
7885 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007886 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007887 if (cpr.launchingApp == app) {
7888 if (!alwaysBad && !app.bad) {
7889 restart = true;
7890 } else {
7891 removeDyingProviderLocked(app, cpr);
7892 NL = mLaunchingProviders.size();
7893 }
7894 }
7895 }
7896 return restart;
7897 }
7898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 // =========================================================
7900 // SERVICES
7901 // =========================================================
7902
7903 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7904 ActivityManager.RunningServiceInfo info =
7905 new ActivityManager.RunningServiceInfo();
7906 info.service = r.name;
7907 if (r.app != null) {
7908 info.pid = r.app.pid;
7909 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007910 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 info.process = r.processName;
7912 info.foreground = r.isForeground;
7913 info.activeSince = r.createTime;
7914 info.started = r.startRequested;
7915 info.clientCount = r.connections.size();
7916 info.crashCount = r.crashCount;
7917 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007918 if (r.isForeground) {
7919 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7920 }
7921 if (r.startRequested) {
7922 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7923 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007924 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007925 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7926 }
7927 if (r.app != null && r.app.persistent) {
7928 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7929 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007930 for (ConnectionRecord conn : r.connections.values()) {
7931 if (conn.clientLabel != 0) {
7932 info.clientPackage = conn.binding.client.info.packageName;
7933 info.clientLabel = conn.clientLabel;
7934 break;
7935 }
7936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 return info;
7938 }
7939
7940 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7941 int flags) {
7942 synchronized (this) {
7943 ArrayList<ActivityManager.RunningServiceInfo> res
7944 = new ArrayList<ActivityManager.RunningServiceInfo>();
7945
7946 if (mServices.size() > 0) {
7947 Iterator<ServiceRecord> it = mServices.values().iterator();
7948 while (it.hasNext() && res.size() < maxNum) {
7949 res.add(makeRunningServiceInfoLocked(it.next()));
7950 }
7951 }
7952
7953 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7954 ServiceRecord r = mRestartingServices.get(i);
7955 ActivityManager.RunningServiceInfo info =
7956 makeRunningServiceInfoLocked(r);
7957 info.restarting = r.nextRestartTime;
7958 res.add(info);
7959 }
7960
7961 return res;
7962 }
7963 }
7964
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007965 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
7966 synchronized (this) {
7967 ServiceRecord r = mServices.get(name);
7968 if (r != null) {
7969 for (ConnectionRecord conn : r.connections.values()) {
7970 if (conn.clientIntent != null) {
7971 return conn.clientIntent;
7972 }
7973 }
7974 }
7975 }
7976 return null;
7977 }
7978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007979 private final ServiceRecord findServiceLocked(ComponentName name,
7980 IBinder token) {
7981 ServiceRecord r = mServices.get(name);
7982 return r == token ? r : null;
7983 }
7984
7985 private final class ServiceLookupResult {
7986 final ServiceRecord record;
7987 final String permission;
7988
7989 ServiceLookupResult(ServiceRecord _record, String _permission) {
7990 record = _record;
7991 permission = _permission;
7992 }
7993 };
7994
7995 private ServiceLookupResult findServiceLocked(Intent service,
7996 String resolvedType) {
7997 ServiceRecord r = null;
7998 if (service.getComponent() != null) {
7999 r = mServices.get(service.getComponent());
8000 }
8001 if (r == null) {
8002 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8003 r = mServicesByIntent.get(filter);
8004 }
8005
8006 if (r == null) {
8007 try {
8008 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008009 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 service, resolvedType, 0);
8011 ServiceInfo sInfo =
8012 rInfo != null ? rInfo.serviceInfo : null;
8013 if (sInfo == null) {
8014 return null;
8015 }
8016
8017 ComponentName name = new ComponentName(
8018 sInfo.applicationInfo.packageName, sInfo.name);
8019 r = mServices.get(name);
8020 } catch (RemoteException ex) {
8021 // pm is in same process, this will never happen.
8022 }
8023 }
8024 if (r != null) {
8025 int callingPid = Binder.getCallingPid();
8026 int callingUid = Binder.getCallingUid();
8027 if (checkComponentPermission(r.permission,
8028 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8029 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008030 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008031 + " from pid=" + callingPid
8032 + ", uid=" + callingUid
8033 + " requires " + r.permission);
8034 return new ServiceLookupResult(null, r.permission);
8035 }
8036 return new ServiceLookupResult(r, null);
8037 }
8038 return null;
8039 }
8040
8041 private class ServiceRestarter implements Runnable {
8042 private ServiceRecord mService;
8043
8044 void setService(ServiceRecord service) {
8045 mService = service;
8046 }
8047
8048 public void run() {
8049 synchronized(ActivityManagerService.this) {
8050 performServiceRestartLocked(mService);
8051 }
8052 }
8053 }
8054
8055 private ServiceLookupResult retrieveServiceLocked(Intent service,
8056 String resolvedType, int callingPid, int callingUid) {
8057 ServiceRecord r = null;
8058 if (service.getComponent() != null) {
8059 r = mServices.get(service.getComponent());
8060 }
8061 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8062 r = mServicesByIntent.get(filter);
8063 if (r == null) {
8064 try {
8065 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008066 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008067 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 ServiceInfo sInfo =
8069 rInfo != null ? rInfo.serviceInfo : null;
8070 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008071 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 ": not found");
8073 return null;
8074 }
8075
8076 ComponentName name = new ComponentName(
8077 sInfo.applicationInfo.packageName, sInfo.name);
8078 r = mServices.get(name);
8079 if (r == null) {
8080 filter = new Intent.FilterComparison(service.cloneFilter());
8081 ServiceRestarter res = new ServiceRestarter();
8082 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8083 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8084 synchronized (stats) {
8085 ss = stats.getServiceStatsLocked(
8086 sInfo.applicationInfo.uid, sInfo.packageName,
8087 sInfo.name);
8088 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008089 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008090 res.setService(r);
8091 mServices.put(name, r);
8092 mServicesByIntent.put(filter, r);
8093
8094 // Make sure this component isn't in the pending list.
8095 int N = mPendingServices.size();
8096 for (int i=0; i<N; i++) {
8097 ServiceRecord pr = mPendingServices.get(i);
8098 if (pr.name.equals(name)) {
8099 mPendingServices.remove(i);
8100 i--;
8101 N--;
8102 }
8103 }
8104 }
8105 } catch (RemoteException ex) {
8106 // pm is in same process, this will never happen.
8107 }
8108 }
8109 if (r != null) {
8110 if (checkComponentPermission(r.permission,
8111 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8112 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008113 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 + " from pid=" + Binder.getCallingPid()
8115 + ", uid=" + Binder.getCallingUid()
8116 + " requires " + r.permission);
8117 return new ServiceLookupResult(null, r.permission);
8118 }
8119 return new ServiceLookupResult(r, null);
8120 }
8121 return null;
8122 }
8123
8124 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8125 long now = SystemClock.uptimeMillis();
8126 if (r.executeNesting == 0 && r.app != null) {
8127 if (r.app.executingServices.size() == 0) {
8128 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8129 msg.obj = r.app;
8130 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8131 }
8132 r.app.executingServices.add(r);
8133 }
8134 r.executeNesting++;
8135 r.executingStart = now;
8136 }
8137
8138 private final void sendServiceArgsLocked(ServiceRecord r,
8139 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008140 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 if (N == 0) {
8142 return;
8143 }
8144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 int i = 0;
8146 while (i < N) {
8147 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008148 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008149 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008150 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008151 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008152 // If somehow we got a dummy start at the front, then
8153 // just drop it here.
8154 i++;
8155 continue;
8156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008157 bumpServiceExecutingLocked(r);
8158 if (!oomAdjusted) {
8159 oomAdjusted = true;
8160 updateOomAdjLocked(r.app);
8161 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008162 int flags = 0;
8163 if (si.deliveryCount > 0) {
8164 flags |= Service.START_FLAG_RETRY;
8165 }
8166 if (si.doneExecutingCount > 0) {
8167 flags |= Service.START_FLAG_REDELIVERY;
8168 }
8169 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8170 si.deliveredTime = SystemClock.uptimeMillis();
8171 r.deliveredStarts.add(si);
8172 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008174 } catch (RemoteException e) {
8175 // Remote process gone... we'll let the normal cleanup take
8176 // care of this.
8177 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008179 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 break;
8181 }
8182 }
8183 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008184 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 } else {
8186 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008188 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 }
8190 }
8191 }
8192
8193 private final boolean requestServiceBindingLocked(ServiceRecord r,
8194 IntentBindRecord i, boolean rebind) {
8195 if (r.app == null || r.app.thread == null) {
8196 // If service is not currently running, can't yet bind.
8197 return false;
8198 }
8199 if ((!i.requested || rebind) && i.apps.size() > 0) {
8200 try {
8201 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008202 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008203 + ": shouldUnbind=" + i.hasBound);
8204 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8205 if (!rebind) {
8206 i.requested = true;
8207 }
8208 i.hasBound = true;
8209 i.doRebind = false;
8210 } catch (RemoteException e) {
8211 return false;
8212 }
8213 }
8214 return true;
8215 }
8216
8217 private final void requestServiceBindingsLocked(ServiceRecord r) {
8218 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8219 while (bindings.hasNext()) {
8220 IntentBindRecord i = bindings.next();
8221 if (!requestServiceBindingLocked(r, i, false)) {
8222 break;
8223 }
8224 }
8225 }
8226
8227 private final void realStartServiceLocked(ServiceRecord r,
8228 ProcessRecord app) throws RemoteException {
8229 if (app.thread == null) {
8230 throw new RemoteException();
8231 }
8232
8233 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008234 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235
8236 app.services.add(r);
8237 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008238 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008239
8240 boolean created = false;
8241 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008242 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008243 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008244 mStringBuilder.setLength(0);
8245 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008246 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008248 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 synchronized (r.stats.getBatteryStats()) {
8250 r.stats.startLaunchedLocked();
8251 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008252 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008253 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008254 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008255 created = true;
8256 } finally {
8257 if (!created) {
8258 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008259 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 }
8261 }
8262
8263 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008264
8265 // If the service is in the started state, and there are no
8266 // pending arguments, then fake up one so its onStartCommand() will
8267 // be called.
8268 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8269 r.lastStartId++;
8270 if (r.lastStartId < 1) {
8271 r.lastStartId = 1;
8272 }
8273 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8274 }
8275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008276 sendServiceArgsLocked(r, true);
8277 }
8278
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008279 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8280 boolean allowCancel) {
8281 boolean canceled = false;
8282
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008283 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008284 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008285 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008286
8287 // Any delivered but not yet finished starts should be put back
8288 // on the pending list.
8289 final int N = r.deliveredStarts.size();
8290 if (N > 0) {
8291 for (int i=N-1; i>=0; i--) {
8292 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8293 if (si.intent == null) {
8294 // We'll generate this again if needed.
8295 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8296 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8297 r.pendingStarts.add(0, si);
8298 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8299 dur *= 2;
8300 if (minDuration < dur) minDuration = dur;
8301 if (resetTime < dur) resetTime = dur;
8302 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008303 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008304 + r.name);
8305 canceled = true;
8306 }
8307 }
8308 r.deliveredStarts.clear();
8309 }
8310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 r.totalRestartCount++;
8312 if (r.restartDelay == 0) {
8313 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008314 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008315 } else {
8316 // If it has been a "reasonably long time" since the service
8317 // was started, then reset our restart duration back to
8318 // the beginning, so we don't infinitely increase the duration
8319 // on a service that just occasionally gets killed (which is
8320 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008321 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008323 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008325 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008326 if (r.restartDelay < minDuration) {
8327 r.restartDelay = minDuration;
8328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 }
8330 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008331
8332 r.nextRestartTime = now + r.restartDelay;
8333
8334 // Make sure that we don't end up restarting a bunch of services
8335 // all at the same time.
8336 boolean repeat;
8337 do {
8338 repeat = false;
8339 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8340 ServiceRecord r2 = mRestartingServices.get(i);
8341 if (r2 != r && r.nextRestartTime
8342 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8343 && r.nextRestartTime
8344 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8345 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8346 r.restartDelay = r.nextRestartTime - now;
8347 repeat = true;
8348 break;
8349 }
8350 }
8351 } while (repeat);
8352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008353 if (!mRestartingServices.contains(r)) {
8354 mRestartingServices.add(r);
8355 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008356
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008357 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008360 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008362 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008363 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008364 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 r.shortName, r.restartDelay);
8366
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008367 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 }
8369
8370 final void performServiceRestartLocked(ServiceRecord r) {
8371 if (!mRestartingServices.contains(r)) {
8372 return;
8373 }
8374 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8375 }
8376
8377 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8378 if (r.restartDelay == 0) {
8379 return false;
8380 }
8381 r.resetRestartCounter();
8382 mRestartingServices.remove(r);
8383 mHandler.removeCallbacks(r.restarter);
8384 return true;
8385 }
8386
8387 private final boolean bringUpServiceLocked(ServiceRecord r,
8388 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008389 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 //r.dump(" ");
8391
Dianne Hackborn36124872009-10-08 16:22:03 -07008392 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 sendServiceArgsLocked(r, false);
8394 return true;
8395 }
8396
8397 if (!whileRestarting && r.restartDelay > 0) {
8398 // If waiting for a restart, then do nothing.
8399 return true;
8400 }
8401
Joe Onorato8a9b2202010-02-26 18:56:32 -08008402 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008403 + " " + r.intent);
8404
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008405 // We are now bringing the service up, so no longer in the
8406 // restarting state.
8407 mRestartingServices.remove(r);
8408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008409 final String appName = r.processName;
8410 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8411 if (app != null && app.thread != null) {
8412 try {
8413 realStartServiceLocked(r, app);
8414 return true;
8415 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008416 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008417 }
8418
8419 // If a dead object exception was thrown -- fall through to
8420 // restart the application.
8421 }
8422
Dianne Hackborn36124872009-10-08 16:22:03 -07008423 // Not running -- get it started, and enqueue this service record
8424 // to be executed when the app comes up.
8425 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8426 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008427 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008428 + r.appInfo.packageName + "/"
8429 + r.appInfo.uid + " for service "
8430 + r.intent.getIntent() + ": process is bad");
8431 bringDownServiceLocked(r, true);
8432 return false;
8433 }
8434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 mPendingServices.add(r);
8437 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 return true;
8440 }
8441
8442 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008443 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008444 //r.dump(" ");
8445
8446 // Does it still need to run?
8447 if (!force && r.startRequested) {
8448 return;
8449 }
8450 if (r.connections.size() > 0) {
8451 if (!force) {
8452 // XXX should probably keep a count of the number of auto-create
8453 // connections directly in the service.
8454 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8455 while (it.hasNext()) {
8456 ConnectionRecord cr = it.next();
8457 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8458 return;
8459 }
8460 }
8461 }
8462
8463 // Report to all of the connections that the service is no longer
8464 // available.
8465 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8466 while (it.hasNext()) {
8467 ConnectionRecord c = it.next();
8468 try {
8469 // todo: shouldn't be a synchronous call!
8470 c.conn.connected(r.name, null);
8471 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008472 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008473 " to connection " + c.conn.asBinder() +
8474 " (in " + c.binding.client.processName + ")", e);
8475 }
8476 }
8477 }
8478
8479 // Tell the service that it has been unbound.
8480 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8481 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8482 while (it.hasNext()) {
8483 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008484 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485 + ": hasBound=" + ibr.hasBound);
8486 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8487 try {
8488 bumpServiceExecutingLocked(r);
8489 updateOomAdjLocked(r.app);
8490 ibr.hasBound = false;
8491 r.app.thread.scheduleUnbindService(r,
8492 ibr.intent.getIntent());
8493 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008494 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 + r.shortName, e);
8496 serviceDoneExecutingLocked(r, true);
8497 }
8498 }
8499 }
8500 }
8501
Joe Onorato8a9b2202010-02-26 18:56:32 -08008502 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008503 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008504 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 System.identityHashCode(r), r.shortName,
8506 (r.app != null) ? r.app.pid : -1);
8507
8508 mServices.remove(r.name);
8509 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008510 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008511 r.totalRestartCount = 0;
8512 unscheduleServiceRestartLocked(r);
8513
8514 // Also make sure it is not on the pending list.
8515 int N = mPendingServices.size();
8516 for (int i=0; i<N; i++) {
8517 if (mPendingServices.get(i) == r) {
8518 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008519 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 TAG, "Removed pending service: " + r.shortName);
8521 i--;
8522 N--;
8523 }
8524 }
8525
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008526 r.cancelNotification();
8527 r.isForeground = false;
8528 r.foregroundId = 0;
8529 r.foregroundNoti = null;
8530
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008531 // Clear start entries.
8532 r.deliveredStarts.clear();
8533 r.pendingStarts.clear();
8534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535 if (r.app != null) {
8536 synchronized (r.stats.getBatteryStats()) {
8537 r.stats.stopLaunchedLocked();
8538 }
8539 r.app.services.remove(r);
8540 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008541 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008542 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008543 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 bumpServiceExecutingLocked(r);
8545 mStoppingServices.add(r);
8546 updateOomAdjLocked(r.app);
8547 r.app.thread.scheduleStopService(r);
8548 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008549 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 + r.shortName, e);
8551 serviceDoneExecutingLocked(r, true);
8552 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008553 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008555 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 TAG, "Removed service that has no process: " + r.shortName);
8557 }
8558 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008559 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008560 TAG, "Removed service that is not running: " + r.shortName);
8561 }
8562 }
8563
8564 ComponentName startServiceLocked(IApplicationThread caller,
8565 Intent service, String resolvedType,
8566 int callingPid, int callingUid) {
8567 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008568 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 + " type=" + resolvedType + " args=" + service.getExtras());
8570
8571 if (caller != null) {
8572 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8573 if (callerApp == null) {
8574 throw new SecurityException(
8575 "Unable to find app for caller " + caller
8576 + " (pid=" + Binder.getCallingPid()
8577 + ") when starting service " + service);
8578 }
8579 }
8580
8581 ServiceLookupResult res =
8582 retrieveServiceLocked(service, resolvedType,
8583 callingPid, callingUid);
8584 if (res == null) {
8585 return null;
8586 }
8587 if (res.record == null) {
8588 return new ComponentName("!", res.permission != null
8589 ? res.permission : "private to package");
8590 }
8591 ServiceRecord r = res.record;
8592 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008593 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 + r.shortName);
8595 }
8596 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008597 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008598 r.lastStartId++;
8599 if (r.lastStartId < 1) {
8600 r.lastStartId = 1;
8601 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008602 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 r.lastActivity = SystemClock.uptimeMillis();
8604 synchronized (r.stats.getBatteryStats()) {
8605 r.stats.startRunningLocked();
8606 }
8607 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8608 return new ComponentName("!", "Service process is bad");
8609 }
8610 return r.name;
8611 }
8612 }
8613
8614 public ComponentName startService(IApplicationThread caller, Intent service,
8615 String resolvedType) {
8616 // Refuse possible leaked file descriptors
8617 if (service != null && service.hasFileDescriptors() == true) {
8618 throw new IllegalArgumentException("File descriptors passed in Intent");
8619 }
8620
8621 synchronized(this) {
8622 final int callingPid = Binder.getCallingPid();
8623 final int callingUid = Binder.getCallingUid();
8624 final long origId = Binder.clearCallingIdentity();
8625 ComponentName res = startServiceLocked(caller, service,
8626 resolvedType, callingPid, callingUid);
8627 Binder.restoreCallingIdentity(origId);
8628 return res;
8629 }
8630 }
8631
8632 ComponentName startServiceInPackage(int uid,
8633 Intent service, String resolvedType) {
8634 synchronized(this) {
8635 final long origId = Binder.clearCallingIdentity();
8636 ComponentName res = startServiceLocked(null, service,
8637 resolvedType, -1, uid);
8638 Binder.restoreCallingIdentity(origId);
8639 return res;
8640 }
8641 }
8642
8643 public int stopService(IApplicationThread caller, Intent service,
8644 String resolvedType) {
8645 // Refuse possible leaked file descriptors
8646 if (service != null && service.hasFileDescriptors() == true) {
8647 throw new IllegalArgumentException("File descriptors passed in Intent");
8648 }
8649
8650 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008651 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 + " type=" + resolvedType);
8653
8654 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8655 if (caller != null && callerApp == null) {
8656 throw new SecurityException(
8657 "Unable to find app for caller " + caller
8658 + " (pid=" + Binder.getCallingPid()
8659 + ") when stopping service " + service);
8660 }
8661
8662 // If this service is active, make sure it is stopped.
8663 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8664 if (r != null) {
8665 if (r.record != null) {
8666 synchronized (r.record.stats.getBatteryStats()) {
8667 r.record.stats.stopRunningLocked();
8668 }
8669 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008670 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 final long origId = Binder.clearCallingIdentity();
8672 bringDownServiceLocked(r.record, false);
8673 Binder.restoreCallingIdentity(origId);
8674 return 1;
8675 }
8676 return -1;
8677 }
8678 }
8679
8680 return 0;
8681 }
8682
8683 public IBinder peekService(Intent service, String resolvedType) {
8684 // Refuse possible leaked file descriptors
8685 if (service != null && service.hasFileDescriptors() == true) {
8686 throw new IllegalArgumentException("File descriptors passed in Intent");
8687 }
8688
8689 IBinder ret = null;
8690
8691 synchronized(this) {
8692 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8693
8694 if (r != null) {
8695 // r.record is null if findServiceLocked() failed the caller permission check
8696 if (r.record == null) {
8697 throw new SecurityException(
8698 "Permission Denial: Accessing service " + r.record.name
8699 + " from pid=" + Binder.getCallingPid()
8700 + ", uid=" + Binder.getCallingUid()
8701 + " requires " + r.permission);
8702 }
8703 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8704 if (ib != null) {
8705 ret = ib.binder;
8706 }
8707 }
8708 }
8709
8710 return ret;
8711 }
8712
8713 public boolean stopServiceToken(ComponentName className, IBinder token,
8714 int startId) {
8715 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008716 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 + " " + token + " startId=" + startId);
8718 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008719 if (r != null) {
8720 if (startId >= 0) {
8721 // Asked to only stop if done with all work. Note that
8722 // to avoid leaks, we will take this as dropping all
8723 // start items up to and including this one.
8724 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8725 if (si != null) {
8726 while (r.deliveredStarts.size() > 0) {
8727 if (r.deliveredStarts.remove(0) == si) {
8728 break;
8729 }
8730 }
8731 }
8732
8733 if (r.lastStartId != startId) {
8734 return false;
8735 }
8736
8737 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008738 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008739 + " is last, but have " + r.deliveredStarts.size()
8740 + " remaining args");
8741 }
8742 }
8743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008744 synchronized (r.stats.getBatteryStats()) {
8745 r.stats.stopRunningLocked();
8746 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008747 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748 }
8749 final long origId = Binder.clearCallingIdentity();
8750 bringDownServiceLocked(r, false);
8751 Binder.restoreCallingIdentity(origId);
8752 return true;
8753 }
8754 }
8755 return false;
8756 }
8757
8758 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008759 int id, Notification notification, boolean removeNotification) {
8760 final long origId = Binder.clearCallingIdentity();
8761 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 synchronized(this) {
8763 ServiceRecord r = findServiceLocked(className, token);
8764 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008765 if (id != 0) {
8766 if (notification == null) {
8767 throw new IllegalArgumentException("null notification");
8768 }
8769 if (r.foregroundId != id) {
8770 r.cancelNotification();
8771 r.foregroundId = id;
8772 }
8773 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8774 r.foregroundNoti = notification;
8775 r.isForeground = true;
8776 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 if (r.app != null) {
8778 updateServiceForegroundLocked(r.app, true);
8779 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008780 } else {
8781 if (r.isForeground) {
8782 r.isForeground = false;
8783 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008784 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008785 updateServiceForegroundLocked(r.app, true);
8786 }
8787 }
8788 if (removeNotification) {
8789 r.cancelNotification();
8790 r.foregroundId = 0;
8791 r.foregroundNoti = null;
8792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 }
8794 }
8795 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008796 } finally {
8797 Binder.restoreCallingIdentity(origId);
8798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 }
8800
8801 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8802 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008803 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 if (sr.isForeground) {
8805 anyForeground = true;
8806 break;
8807 }
8808 }
8809 if (anyForeground != proc.foregroundServices) {
8810 proc.foregroundServices = anyForeground;
8811 if (oomAdj) {
8812 updateOomAdjLocked();
8813 }
8814 }
8815 }
8816
8817 public int bindService(IApplicationThread caller, IBinder token,
8818 Intent service, String resolvedType,
8819 IServiceConnection connection, int flags) {
8820 // Refuse possible leaked file descriptors
8821 if (service != null && service.hasFileDescriptors() == true) {
8822 throw new IllegalArgumentException("File descriptors passed in Intent");
8823 }
8824
8825 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008826 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008827 + " type=" + resolvedType + " conn=" + connection.asBinder()
8828 + " flags=0x" + Integer.toHexString(flags));
8829 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8830 if (callerApp == null) {
8831 throw new SecurityException(
8832 "Unable to find app for caller " + caller
8833 + " (pid=" + Binder.getCallingPid()
8834 + ") when binding service " + service);
8835 }
8836
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008837 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008839 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008841 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008842 return 0;
8843 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008844 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 }
8846
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008847 int clientLabel = 0;
8848 PendingIntent clientIntent = null;
8849
8850 if (callerApp.info.uid == Process.SYSTEM_UID) {
8851 // Hacky kind of thing -- allow system stuff to tell us
8852 // what they are, so we can report this elsewhere for
8853 // others to know why certain services are running.
8854 try {
8855 clientIntent = (PendingIntent)service.getParcelableExtra(
8856 Intent.EXTRA_CLIENT_INTENT);
8857 } catch (RuntimeException e) {
8858 }
8859 if (clientIntent != null) {
8860 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8861 if (clientLabel != 0) {
8862 // There are no useful extras in the intent, trash them.
8863 // System code calling with this stuff just needs to know
8864 // this will happen.
8865 service = service.cloneFilter();
8866 }
8867 }
8868 }
8869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 ServiceLookupResult res =
8871 retrieveServiceLocked(service, resolvedType,
8872 Binder.getCallingPid(), Binder.getCallingUid());
8873 if (res == null) {
8874 return 0;
8875 }
8876 if (res.record == null) {
8877 return -1;
8878 }
8879 ServiceRecord s = res.record;
8880
8881 final long origId = Binder.clearCallingIdentity();
8882
8883 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008884 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 + s.shortName);
8886 }
8887
8888 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8889 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008890 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008891
8892 IBinder binder = connection.asBinder();
8893 s.connections.put(binder, c);
8894 b.connections.add(c);
8895 if (activity != null) {
8896 if (activity.connections == null) {
8897 activity.connections = new HashSet<ConnectionRecord>();
8898 }
8899 activity.connections.add(c);
8900 }
8901 b.client.connections.add(c);
8902 mServiceConnections.put(binder, c);
8903
8904 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8905 s.lastActivity = SystemClock.uptimeMillis();
8906 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8907 return 0;
8908 }
8909 }
8910
8911 if (s.app != null) {
8912 // This could have made the service more important.
8913 updateOomAdjLocked(s.app);
8914 }
8915
Joe Onorato8a9b2202010-02-26 18:56:32 -08008916 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 + ": received=" + b.intent.received
8918 + " apps=" + b.intent.apps.size()
8919 + " doRebind=" + b.intent.doRebind);
8920
8921 if (s.app != null && b.intent.received) {
8922 // Service is already running, so we can immediately
8923 // publish the connection.
8924 try {
8925 c.conn.connected(s.name, b.intent.binder);
8926 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008927 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 + " to connection " + c.conn.asBinder()
8929 + " (in " + c.binding.client.processName + ")", e);
8930 }
8931
8932 // If this is the first app connected back to this binding,
8933 // and the service had previously asked to be told when
8934 // rebound, then do so.
8935 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8936 requestServiceBindingLocked(s, b.intent, true);
8937 }
8938 } else if (!b.intent.requested) {
8939 requestServiceBindingLocked(s, b.intent, false);
8940 }
8941
8942 Binder.restoreCallingIdentity(origId);
8943 }
8944
8945 return 1;
8946 }
8947
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008948 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008949 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 IBinder binder = c.conn.asBinder();
8951 AppBindRecord b = c.binding;
8952 ServiceRecord s = b.service;
8953 s.connections.remove(binder);
8954 b.connections.remove(c);
8955 if (c.activity != null && c.activity != skipAct) {
8956 if (c.activity.connections != null) {
8957 c.activity.connections.remove(c);
8958 }
8959 }
8960 if (b.client != skipApp) {
8961 b.client.connections.remove(c);
8962 }
8963 mServiceConnections.remove(binder);
8964
8965 if (b.connections.size() == 0) {
8966 b.intent.apps.remove(b.client);
8967 }
8968
Joe Onorato8a9b2202010-02-26 18:56:32 -08008969 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 + ": shouldUnbind=" + b.intent.hasBound);
8971 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
8972 && b.intent.hasBound) {
8973 try {
8974 bumpServiceExecutingLocked(s);
8975 updateOomAdjLocked(s.app);
8976 b.intent.hasBound = false;
8977 // Assume the client doesn't want to know about a rebind;
8978 // we will deal with that later if it asks for one.
8979 b.intent.doRebind = false;
8980 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
8981 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008982 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 serviceDoneExecutingLocked(s, true);
8984 }
8985 }
8986
8987 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
8988 bringDownServiceLocked(s, false);
8989 }
8990 }
8991
8992 public boolean unbindService(IServiceConnection connection) {
8993 synchronized (this) {
8994 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008995 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 ConnectionRecord r = mServiceConnections.get(binder);
8997 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008998 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008999 + connection.asBinder());
9000 return false;
9001 }
9002
9003 final long origId = Binder.clearCallingIdentity();
9004
9005 removeConnectionLocked(r, null, null);
9006
9007 if (r.binding.service.app != null) {
9008 // This could have made the service less important.
9009 updateOomAdjLocked(r.binding.service.app);
9010 }
9011
9012 Binder.restoreCallingIdentity(origId);
9013 }
9014
9015 return true;
9016 }
9017
9018 public void publishService(IBinder token, Intent intent, IBinder service) {
9019 // Refuse possible leaked file descriptors
9020 if (intent != null && intent.hasFileDescriptors() == true) {
9021 throw new IllegalArgumentException("File descriptors passed in Intent");
9022 }
9023
9024 synchronized(this) {
9025 if (!(token instanceof ServiceRecord)) {
9026 throw new IllegalArgumentException("Invalid service token");
9027 }
9028 ServiceRecord r = (ServiceRecord)token;
9029
9030 final long origId = Binder.clearCallingIdentity();
9031
Joe Onorato8a9b2202010-02-26 18:56:32 -08009032 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 + " " + intent + ": " + service);
9034 if (r != null) {
9035 Intent.FilterComparison filter
9036 = new Intent.FilterComparison(intent);
9037 IntentBindRecord b = r.bindings.get(filter);
9038 if (b != null && !b.received) {
9039 b.binder = service;
9040 b.requested = true;
9041 b.received = true;
9042 if (r.connections.size() > 0) {
9043 Iterator<ConnectionRecord> it
9044 = r.connections.values().iterator();
9045 while (it.hasNext()) {
9046 ConnectionRecord c = it.next();
9047 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009048 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009050 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009052 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 TAG, "Published intent: " + intent);
9054 continue;
9055 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009056 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 try {
9058 c.conn.connected(r.name, service);
9059 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009060 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 " to connection " + c.conn.asBinder() +
9062 " (in " + c.binding.client.processName + ")", e);
9063 }
9064 }
9065 }
9066 }
9067
9068 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9069
9070 Binder.restoreCallingIdentity(origId);
9071 }
9072 }
9073 }
9074
9075 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9076 // Refuse possible leaked file descriptors
9077 if (intent != null && intent.hasFileDescriptors() == true) {
9078 throw new IllegalArgumentException("File descriptors passed in Intent");
9079 }
9080
9081 synchronized(this) {
9082 if (!(token instanceof ServiceRecord)) {
9083 throw new IllegalArgumentException("Invalid service token");
9084 }
9085 ServiceRecord r = (ServiceRecord)token;
9086
9087 final long origId = Binder.clearCallingIdentity();
9088
9089 if (r != null) {
9090 Intent.FilterComparison filter
9091 = new Intent.FilterComparison(intent);
9092 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009093 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 + " at " + b + ": apps="
9095 + (b != null ? b.apps.size() : 0));
9096 if (b != null) {
9097 if (b.apps.size() > 0) {
9098 // Applications have already bound since the last
9099 // unbind, so just rebind right here.
9100 requestServiceBindingLocked(r, b, true);
9101 } else {
9102 // Note to tell the service the next time there is
9103 // a new client.
9104 b.doRebind = true;
9105 }
9106 }
9107
9108 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9109
9110 Binder.restoreCallingIdentity(origId);
9111 }
9112 }
9113 }
9114
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009115 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 synchronized(this) {
9117 if (!(token instanceof ServiceRecord)) {
9118 throw new IllegalArgumentException("Invalid service token");
9119 }
9120 ServiceRecord r = (ServiceRecord)token;
9121 boolean inStopping = mStoppingServices.contains(token);
9122 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009123 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 + ": nesting=" + r.executeNesting
9125 + ", inStopping=" + inStopping);
9126 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009127 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009128 + " with incorrect token: given " + token
9129 + ", expected " + r);
9130 return;
9131 }
9132
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009133 if (type == 1) {
9134 // This is a call from a service start... take care of
9135 // book-keeping.
9136 r.callStart = true;
9137 switch (res) {
9138 case Service.START_STICKY_COMPATIBILITY:
9139 case Service.START_STICKY: {
9140 // We are done with the associated start arguments.
9141 r.findDeliveredStart(startId, true);
9142 // Don't stop if killed.
9143 r.stopIfKilled = false;
9144 break;
9145 }
9146 case Service.START_NOT_STICKY: {
9147 // We are done with the associated start arguments.
9148 r.findDeliveredStart(startId, true);
9149 if (r.lastStartId == startId) {
9150 // There is no more work, and this service
9151 // doesn't want to hang around if killed.
9152 r.stopIfKilled = true;
9153 }
9154 break;
9155 }
9156 case Service.START_REDELIVER_INTENT: {
9157 // We'll keep this item until they explicitly
9158 // call stop for it, but keep track of the fact
9159 // that it was delivered.
9160 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9161 if (si != null) {
9162 si.deliveryCount = 0;
9163 si.doneExecutingCount++;
9164 // Don't stop if killed.
9165 r.stopIfKilled = true;
9166 }
9167 break;
9168 }
9169 default:
9170 throw new IllegalArgumentException(
9171 "Unknown service start result: " + res);
9172 }
9173 if (res == Service.START_STICKY_COMPATIBILITY) {
9174 r.callStart = false;
9175 }
9176 }
9177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 final long origId = Binder.clearCallingIdentity();
9179 serviceDoneExecutingLocked(r, inStopping);
9180 Binder.restoreCallingIdentity(origId);
9181 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009182 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 + " with token " + token);
9184 }
9185 }
9186 }
9187
9188 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9189 r.executeNesting--;
9190 if (r.executeNesting <= 0 && r.app != null) {
9191 r.app.executingServices.remove(r);
9192 if (r.app.executingServices.size() == 0) {
9193 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9194 }
9195 if (inStopping) {
9196 mStoppingServices.remove(r);
9197 }
9198 updateOomAdjLocked(r.app);
9199 }
9200 }
9201
9202 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009203 String anrMessage = null;
9204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009205 synchronized(this) {
9206 if (proc.executingServices.size() == 0 || proc.thread == null) {
9207 return;
9208 }
9209 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9210 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9211 ServiceRecord timeout = null;
9212 long nextTime = 0;
9213 while (it.hasNext()) {
9214 ServiceRecord sr = it.next();
9215 if (sr.executingStart < maxTime) {
9216 timeout = sr;
9217 break;
9218 }
9219 if (sr.executingStart > nextTime) {
9220 nextTime = sr.executingStart;
9221 }
9222 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009223 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009224 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009225 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 } else {
9227 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9228 msg.obj = proc;
9229 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9230 }
9231 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009232
9233 if (anrMessage != null) {
9234 appNotResponding(proc, null, null, anrMessage);
9235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 }
9237
9238 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009239 // BACKUP AND RESTORE
9240 // =========================================================
9241
9242 // Cause the target app to be launched if necessary and its backup agent
9243 // instantiated. The backup agent will invoke backupAgentCreated() on the
9244 // activity manager to announce its creation.
9245 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009246 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009247 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9248
9249 synchronized(this) {
9250 // !!! TODO: currently no check here that we're already bound
9251 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9252 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9253 synchronized (stats) {
9254 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9255 }
9256
9257 BackupRecord r = new BackupRecord(ss, app, backupMode);
9258 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9259 // startProcessLocked() returns existing proc's record if it's already running
9260 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009261 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009262 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009263 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009264 return false;
9265 }
9266
9267 r.app = proc;
9268 mBackupTarget = r;
9269 mBackupAppName = app.packageName;
9270
Christopher Tate6fa95972009-06-05 18:43:55 -07009271 // Try not to kill the process during backup
9272 updateOomAdjLocked(proc);
9273
Christopher Tate181fafa2009-05-14 11:12:14 -07009274 // If the process is already attached, schedule the creation of the backup agent now.
9275 // If it is not yet live, this will be done when it attaches to the framework.
9276 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009277 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009278 try {
9279 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9280 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009281 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009282 }
9283 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009284 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009285 }
9286 // Invariants: at this point, the target app process exists and the application
9287 // is either already running or in the process of coming up. mBackupTarget and
9288 // mBackupAppName describe the app, so that when it binds back to the AM we
9289 // know that it's scheduled for a backup-agent operation.
9290 }
9291
9292 return true;
9293 }
9294
9295 // A backup agent has just come up
9296 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009297 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009298 + " = " + agent);
9299
9300 synchronized(this) {
9301 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009302 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009303 return;
9304 }
9305
Christopher Tate043dadc2009-06-02 16:11:00 -07009306 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009307 try {
9308 IBackupManager bm = IBackupManager.Stub.asInterface(
9309 ServiceManager.getService(Context.BACKUP_SERVICE));
9310 bm.agentConnected(agentPackageName, agent);
9311 } catch (RemoteException e) {
9312 // can't happen; the backup manager service is local
9313 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009314 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009315 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009316 } finally {
9317 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009318 }
9319 }
9320 }
9321
9322 // done with this agent
9323 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009324 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009325 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009326 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009327 return;
9328 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009329
9330 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009331 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009332 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009333 return;
9334 }
9335
Christopher Tate181fafa2009-05-14 11:12:14 -07009336 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009337 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009338 return;
9339 }
9340
Christopher Tate6fa95972009-06-05 18:43:55 -07009341 ProcessRecord proc = mBackupTarget.app;
9342 mBackupTarget = null;
9343 mBackupAppName = null;
9344
9345 // Not backing this app up any more; reset its OOM adjustment
9346 updateOomAdjLocked(proc);
9347
Christopher Tatec7b31e32009-06-10 15:49:30 -07009348 // If the app crashed during backup, 'thread' will be null here
9349 if (proc.thread != null) {
9350 try {
9351 proc.thread.scheduleDestroyBackupAgent(appInfo);
9352 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009353 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009354 e.printStackTrace();
9355 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009356 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009357 }
9358 }
9359 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 // BROADCASTS
9361 // =========================================================
9362
Josh Bartel7f208742010-02-25 11:01:44 -06009363 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009364 List cur) {
9365 final ContentResolver resolver = mContext.getContentResolver();
9366 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9367 if (list == null) {
9368 return cur;
9369 }
9370 int N = list.size();
9371 for (int i=0; i<N; i++) {
9372 Intent intent = list.get(i);
9373 if (filter.match(resolver, intent, true, TAG) >= 0) {
9374 if (cur == null) {
9375 cur = new ArrayList<Intent>();
9376 }
9377 cur.add(intent);
9378 }
9379 }
9380 return cur;
9381 }
9382
9383 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009384 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 + mBroadcastsScheduled);
9386
9387 if (mBroadcastsScheduled) {
9388 return;
9389 }
9390 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9391 mBroadcastsScheduled = true;
9392 }
9393
9394 public Intent registerReceiver(IApplicationThread caller,
9395 IIntentReceiver receiver, IntentFilter filter, String permission) {
9396 synchronized(this) {
9397 ProcessRecord callerApp = null;
9398 if (caller != null) {
9399 callerApp = getRecordForAppLocked(caller);
9400 if (callerApp == null) {
9401 throw new SecurityException(
9402 "Unable to find app for caller " + caller
9403 + " (pid=" + Binder.getCallingPid()
9404 + ") when registering receiver " + receiver);
9405 }
9406 }
9407
9408 List allSticky = null;
9409
9410 // Look for any matching sticky broadcasts...
9411 Iterator actions = filter.actionsIterator();
9412 if (actions != null) {
9413 while (actions.hasNext()) {
9414 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009415 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 }
9417 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009418 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419 }
9420
9421 // The first sticky in the list is returned directly back to
9422 // the client.
9423 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9424
Joe Onorato8a9b2202010-02-26 18:56:32 -08009425 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426 + ": " + sticky);
9427
9428 if (receiver == null) {
9429 return sticky;
9430 }
9431
9432 ReceiverList rl
9433 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9434 if (rl == null) {
9435 rl = new ReceiverList(this, callerApp,
9436 Binder.getCallingPid(),
9437 Binder.getCallingUid(), receiver);
9438 if (rl.app != null) {
9439 rl.app.receivers.add(rl);
9440 } else {
9441 try {
9442 receiver.asBinder().linkToDeath(rl, 0);
9443 } catch (RemoteException e) {
9444 return sticky;
9445 }
9446 rl.linkedToDeath = true;
9447 }
9448 mRegisteredReceivers.put(receiver.asBinder(), rl);
9449 }
9450 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9451 rl.add(bf);
9452 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009453 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 }
9455 mReceiverResolver.addFilter(bf);
9456
9457 // Enqueue broadcasts for all existing stickies that match
9458 // this filter.
9459 if (allSticky != null) {
9460 ArrayList receivers = new ArrayList();
9461 receivers.add(bf);
9462
9463 int N = allSticky.size();
9464 for (int i=0; i<N; i++) {
9465 Intent intent = (Intent)allSticky.get(i);
9466 BroadcastRecord r = new BroadcastRecord(intent, null,
9467 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009468 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 if (mParallelBroadcasts.size() == 0) {
9470 scheduleBroadcastsLocked();
9471 }
9472 mParallelBroadcasts.add(r);
9473 }
9474 }
9475
9476 return sticky;
9477 }
9478 }
9479
9480 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009481 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482
9483 boolean doNext = false;
9484
9485 synchronized(this) {
9486 ReceiverList rl
9487 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9488 if (rl != null) {
9489 if (rl.curBroadcast != null) {
9490 BroadcastRecord r = rl.curBroadcast;
9491 doNext = finishReceiverLocked(
9492 receiver.asBinder(), r.resultCode, r.resultData,
9493 r.resultExtras, r.resultAbort, true);
9494 }
9495
9496 if (rl.app != null) {
9497 rl.app.receivers.remove(rl);
9498 }
9499 removeReceiverLocked(rl);
9500 if (rl.linkedToDeath) {
9501 rl.linkedToDeath = false;
9502 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9503 }
9504 }
9505 }
9506
9507 if (!doNext) {
9508 return;
9509 }
9510
9511 final long origId = Binder.clearCallingIdentity();
9512 processNextBroadcast(false);
9513 trimApplications();
9514 Binder.restoreCallingIdentity(origId);
9515 }
9516
9517 void removeReceiverLocked(ReceiverList rl) {
9518 mRegisteredReceivers.remove(rl.receiver.asBinder());
9519 int N = rl.size();
9520 for (int i=0; i<N; i++) {
9521 mReceiverResolver.removeFilter(rl.get(i));
9522 }
9523 }
9524
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009525 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9526 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9527 ProcessRecord r = mLruProcesses.get(i);
9528 if (r.thread != null) {
9529 try {
9530 r.thread.dispatchPackageBroadcast(cmd, packages);
9531 } catch (RemoteException ex) {
9532 }
9533 }
9534 }
9535 }
9536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009537 private final int broadcastIntentLocked(ProcessRecord callerApp,
9538 String callerPackage, Intent intent, String resolvedType,
9539 IIntentReceiver resultTo, int resultCode, String resultData,
9540 Bundle map, String requiredPermission,
9541 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9542 intent = new Intent(intent);
9543
Joe Onorato8a9b2202010-02-26 18:56:32 -08009544 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9546 + " ordered=" + ordered);
9547 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009548 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009549 }
9550
9551 // Handle special intents: if this broadcast is from the package
9552 // manager about a package being removed, we need to remove all of
9553 // its activities from the history stack.
9554 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9555 intent.getAction());
9556 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9557 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009558 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 || uidRemoved) {
9560 if (checkComponentPermission(
9561 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9562 callingPid, callingUid, -1)
9563 == PackageManager.PERMISSION_GRANTED) {
9564 if (uidRemoved) {
9565 final Bundle intentExtras = intent.getExtras();
9566 final int uid = intentExtras != null
9567 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9568 if (uid >= 0) {
9569 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9570 synchronized (bs) {
9571 bs.removeUidStatsLocked(uid);
9572 }
9573 }
9574 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009575 // If resources are unvailble just force stop all
9576 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009577 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009578 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9579 if (list != null && (list.length > 0)) {
9580 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009581 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009582 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009583 sendPackageBroadcastLocked(
9584 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009585 }
9586 } else {
9587 Uri data = intent.getData();
9588 String ssp;
9589 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9590 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9591 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009592 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009593 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009594 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9595 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9596 new String[] {ssp});
9597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 }
9599 }
9600 }
9601 } else {
9602 String msg = "Permission Denial: " + intent.getAction()
9603 + " broadcast from " + callerPackage + " (pid=" + callingPid
9604 + ", uid=" + callingUid + ")"
9605 + " requires "
9606 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009607 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 throw new SecurityException(msg);
9609 }
9610 }
9611
9612 /*
9613 * If this is the time zone changed action, queue up a message that will reset the timezone
9614 * of all currently running processes. This message will get queued up before the broadcast
9615 * happens.
9616 */
9617 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9618 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9619 }
9620
Dianne Hackborn854060af2009-07-09 18:14:31 -07009621 /*
9622 * Prevent non-system code (defined here to be non-persistent
9623 * processes) from sending protected broadcasts.
9624 */
9625 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9626 || callingUid == Process.SHELL_UID || callingUid == 0) {
9627 // Always okay.
9628 } else if (callerApp == null || !callerApp.persistent) {
9629 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009630 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009631 intent.getAction())) {
9632 String msg = "Permission Denial: not allowed to send broadcast "
9633 + intent.getAction() + " from pid="
9634 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009635 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009636 throw new SecurityException(msg);
9637 }
9638 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009639 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009640 return BROADCAST_SUCCESS;
9641 }
9642 }
9643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 // Add to the sticky list if requested.
9645 if (sticky) {
9646 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9647 callingPid, callingUid)
9648 != PackageManager.PERMISSION_GRANTED) {
9649 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9650 + callingPid + ", uid=" + callingUid
9651 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009652 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 throw new SecurityException(msg);
9654 }
9655 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009656 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 + " and enforce permission " + requiredPermission);
9658 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9659 }
9660 if (intent.getComponent() != null) {
9661 throw new SecurityException(
9662 "Sticky broadcasts can't target a specific component");
9663 }
9664 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9665 if (list == null) {
9666 list = new ArrayList<Intent>();
9667 mStickyBroadcasts.put(intent.getAction(), list);
9668 }
9669 int N = list.size();
9670 int i;
9671 for (i=0; i<N; i++) {
9672 if (intent.filterEquals(list.get(i))) {
9673 // This sticky already exists, replace it.
9674 list.set(i, new Intent(intent));
9675 break;
9676 }
9677 }
9678 if (i >= N) {
9679 list.add(new Intent(intent));
9680 }
9681 }
9682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 // Figure out who all will receive this broadcast.
9684 List receivers = null;
9685 List<BroadcastFilter> registeredReceivers = null;
9686 try {
9687 if (intent.getComponent() != null) {
9688 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009689 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009690 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 if (ai != null) {
9692 receivers = new ArrayList();
9693 ResolveInfo ri = new ResolveInfo();
9694 ri.activityInfo = ai;
9695 receivers.add(ri);
9696 }
9697 } else {
9698 // Need to resolve the intent to interested receivers...
9699 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9700 == 0) {
9701 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009702 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009703 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 }
Mihai Preda074edef2009-05-18 17:13:31 +02009705 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706 }
9707 } catch (RemoteException ex) {
9708 // pm is in same process, this will never happen.
9709 }
9710
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009711 final boolean replacePending =
9712 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9713
Joe Onorato8a9b2202010-02-26 18:56:32 -08009714 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009715 + " replacePending=" + replacePending);
9716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9718 if (!ordered && NR > 0) {
9719 // If we are not serializing this broadcast, then send the
9720 // registered receivers separately so they don't wait for the
9721 // components to be launched.
9722 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9723 callerPackage, callingPid, callingUid, requiredPermission,
9724 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009725 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009726 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 TAG, "Enqueueing parallel broadcast " + r
9728 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009729 boolean replaced = false;
9730 if (replacePending) {
9731 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9732 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009733 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009734 "***** DROPPING PARALLEL: " + intent);
9735 mParallelBroadcasts.set(i, r);
9736 replaced = true;
9737 break;
9738 }
9739 }
9740 }
9741 if (!replaced) {
9742 mParallelBroadcasts.add(r);
9743 scheduleBroadcastsLocked();
9744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 registeredReceivers = null;
9746 NR = 0;
9747 }
9748
9749 // Merge into one list.
9750 int ir = 0;
9751 if (receivers != null) {
9752 // A special case for PACKAGE_ADDED: do not allow the package
9753 // being added to see this broadcast. This prevents them from
9754 // using this as a back door to get run as soon as they are
9755 // installed. Maybe in the future we want to have a special install
9756 // broadcast or such for apps, but we'd like to deliberately make
9757 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009758 String skipPackages[] = null;
9759 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9760 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9761 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9762 Uri data = intent.getData();
9763 if (data != null) {
9764 String pkgName = data.getSchemeSpecificPart();
9765 if (pkgName != null) {
9766 skipPackages = new String[] { pkgName };
9767 }
9768 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009769 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009770 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009771 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009772 if (skipPackages != null && (skipPackages.length > 0)) {
9773 for (String skipPackage : skipPackages) {
9774 if (skipPackage != null) {
9775 int NT = receivers.size();
9776 for (int it=0; it<NT; it++) {
9777 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9778 if (curt.activityInfo.packageName.equals(skipPackage)) {
9779 receivers.remove(it);
9780 it--;
9781 NT--;
9782 }
9783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 }
9785 }
9786 }
9787
9788 int NT = receivers != null ? receivers.size() : 0;
9789 int it = 0;
9790 ResolveInfo curt = null;
9791 BroadcastFilter curr = null;
9792 while (it < NT && ir < NR) {
9793 if (curt == null) {
9794 curt = (ResolveInfo)receivers.get(it);
9795 }
9796 if (curr == null) {
9797 curr = registeredReceivers.get(ir);
9798 }
9799 if (curr.getPriority() >= curt.priority) {
9800 // Insert this broadcast record into the final list.
9801 receivers.add(it, curr);
9802 ir++;
9803 curr = null;
9804 it++;
9805 NT++;
9806 } else {
9807 // Skip to the next ResolveInfo in the final list.
9808 it++;
9809 curt = null;
9810 }
9811 }
9812 }
9813 while (ir < NR) {
9814 if (receivers == null) {
9815 receivers = new ArrayList();
9816 }
9817 receivers.add(registeredReceivers.get(ir));
9818 ir++;
9819 }
9820
9821 if ((receivers != null && receivers.size() > 0)
9822 || resultTo != null) {
9823 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9824 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009825 receivers, resultTo, resultCode, resultData, map, ordered,
9826 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009827 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 TAG, "Enqueueing ordered broadcast " + r
9829 + ": prev had " + mOrderedBroadcasts.size());
9830 if (DEBUG_BROADCAST) {
9831 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009832 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009834 boolean replaced = false;
9835 if (replacePending) {
9836 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9837 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009838 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009839 "***** DROPPING ORDERED: " + intent);
9840 mOrderedBroadcasts.set(i, r);
9841 replaced = true;
9842 break;
9843 }
9844 }
9845 }
9846 if (!replaced) {
9847 mOrderedBroadcasts.add(r);
9848 scheduleBroadcastsLocked();
9849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009850 }
9851
9852 return BROADCAST_SUCCESS;
9853 }
9854
9855 public final int broadcastIntent(IApplicationThread caller,
9856 Intent intent, String resolvedType, IIntentReceiver resultTo,
9857 int resultCode, String resultData, Bundle map,
9858 String requiredPermission, boolean serialized, boolean sticky) {
9859 // Refuse possible leaked file descriptors
9860 if (intent != null && intent.hasFileDescriptors() == true) {
9861 throw new IllegalArgumentException("File descriptors passed in Intent");
9862 }
9863
9864 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009865 int flags = intent.getFlags();
9866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009867 if (!mSystemReady) {
9868 // if the caller really truly claims to know what they're doing, go
9869 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009870 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9871 intent = new Intent(intent);
9872 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9873 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009874 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 + " before boot completion");
9876 throw new IllegalStateException("Cannot broadcast before boot completed");
9877 }
9878 }
9879
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009880 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9881 throw new IllegalArgumentException(
9882 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9883 }
9884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9886 final int callingPid = Binder.getCallingPid();
9887 final int callingUid = Binder.getCallingUid();
9888 final long origId = Binder.clearCallingIdentity();
9889 int res = broadcastIntentLocked(callerApp,
9890 callerApp != null ? callerApp.info.packageName : null,
9891 intent, resolvedType, resultTo,
9892 resultCode, resultData, map, requiredPermission, serialized,
9893 sticky, callingPid, callingUid);
9894 Binder.restoreCallingIdentity(origId);
9895 return res;
9896 }
9897 }
9898
9899 int broadcastIntentInPackage(String packageName, int uid,
9900 Intent intent, String resolvedType, IIntentReceiver resultTo,
9901 int resultCode, String resultData, Bundle map,
9902 String requiredPermission, boolean serialized, boolean sticky) {
9903 synchronized(this) {
9904 final long origId = Binder.clearCallingIdentity();
9905 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9906 resultTo, resultCode, resultData, map, requiredPermission,
9907 serialized, sticky, -1, uid);
9908 Binder.restoreCallingIdentity(origId);
9909 return res;
9910 }
9911 }
9912
9913 public final void unbroadcastIntent(IApplicationThread caller,
9914 Intent intent) {
9915 // Refuse possible leaked file descriptors
9916 if (intent != null && intent.hasFileDescriptors() == true) {
9917 throw new IllegalArgumentException("File descriptors passed in Intent");
9918 }
9919
9920 synchronized(this) {
9921 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9922 != PackageManager.PERMISSION_GRANTED) {
9923 String msg = "Permission Denial: unbroadcastIntent() from pid="
9924 + Binder.getCallingPid()
9925 + ", uid=" + Binder.getCallingUid()
9926 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009927 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 throw new SecurityException(msg);
9929 }
9930 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9931 if (list != null) {
9932 int N = list.size();
9933 int i;
9934 for (i=0; i<N; i++) {
9935 if (intent.filterEquals(list.get(i))) {
9936 list.remove(i);
9937 break;
9938 }
9939 }
9940 }
9941 }
9942 }
9943
9944 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9945 String resultData, Bundle resultExtras, boolean resultAbort,
9946 boolean explicit) {
9947 if (mOrderedBroadcasts.size() == 0) {
9948 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009949 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009950 }
9951 return false;
9952 }
9953 BroadcastRecord r = mOrderedBroadcasts.get(0);
9954 if (r.receiver == null) {
9955 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009956 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 }
9958 return false;
9959 }
9960 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009961 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 return false;
9963 }
9964 int state = r.state;
9965 r.state = r.IDLE;
9966 if (state == r.IDLE) {
9967 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009968 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009969 }
9970 }
9971 r.receiver = null;
9972 r.intent.setComponent(null);
9973 if (r.curApp != null) {
9974 r.curApp.curReceiver = null;
9975 }
9976 if (r.curFilter != null) {
9977 r.curFilter.receiverList.curBroadcast = null;
9978 }
9979 r.curFilter = null;
9980 r.curApp = null;
9981 r.curComponent = null;
9982 r.curReceiver = null;
9983 mPendingBroadcast = null;
9984
9985 r.resultCode = resultCode;
9986 r.resultData = resultData;
9987 r.resultExtras = resultExtras;
9988 r.resultAbort = resultAbort;
9989
9990 // We will process the next receiver right now if this is finishing
9991 // an app receiver (which is always asynchronous) or after we have
9992 // come back from calling a receiver.
9993 return state == BroadcastRecord.APP_RECEIVE
9994 || state == BroadcastRecord.CALL_DONE_RECEIVE;
9995 }
9996
9997 public void finishReceiver(IBinder who, int resultCode, String resultData,
9998 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009999 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000
10001 // Refuse possible leaked file descriptors
10002 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10003 throw new IllegalArgumentException("File descriptors passed in Bundle");
10004 }
10005
10006 boolean doNext;
10007
10008 final long origId = Binder.clearCallingIdentity();
10009
10010 synchronized(this) {
10011 doNext = finishReceiverLocked(
10012 who, resultCode, resultData, resultExtras, resultAbort, true);
10013 }
10014
10015 if (doNext) {
10016 processNextBroadcast(false);
10017 }
10018 trimApplications();
10019
10020 Binder.restoreCallingIdentity(origId);
10021 }
10022
10023 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10024 if (r.nextReceiver > 0) {
10025 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10026 if (curReceiver instanceof BroadcastFilter) {
10027 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010028 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010029 System.identityHashCode(r),
10030 r.intent.getAction(),
10031 r.nextReceiver - 1,
10032 System.identityHashCode(bf));
10033 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010034 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 System.identityHashCode(r),
10036 r.intent.getAction(),
10037 r.nextReceiver - 1,
10038 ((ResolveInfo)curReceiver).toString());
10039 }
10040 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010041 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010043 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 System.identityHashCode(r),
10045 r.intent.getAction(),
10046 r.nextReceiver,
10047 "NONE");
10048 }
10049 }
10050
10051 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010052 ProcessRecord app = null;
10053 String anrMessage = null;
10054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 synchronized (this) {
10056 if (mOrderedBroadcasts.size() == 0) {
10057 return;
10058 }
10059 long now = SystemClock.uptimeMillis();
10060 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010061 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010062 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010063 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010064 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010066 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 return;
10068 }
10069
Joe Onorato8a9b2202010-02-26 18:56:32 -080010070 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010071 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010072 r.anrCount++;
10073
10074 // Current receiver has passed its expiration date.
10075 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010076 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 return;
10078 }
10079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010081 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 logBroadcastReceiverDiscard(r);
10083 if (curReceiver instanceof BroadcastFilter) {
10084 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10085 if (bf.receiverList.pid != 0
10086 && bf.receiverList.pid != MY_PID) {
10087 synchronized (this.mPidsSelfLocked) {
10088 app = this.mPidsSelfLocked.get(
10089 bf.receiverList.pid);
10090 }
10091 }
10092 } else {
10093 app = r.curApp;
10094 }
10095
10096 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010097 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 }
10099
10100 if (mPendingBroadcast == r) {
10101 mPendingBroadcast = null;
10102 }
10103
10104 // Move on to the next receiver.
10105 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10106 r.resultExtras, r.resultAbort, true);
10107 scheduleBroadcastsLocked();
10108 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010109
10110 if (anrMessage != null) {
10111 appNotResponding(app, null, null, anrMessage);
10112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113 }
10114
10115 private final void processCurBroadcastLocked(BroadcastRecord r,
10116 ProcessRecord app) throws RemoteException {
10117 if (app.thread == null) {
10118 throw new RemoteException();
10119 }
10120 r.receiver = app.thread.asBinder();
10121 r.curApp = app;
10122 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010123 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124
10125 // Tell the application to launch this receiver.
10126 r.intent.setComponent(r.curComponent);
10127
10128 boolean started = false;
10129 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010130 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010131 "Delivering to component " + r.curComponent
10132 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010133 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010134 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10135 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10136 started = true;
10137 } finally {
10138 if (!started) {
10139 r.receiver = null;
10140 r.curApp = null;
10141 app.curReceiver = null;
10142 }
10143 }
10144
10145 }
10146
10147 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010148 Intent intent, int resultCode, String data, Bundle extras,
10149 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 if (app != null && app.thread != null) {
10151 // If we have an app thread, do the call through that so it is
10152 // correctly ordered with other one-way calls.
10153 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010154 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010156 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010157 }
10158 }
10159
10160 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10161 BroadcastFilter filter, boolean ordered) {
10162 boolean skip = false;
10163 if (filter.requiredPermission != null) {
10164 int perm = checkComponentPermission(filter.requiredPermission,
10165 r.callingPid, r.callingUid, -1);
10166 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010167 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 + r.intent.toString()
10169 + " from " + r.callerPackage + " (pid="
10170 + r.callingPid + ", uid=" + r.callingUid + ")"
10171 + " requires " + filter.requiredPermission
10172 + " due to registered receiver " + filter);
10173 skip = true;
10174 }
10175 }
10176 if (r.requiredPermission != null) {
10177 int perm = checkComponentPermission(r.requiredPermission,
10178 filter.receiverList.pid, filter.receiverList.uid, -1);
10179 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010180 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010181 + r.intent.toString()
10182 + " to " + filter.receiverList.app
10183 + " (pid=" + filter.receiverList.pid
10184 + ", uid=" + filter.receiverList.uid + ")"
10185 + " requires " + r.requiredPermission
10186 + " due to sender " + r.callerPackage
10187 + " (uid " + r.callingUid + ")");
10188 skip = true;
10189 }
10190 }
10191
10192 if (!skip) {
10193 // If this is not being sent as an ordered broadcast, then we
10194 // don't want to touch the fields that keep track of the current
10195 // state of ordered broadcasts.
10196 if (ordered) {
10197 r.receiver = filter.receiverList.receiver.asBinder();
10198 r.curFilter = filter;
10199 filter.receiverList.curBroadcast = r;
10200 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010201 if (filter.receiverList.app != null) {
10202 // Bump hosting application to no longer be in background
10203 // scheduling class. Note that we can't do that if there
10204 // isn't an app... but we can only be in that case for
10205 // things that directly call the IActivityManager API, which
10206 // are already core system stuff so don't matter for this.
10207 r.curApp = filter.receiverList.app;
10208 filter.receiverList.app.curReceiver = r;
10209 updateOomAdjLocked();
10210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 }
10212 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010213 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010214 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010215 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010216 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 }
10218 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10219 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010220 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 if (ordered) {
10222 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10223 }
10224 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010225 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 if (ordered) {
10227 r.receiver = null;
10228 r.curFilter = null;
10229 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010230 if (filter.receiverList.app != null) {
10231 filter.receiverList.app.curReceiver = null;
10232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010233 }
10234 }
10235 }
10236 }
10237
Dianne Hackborn12527f92009-11-11 17:39:50 -080010238 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10239 if (r.callingUid < 0) {
10240 // This was from a registerReceiver() call; ignore it.
10241 return;
10242 }
10243 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10244 MAX_BROADCAST_HISTORY-1);
10245 r.finishTime = SystemClock.uptimeMillis();
10246 mBroadcastHistory[0] = r;
10247 }
10248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 private final void processNextBroadcast(boolean fromMsg) {
10250 synchronized(this) {
10251 BroadcastRecord r;
10252
Joe Onorato8a9b2202010-02-26 18:56:32 -080010253 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010255 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256
10257 updateCpuStats();
10258
10259 if (fromMsg) {
10260 mBroadcastsScheduled = false;
10261 }
10262
10263 // First, deliver any non-serialized broadcasts right away.
10264 while (mParallelBroadcasts.size() > 0) {
10265 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010266 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010267 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010268 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010269 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010270 for (int i=0; i<N; i++) {
10271 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010272 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010273 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 + target + ": " + r);
10275 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10276 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010277 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010278 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010279 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 }
10281
10282 // Now take care of the next serialized one...
10283
10284 // If we are waiting for a process to come up to handle the next
10285 // broadcast, then do nothing at this point. Just in case, we
10286 // check that the process we're waiting for still exists.
10287 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010288 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010289 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010290 + mPendingBroadcast.curApp);
10291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292
10293 boolean isDead;
10294 synchronized (mPidsSelfLocked) {
10295 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10296 }
10297 if (!isDead) {
10298 // It's still alive, so keep waiting
10299 return;
10300 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010301 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 + " died before responding to broadcast");
10303 mPendingBroadcast = null;
10304 }
10305 }
10306
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010307 boolean looped = false;
10308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 do {
10310 if (mOrderedBroadcasts.size() == 0) {
10311 // No more broadcasts pending, so all done!
10312 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010313 if (looped) {
10314 // If we had finished the last ordered broadcast, then
10315 // make sure all processes have correct oom and sched
10316 // adjustments.
10317 updateOomAdjLocked();
10318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 return;
10320 }
10321 r = mOrderedBroadcasts.get(0);
10322 boolean forceReceive = false;
10323
10324 // Ensure that even if something goes awry with the timeout
10325 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010326 // and continue to make progress.
10327 //
10328 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10329 // receivers don't get executed with with timeouts. They're intended for
10330 // one time heavy lifting after system upgrades and can take
10331 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010333 if (mSystemReady && r.dispatchTime > 0) {
10334 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010335 if ((numReceivers > 0) &&
10336 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010337 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 + " now=" + now
10339 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010340 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 + " intent=" + r.intent
10342 + " numReceivers=" + numReceivers
10343 + " nextReceiver=" + r.nextReceiver
10344 + " state=" + r.state);
10345 broadcastTimeout(); // forcibly finish this broadcast
10346 forceReceive = true;
10347 r.state = BroadcastRecord.IDLE;
10348 }
10349 }
10350
10351 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010352 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 "processNextBroadcast() called when not idle (state="
10354 + r.state + ")");
10355 return;
10356 }
10357
10358 if (r.receivers == null || r.nextReceiver >= numReceivers
10359 || r.resultAbort || forceReceive) {
10360 // No more receivers for this broadcast! Send the final
10361 // result if requested...
10362 if (r.resultTo != null) {
10363 try {
10364 if (DEBUG_BROADCAST) {
10365 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010366 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 + " seq=" + seq + " app=" + r.callerApp);
10368 }
10369 performReceive(r.callerApp, r.resultTo,
10370 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010371 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010373 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010374 }
10375 }
10376
Joe Onorato8a9b2202010-02-26 18:56:32 -080010377 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10379
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010381 + r);
10382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010384 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010385 mOrderedBroadcasts.remove(0);
10386 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010387 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 continue;
10389 }
10390 } while (r == null);
10391
10392 // Get the next receiver...
10393 int recIdx = r.nextReceiver++;
10394
10395 // Keep track of when this receiver started, and make sure there
10396 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010397 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010399 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400
Joe Onorato8a9b2202010-02-26 18:56:32 -080010401 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010402 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010403 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010405 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010407 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 }
10409
10410 Object nextReceiver = r.receivers.get(recIdx);
10411 if (nextReceiver instanceof BroadcastFilter) {
10412 // Simple case: this is a registered receiver who gets
10413 // a direct call.
10414 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010416 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417 + filter + ": " + r);
10418 deliverToRegisteredReceiver(r, filter, r.ordered);
10419 if (r.receiver == null || !r.ordered) {
10420 // The receiver has already finished, so schedule to
10421 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010422 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10423 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 r.state = BroadcastRecord.IDLE;
10425 scheduleBroadcastsLocked();
10426 }
10427 return;
10428 }
10429
10430 // Hard case: need to instantiate the receiver, possibly
10431 // starting its application process to host it.
10432
10433 ResolveInfo info =
10434 (ResolveInfo)nextReceiver;
10435
10436 boolean skip = false;
10437 int perm = checkComponentPermission(info.activityInfo.permission,
10438 r.callingPid, r.callingUid,
10439 info.activityInfo.exported
10440 ? -1 : info.activityInfo.applicationInfo.uid);
10441 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010442 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 + r.intent.toString()
10444 + " from " + r.callerPackage + " (pid=" + r.callingPid
10445 + ", uid=" + r.callingUid + ")"
10446 + " requires " + info.activityInfo.permission
10447 + " due to receiver " + info.activityInfo.packageName
10448 + "/" + info.activityInfo.name);
10449 skip = true;
10450 }
10451 if (r.callingUid != Process.SYSTEM_UID &&
10452 r.requiredPermission != null) {
10453 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010454 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010455 checkPermission(r.requiredPermission,
10456 info.activityInfo.applicationInfo.packageName);
10457 } catch (RemoteException e) {
10458 perm = PackageManager.PERMISSION_DENIED;
10459 }
10460 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010461 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 + r.intent + " to "
10463 + info.activityInfo.applicationInfo.packageName
10464 + " requires " + r.requiredPermission
10465 + " due to sender " + r.callerPackage
10466 + " (uid " + r.callingUid + ")");
10467 skip = true;
10468 }
10469 }
10470 if (r.curApp != null && r.curApp.crashing) {
10471 // If the target process is crashing, just skip it.
10472 skip = true;
10473 }
10474
10475 if (skip) {
10476 r.receiver = null;
10477 r.curFilter = null;
10478 r.state = BroadcastRecord.IDLE;
10479 scheduleBroadcastsLocked();
10480 return;
10481 }
10482
10483 r.state = BroadcastRecord.APP_RECEIVE;
10484 String targetProcess = info.activityInfo.processName;
10485 r.curComponent = new ComponentName(
10486 info.activityInfo.applicationInfo.packageName,
10487 info.activityInfo.name);
10488 r.curReceiver = info.activityInfo;
10489
10490 // Is this receiver's application already running?
10491 ProcessRecord app = getProcessRecordLocked(targetProcess,
10492 info.activityInfo.applicationInfo.uid);
10493 if (app != null && app.thread != null) {
10494 try {
10495 processCurBroadcastLocked(r, app);
10496 return;
10497 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010498 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010499 + r.curComponent, e);
10500 }
10501
10502 // If a dead object exception was thrown -- fall through to
10503 // restart the application.
10504 }
10505
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010506 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010507 if ((r.curApp=startProcessLocked(targetProcess,
10508 info.activityInfo.applicationInfo, true,
10509 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010510 "broadcast", r.curComponent,
10511 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10512 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010513 // Ah, this recipient is unavailable. Finish it if necessary,
10514 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 + info.activityInfo.applicationInfo.packageName + "/"
10517 + info.activityInfo.applicationInfo.uid + " for broadcast "
10518 + r.intent + ": process is bad");
10519 logBroadcastReceiverDiscard(r);
10520 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10521 r.resultExtras, r.resultAbort, true);
10522 scheduleBroadcastsLocked();
10523 r.state = BroadcastRecord.IDLE;
10524 return;
10525 }
10526
10527 mPendingBroadcast = r;
10528 }
10529 }
10530
10531 // =========================================================
10532 // INSTRUMENTATION
10533 // =========================================================
10534
10535 public boolean startInstrumentation(ComponentName className,
10536 String profileFile, int flags, Bundle arguments,
10537 IInstrumentationWatcher watcher) {
10538 // Refuse possible leaked file descriptors
10539 if (arguments != null && arguments.hasFileDescriptors()) {
10540 throw new IllegalArgumentException("File descriptors passed in Bundle");
10541 }
10542
10543 synchronized(this) {
10544 InstrumentationInfo ii = null;
10545 ApplicationInfo ai = null;
10546 try {
10547 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010548 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010549 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010550 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 } catch (PackageManager.NameNotFoundException e) {
10552 }
10553 if (ii == null) {
10554 reportStartInstrumentationFailure(watcher, className,
10555 "Unable to find instrumentation info for: " + className);
10556 return false;
10557 }
10558 if (ai == null) {
10559 reportStartInstrumentationFailure(watcher, className,
10560 "Unable to find instrumentation target package: " + ii.targetPackage);
10561 return false;
10562 }
10563
10564 int match = mContext.getPackageManager().checkSignatures(
10565 ii.targetPackage, ii.packageName);
10566 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10567 String msg = "Permission Denial: starting instrumentation "
10568 + className + " from pid="
10569 + Binder.getCallingPid()
10570 + ", uid=" + Binder.getCallingPid()
10571 + " not allowed because package " + ii.packageName
10572 + " does not have a signature matching the target "
10573 + ii.targetPackage;
10574 reportStartInstrumentationFailure(watcher, className, msg);
10575 throw new SecurityException(msg);
10576 }
10577
10578 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010579 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010580 ProcessRecord app = addAppLocked(ai);
10581 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010582 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 app.instrumentationProfileFile = profileFile;
10584 app.instrumentationArguments = arguments;
10585 app.instrumentationWatcher = watcher;
10586 app.instrumentationResultClass = className;
10587 Binder.restoreCallingIdentity(origId);
10588 }
10589
10590 return true;
10591 }
10592
10593 /**
10594 * Report errors that occur while attempting to start Instrumentation. Always writes the
10595 * error to the logs, but if somebody is watching, send the report there too. This enables
10596 * the "am" command to report errors with more information.
10597 *
10598 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10599 * @param cn The component name of the instrumentation.
10600 * @param report The error report.
10601 */
10602 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10603 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010604 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 try {
10606 if (watcher != null) {
10607 Bundle results = new Bundle();
10608 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10609 results.putString("Error", report);
10610 watcher.instrumentationStatus(cn, -1, results);
10611 }
10612 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010613 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 }
10615 }
10616
10617 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10618 if (app.instrumentationWatcher != null) {
10619 try {
10620 // NOTE: IInstrumentationWatcher *must* be oneway here
10621 app.instrumentationWatcher.instrumentationFinished(
10622 app.instrumentationClass,
10623 resultCode,
10624 results);
10625 } catch (RemoteException e) {
10626 }
10627 }
10628 app.instrumentationWatcher = null;
10629 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010630 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 app.instrumentationProfileFile = null;
10632 app.instrumentationArguments = null;
10633
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010634 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 }
10636
10637 public void finishInstrumentation(IApplicationThread target,
10638 int resultCode, Bundle results) {
10639 // Refuse possible leaked file descriptors
10640 if (results != null && results.hasFileDescriptors()) {
10641 throw new IllegalArgumentException("File descriptors passed in Intent");
10642 }
10643
10644 synchronized(this) {
10645 ProcessRecord app = getRecordForAppLocked(target);
10646 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010647 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 return;
10649 }
10650 final long origId = Binder.clearCallingIdentity();
10651 finishInstrumentationLocked(app, resultCode, results);
10652 Binder.restoreCallingIdentity(origId);
10653 }
10654 }
10655
10656 // =========================================================
10657 // CONFIGURATION
10658 // =========================================================
10659
10660 public ConfigurationInfo getDeviceConfigurationInfo() {
10661 ConfigurationInfo config = new ConfigurationInfo();
10662 synchronized (this) {
10663 config.reqTouchScreen = mConfiguration.touchscreen;
10664 config.reqKeyboardType = mConfiguration.keyboard;
10665 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010666 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10667 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010668 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10669 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010670 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10671 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010672 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10673 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010674 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010675 }
10676 return config;
10677 }
10678
10679 public Configuration getConfiguration() {
10680 Configuration ci;
10681 synchronized(this) {
10682 ci = new Configuration(mConfiguration);
10683 }
10684 return ci;
10685 }
10686
10687 public void updateConfiguration(Configuration values) {
10688 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10689 "updateConfiguration()");
10690
10691 synchronized(this) {
10692 if (values == null && mWindowManager != null) {
10693 // sentinel: fetch the current configuration from the window manager
10694 values = mWindowManager.computeNewConfiguration();
10695 }
10696
10697 final long origId = Binder.clearCallingIdentity();
10698 updateConfigurationLocked(values, null);
10699 Binder.restoreCallingIdentity(origId);
10700 }
10701 }
10702
10703 /**
10704 * Do either or both things: (1) change the current configuration, and (2)
10705 * make sure the given activity is running with the (now) current
10706 * configuration. Returns true if the activity has been left running, or
10707 * false if <var>starting</var> is being destroyed to match the new
10708 * configuration.
10709 */
10710 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010711 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 int changes = 0;
10713
10714 boolean kept = true;
10715
10716 if (values != null) {
10717 Configuration newConfig = new Configuration(mConfiguration);
10718 changes = newConfig.updateFrom(values);
10719 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010720 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010721 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 }
10723
Doug Zongker2bec3d42009-12-04 12:52:44 -080010724 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725
10726 if (values.locale != null) {
10727 saveLocaleLocked(values.locale,
10728 !values.locale.equals(mConfiguration.locale),
10729 values.userSetLocale);
10730 }
10731
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010732 mConfigurationSeq++;
10733 if (mConfigurationSeq <= 0) {
10734 mConfigurationSeq = 1;
10735 }
10736 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010738 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010739
10740 AttributeCache ac = AttributeCache.instance();
10741 if (ac != null) {
10742 ac.updateConfiguration(mConfiguration);
10743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010744
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010745 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10746 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10747 msg.obj = new Configuration(mConfiguration);
10748 mHandler.sendMessage(msg);
10749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010751 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10752 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 try {
10754 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010755 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010756 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 app.thread.scheduleConfigurationChanged(mConfiguration);
10758 }
10759 } catch (Exception e) {
10760 }
10761 }
10762 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010763 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10764 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10766 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010767 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10768 broadcastIntentLocked(null, null,
10769 new Intent(Intent.ACTION_LOCALE_CHANGED),
10770 null, null, 0, null, null,
10771 null, false, false, MY_PID, Process.SYSTEM_UID);
10772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 }
10774 }
10775
10776 if (changes != 0 && starting == null) {
10777 // If the configuration changed, and the caller is not already
10778 // in the process of starting an activity, then find the top
10779 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010780 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 }
10782
10783 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010784 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 if (kept) {
10786 // If this didn't result in the starting activity being
10787 // destroyed, then we need to make sure at this point that all
10788 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010789 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010790 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010791 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 }
10793 }
10794
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010795 if (values != null && mWindowManager != null) {
10796 mWindowManager.setNewConfiguration(mConfiguration);
10797 }
10798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 return kept;
10800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801
10802 /**
10803 * Save the locale. You must be inside a synchronized (this) block.
10804 */
10805 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10806 if(isDiff) {
10807 SystemProperties.set("user.language", l.getLanguage());
10808 SystemProperties.set("user.region", l.getCountry());
10809 }
10810
10811 if(isPersist) {
10812 SystemProperties.set("persist.sys.language", l.getLanguage());
10813 SystemProperties.set("persist.sys.country", l.getCountry());
10814 SystemProperties.set("persist.sys.localevar", l.getVariant());
10815 }
10816 }
10817
10818 // =========================================================
10819 // LIFETIME MANAGEMENT
10820 // =========================================================
10821
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010822 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10823 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010825 // This adjustment has already been computed. If we are calling
10826 // from the top, we may have already computed our adjustment with
10827 // an earlier hidden adjustment that isn't really for us... if
10828 // so, use the new hidden adjustment.
10829 if (!recursed && app.hidden) {
10830 app.curAdj = hiddenAdj;
10831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 return app.curAdj;
10833 }
10834
10835 if (app.thread == null) {
10836 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010837 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010838 return (app.curAdj=EMPTY_APP_ADJ);
10839 }
10840
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010841 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10842 // The max adjustment doesn't allow this app to be anything
10843 // below foreground, so it is not worth doing work for it.
10844 app.adjType = "fixed";
10845 app.adjSeq = mAdjSeq;
10846 app.curRawAdj = app.maxAdj;
10847 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10848 return (app.curAdj=app.maxAdj);
10849 }
10850
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010851 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010852 app.adjSource = null;
10853 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010854 app.empty = false;
10855 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010856
The Android Open Source Project4df24232009-03-05 14:34:35 -080010857 // Determine the importance of the process, starting with most
10858 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010860 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010861 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010862 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010863 // The last app on the list is the foreground app.
10864 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010865 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010866 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010867 } else if (app.instrumentationClass != null) {
10868 // Don't want to kill running instrumentation.
10869 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010870 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010871 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010872 } else if (app.persistentActivities > 0) {
10873 // Special persistent activities... shouldn't be used these days.
10874 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010875 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010876 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 } else if (app.curReceiver != null ||
10878 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10879 // An app that is currently receiving a broadcast also
10880 // counts as being in the foreground.
10881 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010882 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010883 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 } else if (app.executingServices.size() > 0) {
10885 // An app that is currently executing a service callback also
10886 // counts as being in the foreground.
10887 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010888 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010889 app.adjType = "exec-service";
10890 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010892 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010893 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010894 app.adjType = "foreground-service";
10895 } else if (app.forcingToForeground != null) {
10896 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010897 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010898 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010899 app.adjType = "force-foreground";
10900 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010901 } else if (app == mHeavyWeightProcess) {
10902 // We don't want to kill the current heavy-weight process.
10903 adj = HEAVY_WEIGHT_APP_ADJ;
10904 schedGroup = Process.THREAD_GROUP_DEFAULT;
10905 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010906 } else if (app == mHomeProcess) {
10907 // This process is hosting what we currently consider to be the
10908 // home app, so we don't want to let it go into the background.
10909 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010910 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010911 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010912 } else if ((N=app.activities.size()) != 0) {
10913 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010914 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010916 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010917 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010918 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010920 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010922 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010924 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010925 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 break;
10927 }
10928 }
10929 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010930 // A very not-needed process. If this is lower in the lru list,
10931 // we will push it in to the empty bucket.
10932 app.hidden = true;
10933 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010934 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010935 adj = hiddenAdj;
10936 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 }
10938
Joe Onorato8a9b2202010-02-26 18:56:32 -080010939 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010940
The Android Open Source Project4df24232009-03-05 14:34:35 -080010941 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 // there are applications dependent on our services or providers, but
10943 // this gives us a baseline and makes sure we don't get into an
10944 // infinite recursion.
10945 app.adjSeq = mAdjSeq;
10946 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947
Christopher Tate6fa95972009-06-05 18:43:55 -070010948 if (mBackupTarget != null && app == mBackupTarget.app) {
10949 // If possible we want to avoid killing apps while they're being backed up
10950 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010951 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010952 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010953 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010954 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010955 }
10956 }
10957
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010958 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10959 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 final long now = SystemClock.uptimeMillis();
10961 // This process is more important if the top activity is
10962 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010963 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010965 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 if (s.startRequested) {
10967 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
10968 // This service has seen some activity within
10969 // recent memory, so we will keep its process ahead
10970 // of the background processes.
10971 if (adj > SECONDARY_SERVER_ADJ) {
10972 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010973 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010974 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010975 }
10976 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080010977 // If we have let the service slide into the background
10978 // state, still have some text describing what it is doing
10979 // even though the service no longer has an impact.
10980 if (adj > SECONDARY_SERVER_ADJ) {
10981 app.adjType = "started-bg-services";
10982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010984 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
10985 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 Iterator<ConnectionRecord> kt
10987 = s.connections.values().iterator();
10988 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
10989 // XXX should compute this based on the max of
10990 // all connected clients.
10991 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070010992 if (cr.binding.client == app) {
10993 // Binding to ourself is not interesting.
10994 continue;
10995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10997 ProcessRecord client = cr.binding.client;
10998 int myHiddenAdj = hiddenAdj;
10999 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011000 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 myHiddenAdj = client.hiddenAdj;
11002 } else {
11003 myHiddenAdj = VISIBLE_APP_ADJ;
11004 }
11005 }
11006 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011007 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011009 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011011 if (!client.hidden) {
11012 app.hidden = false;
11013 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011014 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011015 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11016 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011017 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011018 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011020 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11021 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11022 schedGroup = Process.THREAD_GROUP_DEFAULT;
11023 }
11024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011026 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011028 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 //}
11030 if (a != null && adj > FOREGROUND_APP_ADJ &&
11031 (a.state == ActivityState.RESUMED
11032 || a.state == ActivityState.PAUSING)) {
11033 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011034 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011035 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011036 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011037 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11038 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011039 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011040 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 }
11042 }
11043 }
11044 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011045
11046 // Finally, f this process has active services running in it, we
11047 // would like to avoid killing it unless it would prevent the current
11048 // application from running. By default we put the process in
11049 // with the rest of the background processes; as we scan through
11050 // its services we may bump it up from there.
11051 if (adj > hiddenAdj) {
11052 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011053 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011054 app.adjType = "bg-services";
11055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 }
11057
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011058 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11059 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011060 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011061 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11062 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011063 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 if (cpr.clients.size() != 0) {
11065 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11066 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11067 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011068 if (client == app) {
11069 // Being our own client is not interesting.
11070 continue;
11071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 int myHiddenAdj = hiddenAdj;
11073 if (myHiddenAdj > client.hiddenAdj) {
11074 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11075 myHiddenAdj = client.hiddenAdj;
11076 } else {
11077 myHiddenAdj = FOREGROUND_APP_ADJ;
11078 }
11079 }
11080 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011081 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011082 if (adj > clientAdj) {
11083 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011084 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011085 if (!client.hidden) {
11086 app.hidden = false;
11087 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011088 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011089 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11090 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011091 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011092 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011094 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11095 schedGroup = Process.THREAD_GROUP_DEFAULT;
11096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 }
11098 }
11099 // If the provider has external (non-framework) process
11100 // dependencies, ensure that its adjustment is at least
11101 // FOREGROUND_APP_ADJ.
11102 if (cpr.externals != 0) {
11103 if (adj > FOREGROUND_APP_ADJ) {
11104 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011105 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011106 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011107 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011108 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 }
11110 }
11111 }
11112 }
11113
11114 app.curRawAdj = adj;
11115
Joe Onorato8a9b2202010-02-26 18:56:32 -080011116 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11118 if (adj > app.maxAdj) {
11119 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011120 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011121 schedGroup = Process.THREAD_GROUP_DEFAULT;
11122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 }
11124
11125 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011126 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 return adj;
11129 }
11130
11131 /**
11132 * Ask a given process to GC right now.
11133 */
11134 final void performAppGcLocked(ProcessRecord app) {
11135 try {
11136 app.lastRequestedGc = SystemClock.uptimeMillis();
11137 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011138 if (app.reportLowMemory) {
11139 app.reportLowMemory = false;
11140 app.thread.scheduleLowMemory();
11141 } else {
11142 app.thread.processInBackground();
11143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 }
11145 } catch (Exception e) {
11146 // whatever.
11147 }
11148 }
11149
11150 /**
11151 * Returns true if things are idle enough to perform GCs.
11152 */
Josh Bartel7f208742010-02-25 11:01:44 -060011153 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 return mParallelBroadcasts.size() == 0
11155 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011156 && (mSleeping || (mMainStack.mResumedActivity != null &&
11157 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 }
11159
11160 /**
11161 * Perform GCs on all processes that are waiting for it, but only
11162 * if things are idle.
11163 */
11164 final void performAppGcsLocked() {
11165 final int N = mProcessesToGc.size();
11166 if (N <= 0) {
11167 return;
11168 }
Josh Bartel7f208742010-02-25 11:01:44 -060011169 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 while (mProcessesToGc.size() > 0) {
11171 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011172 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011173 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11174 <= SystemClock.uptimeMillis()) {
11175 // To avoid spamming the system, we will GC processes one
11176 // at a time, waiting a few seconds between each.
11177 performAppGcLocked(proc);
11178 scheduleAppGcsLocked();
11179 return;
11180 } else {
11181 // It hasn't been long enough since we last GCed this
11182 // process... put it in the list to wait for its time.
11183 addProcessToGcListLocked(proc);
11184 break;
11185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 }
11187 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011188
11189 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011190 }
11191 }
11192
11193 /**
11194 * If all looks good, perform GCs on all processes waiting for them.
11195 */
11196 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011197 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 performAppGcsLocked();
11199 return;
11200 }
11201 // Still not idle, wait some more.
11202 scheduleAppGcsLocked();
11203 }
11204
11205 /**
11206 * Schedule the execution of all pending app GCs.
11207 */
11208 final void scheduleAppGcsLocked() {
11209 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011210
11211 if (mProcessesToGc.size() > 0) {
11212 // Schedule a GC for the time to the next process.
11213 ProcessRecord proc = mProcessesToGc.get(0);
11214 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11215
11216 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11217 long now = SystemClock.uptimeMillis();
11218 if (when < (now+GC_TIMEOUT)) {
11219 when = now + GC_TIMEOUT;
11220 }
11221 mHandler.sendMessageAtTime(msg, when);
11222 }
11223 }
11224
11225 /**
11226 * Add a process to the array of processes waiting to be GCed. Keeps the
11227 * list in sorted order by the last GC time. The process can't already be
11228 * on the list.
11229 */
11230 final void addProcessToGcListLocked(ProcessRecord proc) {
11231 boolean added = false;
11232 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11233 if (mProcessesToGc.get(i).lastRequestedGc <
11234 proc.lastRequestedGc) {
11235 added = true;
11236 mProcessesToGc.add(i+1, proc);
11237 break;
11238 }
11239 }
11240 if (!added) {
11241 mProcessesToGc.add(0, proc);
11242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 }
11244
11245 /**
11246 * Set up to ask a process to GC itself. This will either do it
11247 * immediately, or put it on the list of processes to gc the next
11248 * time things are idle.
11249 */
11250 final void scheduleAppGcLocked(ProcessRecord app) {
11251 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011252 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253 return;
11254 }
11255 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011256 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 scheduleAppGcsLocked();
11258 }
11259 }
11260
11261 private final boolean updateOomAdjLocked(
11262 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11263 app.hiddenAdj = hiddenAdj;
11264
11265 if (app.thread == null) {
11266 return true;
11267 }
11268
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011269 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011271 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 if (app.curRawAdj != app.setRawAdj) {
11273 if (app.curRawAdj > FOREGROUND_APP_ADJ
11274 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11275 // If this app is transitioning from foreground to
11276 // non-foreground, have it do a gc.
11277 scheduleAppGcLocked(app);
11278 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11279 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11280 // Likewise do a gc when an app is moving in to the
11281 // background (such as a service stopping).
11282 scheduleAppGcLocked(app);
11283 }
11284 app.setRawAdj = app.curRawAdj;
11285 }
11286 if (adj != app.setAdj) {
11287 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011288 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 TAG, "Set app " + app.processName +
11290 " oom adj to " + adj);
11291 app.setAdj = adj;
11292 } else {
11293 return false;
11294 }
11295 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011296 if (app.setSchedGroup != app.curSchedGroup) {
11297 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011298 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011299 "Setting process group of " + app.processName
11300 + " to " + app.curSchedGroup);
11301 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011302 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011303 try {
11304 Process.setProcessGroup(app.pid, app.curSchedGroup);
11305 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011306 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011307 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011308 e.printStackTrace();
11309 } finally {
11310 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011311 }
11312 }
11313 if (false) {
11314 if (app.thread != null) {
11315 try {
11316 app.thread.setSchedulingGroup(app.curSchedGroup);
11317 } catch (RemoteException e) {
11318 }
11319 }
11320 }
11321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 }
11323
11324 return true;
11325 }
11326
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011327 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011328 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011330 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011332 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 }
11334 }
11335 return resumedActivity;
11336 }
11337
11338 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011339 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011340 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11341 int curAdj = app.curAdj;
11342 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11343 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11344
11345 mAdjSeq++;
11346
11347 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11348 if (res) {
11349 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11350 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11351 if (nowHidden != wasHidden) {
11352 // Changed to/from hidden state, so apps after it in the LRU
11353 // list may also be changed.
11354 updateOomAdjLocked();
11355 }
11356 }
11357 return res;
11358 }
11359
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011360 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011362 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11364
11365 if (false) {
11366 RuntimeException e = new RuntimeException();
11367 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011368 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 }
11370
11371 mAdjSeq++;
11372
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011373 // Let's determine how many processes we have running vs.
11374 // how many slots we have for background processes; we may want
11375 // to put multiple processes in a slot of there are enough of
11376 // them.
11377 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11378 int factor = (mLruProcesses.size()-4)/numSlots;
11379 if (factor < 1) factor = 1;
11380 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011381 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011383 // First try updating the OOM adjustment for each of the
11384 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011385 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011386 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11387 while (i > 0) {
11388 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011389 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011390 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011392 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011394 step++;
11395 if (step >= factor) {
11396 step = 0;
11397 curHiddenAdj++;
11398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011400 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011401 if (!app.killedBackground) {
11402 numHidden++;
11403 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011404 Slog.i(TAG, "No longer want " + app.processName
11405 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011406 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11407 app.processName, app.setAdj, "too many background");
11408 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011409 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011410 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011411 }
11412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011413 } else {
11414 didOomAdj = false;
11415 }
11416 }
11417
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011418 // If we return false, we will fall back on killing processes to
11419 // have a fixed limit. Do this if a limit has been requested; else
11420 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11422 }
11423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011424 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011425 synchronized (this) {
11426 int i;
11427
11428 // First remove any unused application processes whose package
11429 // has been removed.
11430 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11431 final ProcessRecord app = mRemovedProcesses.get(i);
11432 if (app.activities.size() == 0
11433 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011434 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011435 TAG, "Exiting empty application process "
11436 + app.processName + " ("
11437 + (app.thread != null ? app.thread.asBinder() : null)
11438 + ")\n");
11439 if (app.pid > 0 && app.pid != MY_PID) {
11440 Process.killProcess(app.pid);
11441 } else {
11442 try {
11443 app.thread.scheduleExit();
11444 } catch (Exception e) {
11445 // Ignore exceptions.
11446 }
11447 }
11448 cleanUpApplicationRecordLocked(app, false, -1);
11449 mRemovedProcesses.remove(i);
11450
11451 if (app.persistent) {
11452 if (app.persistent) {
11453 addAppLocked(app.info);
11454 }
11455 }
11456 }
11457 }
11458
11459 // Now try updating the OOM adjustment for each of the
11460 // application processes based on their current state.
11461 // If the setOomAdj() API is not supported, then go with our
11462 // back-up plan...
11463 if (!updateOomAdjLocked()) {
11464
11465 // Count how many processes are running services.
11466 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011467 for (i=mLruProcesses.size()-1; i>=0; i--) {
11468 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469
11470 if (app.persistent || app.services.size() != 0
11471 || app.curReceiver != null
11472 || app.persistentActivities > 0) {
11473 // Don't count processes holding services against our
11474 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011475 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 TAG, "Not trimming app " + app + " with services: "
11477 + app.services);
11478 numServiceProcs++;
11479 }
11480 }
11481
11482 int curMaxProcs = mProcessLimit;
11483 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11484 if (mAlwaysFinishActivities) {
11485 curMaxProcs = 1;
11486 }
11487 curMaxProcs += numServiceProcs;
11488
11489 // Quit as many processes as we can to get down to the desired
11490 // process count. First remove any processes that no longer
11491 // have activites running in them.
11492 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011493 i<mLruProcesses.size()
11494 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011496 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011497 // Quit an application only if it is not currently
11498 // running any activities.
11499 if (!app.persistent && app.activities.size() == 0
11500 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011501 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011502 TAG, "Exiting empty application process "
11503 + app.processName + " ("
11504 + (app.thread != null ? app.thread.asBinder() : null)
11505 + ")\n");
11506 if (app.pid > 0 && app.pid != MY_PID) {
11507 Process.killProcess(app.pid);
11508 } else {
11509 try {
11510 app.thread.scheduleExit();
11511 } catch (Exception e) {
11512 // Ignore exceptions.
11513 }
11514 }
11515 // todo: For now we assume the application is not buggy
11516 // or evil, and will quit as a result of our request.
11517 // Eventually we need to drive this off of the death
11518 // notification, and kill the process if it takes too long.
11519 cleanUpApplicationRecordLocked(app, false, i);
11520 i--;
11521 }
11522 }
11523
11524 // If we still have too many processes, now from the least
11525 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011526 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011527 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011528 " of " + curMaxProcs + " processes");
11529 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011530 i<mLruProcesses.size()
11531 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011533 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 // Quit the application only if we have a state saved for
11535 // all of its activities.
11536 boolean canQuit = !app.persistent && app.curReceiver == null
11537 && app.services.size() == 0
11538 && app.persistentActivities == 0;
11539 int NUMA = app.activities.size();
11540 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011541 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 TAG, "Looking to quit " + app.processName);
11543 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011544 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011545 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 TAG, " " + r.intent.getComponent().flattenToShortString()
11547 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11548 canQuit = (r.haveState || !r.stateNotNeeded)
11549 && !r.visible && r.stopped;
11550 }
11551 if (canQuit) {
11552 // Finish all of the activities, and then the app itself.
11553 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011554 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011555 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011556 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 }
11558 r.resultTo = null;
11559 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011560 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011561 + app.processName + " ("
11562 + (app.thread != null ? app.thread.asBinder() : null)
11563 + ")\n");
11564 if (app.pid > 0 && app.pid != MY_PID) {
11565 Process.killProcess(app.pid);
11566 } else {
11567 try {
11568 app.thread.scheduleExit();
11569 } catch (Exception e) {
11570 // Ignore exceptions.
11571 }
11572 }
11573 // todo: For now we assume the application is not buggy
11574 // or evil, and will quit as a result of our request.
11575 // Eventually we need to drive this off of the death
11576 // notification, and kill the process if it takes too long.
11577 cleanUpApplicationRecordLocked(app, false, i);
11578 i--;
11579 //dump();
11580 }
11581 }
11582
11583 }
11584
11585 int curMaxActivities = MAX_ACTIVITIES;
11586 if (mAlwaysFinishActivities) {
11587 curMaxActivities = 1;
11588 }
11589
11590 // Finally, if there are too many activities now running, try to
11591 // finish as many as we can to get back down to the limit.
11592 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011593 i<mMainStack.mLRUActivities.size()
11594 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011596 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011597 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598
11599 // We can finish this one if we have its icicle saved and
11600 // it is not persistent.
11601 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11602 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011603 final int origSize = mMainStack.mLRUActivities.size();
11604 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011605
11606 // This will remove it from the LRU list, so keep
11607 // our index at the same value. Note that this check to
11608 // see if the size changes is just paranoia -- if
11609 // something unexpected happens, we don't want to end up
11610 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011611 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 i--;
11613 }
11614 }
11615 }
11616 }
11617 }
11618
11619 /** This method sends the specified signal to each of the persistent apps */
11620 public void signalPersistentProcesses(int sig) throws RemoteException {
11621 if (sig != Process.SIGNAL_USR1) {
11622 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11623 }
11624
11625 synchronized (this) {
11626 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11627 != PackageManager.PERMISSION_GRANTED) {
11628 throw new SecurityException("Requires permission "
11629 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11630 }
11631
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011632 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11633 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 if (r.thread != null && r.persistent) {
11635 Process.sendSignal(r.pid, sig);
11636 }
11637 }
11638 }
11639 }
11640
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011641 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011642 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011643
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011644 try {
11645 synchronized (this) {
11646 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11647 // its own permission.
11648 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11649 != PackageManager.PERMISSION_GRANTED) {
11650 throw new SecurityException("Requires permission "
11651 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011652 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011653
11654 if (start && fd == null) {
11655 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011656 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011657
11658 ProcessRecord proc = null;
11659 try {
11660 int pid = Integer.parseInt(process);
11661 synchronized (mPidsSelfLocked) {
11662 proc = mPidsSelfLocked.get(pid);
11663 }
11664 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011665 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011666
11667 if (proc == null) {
11668 HashMap<String, SparseArray<ProcessRecord>> all
11669 = mProcessNames.getMap();
11670 SparseArray<ProcessRecord> procs = all.get(process);
11671 if (procs != null && procs.size() > 0) {
11672 proc = procs.valueAt(0);
11673 }
11674 }
11675
11676 if (proc == null || proc.thread == null) {
11677 throw new IllegalArgumentException("Unknown process: " + process);
11678 }
11679
11680 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11681 if (isSecure) {
11682 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11683 throw new SecurityException("Process not debuggable: " + proc);
11684 }
11685 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011686
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011687 proc.thread.profilerControl(start, path, fd);
11688 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011689 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011690 }
11691 } catch (RemoteException e) {
11692 throw new IllegalStateException("Process disappeared");
11693 } finally {
11694 if (fd != null) {
11695 try {
11696 fd.close();
11697 } catch (IOException e) {
11698 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011699 }
11700 }
11701 }
11702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011703 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11704 public void monitor() {
11705 synchronized (this) { }
11706 }
11707}